2021-06-18 17:50:14 +00:00
// _ _ _ ____ _ _____
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
// |
// Copyright 2015-2021 Łukasz "JustArchi" Domeradzki
// Contact: JustArchi@JustArchi.net
// |
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// |
// http://www.apache.org/licenses/LICENSE-2.0
// |
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using Microsoft.VisualStudio.TestTools.UnitTesting ;
using static ArchiSteamFarm . Steam . Integration . SteamChatMessage ;
2021-11-10 20:23:24 +00:00
namespace ArchiSteamFarm.Tests ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[TestClass]
public sealed class SteamChatMessage {
[TestMethod]
public async Task CanSplitEvenWithStupidlyLongPrefix ( ) {
string prefix = new ( 'x' , MaxMessagePrefixBytes ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
const string emoji = "😎" ;
const string message = emoji + emoji + emoji + emoji ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message , prefix , true ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 4 , output . Count ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( prefix + emoji + ContinuationCharacter , output [ 0 ] ) ;
Assert . AreEqual ( prefix + ContinuationCharacter + emoji + ContinuationCharacter , output [ 1 ] ) ;
Assert . AreEqual ( prefix + ContinuationCharacter + emoji + ContinuationCharacter , output [ 2 ] ) ;
Assert . AreEqual ( prefix + ContinuationCharacter + emoji , output [ 3 ] ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[TestMethod]
public void ContinuationCharacterSizeIsProperlyCalculated ( ) = > Assert . AreEqual ( ContinuationCharacterBytes , Encoding . UTF8 . GetByteCount ( ContinuationCharacter . ToString ( ) ) ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[TestMethod]
public async Task DoesntSkipEmptyNewlines ( ) {
string message = $"asdf{Environment.NewLine}{Environment.NewLine}asdf" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 1 , output . Count ) ;
Assert . AreEqual ( message , output . First ( ) ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[DataRow(false)]
[DataRow(true)]
[DataTestMethod]
public async Task DoesntSplitInTheMiddleOfMultiByteChar ( bool isAccountLimited ) {
int maxMessageBytes = isAccountLimited ? MaxMessageBytesForLimitedAccounts : MaxMessageBytesForUnlimitedAccounts ;
int longLineLength = maxMessageBytes - ReservedContinuationMessageBytes ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
const string emoji = "😎" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
string longSequence = new ( 'a' , longLineLength - 1 ) ;
string message = longSequence + emoji ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message , isAccountLimited : isAccountLimited ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 2 , output . Count ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( longSequence + ContinuationCharacter , output [ 0 ] ) ;
Assert . AreEqual ( ContinuationCharacter + emoji , output [ 1 ] ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[TestMethod]
public async Task DoesntSplitJustBecauseOfLastEscapableCharacter ( ) {
const string message = "abcdef[" ;
const string escapedMessage = @"abcdef\[" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 1 , output . Count ) ;
Assert . AreEqual ( escapedMessage , output . First ( ) ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[DataRow(false)]
[DataRow(true)]
[DataTestMethod]
public async Task DoesntSplitOnBackslashNotUsedForEscaping ( bool isAccountLimited ) {
int maxMessageBytes = isAccountLimited ? MaxMessageBytesForLimitedAccounts : MaxMessageBytesForUnlimitedAccounts ;
int longLineLength = maxMessageBytes - ReservedContinuationMessageBytes ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
string longLine = new ( 'a' , longLineLength - 2 ) ;
string message = $@"{longLine}\" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message , isAccountLimited : isAccountLimited ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 1 , output . Count ) ;
Assert . AreEqual ( $@"{message}\" , output . First ( ) ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[DataRow(false)]
[DataRow(true)]
[DataTestMethod]
public async Task DoesntSplitOnEscapeCharacter ( bool isAccountLimited ) {
int maxMessageBytes = isAccountLimited ? MaxMessageBytesForLimitedAccounts : MaxMessageBytesForUnlimitedAccounts ;
int longLineLength = maxMessageBytes - ReservedContinuationMessageBytes ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
string longLine = new ( 'a' , longLineLength - 1 ) ;
string message = $"{longLine}[" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message , isAccountLimited : isAccountLimited ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 2 , output . Count ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( longLine + ContinuationCharacter , output [ 0 ] ) ;
Assert . AreEqual ( $@"{ContinuationCharacter}\[" , output [ 1 ] ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[TestMethod]
public async Task NoNeedForAnySplittingWithNewlines ( ) {
string message = $"abcdef{Environment.NewLine}ghijkl{Environment.NewLine}mnopqr" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 1 , output . Count ) ;
Assert . AreEqual ( message , output . First ( ) ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[TestMethod]
public async Task NoNeedForAnySplittingWithoutNewlines ( ) {
const string message = "abcdef" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 1 , output . Count ) ;
Assert . AreEqual ( message , output . First ( ) ) ;
}
2021-06-30 11:10:05 +00:00
2021-11-10 20:23:24 +00:00
[TestMethod]
public void ParagraphCharacterSizeIsLessOrEqualToContinuationCharacterSize ( ) = > Assert . IsTrue ( ContinuationCharacterBytes > = Encoding . UTF8 . GetByteCount ( ParagraphCharacter . ToString ( ) ) ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[TestMethod]
public async Task ProperlyEscapesCharacters ( ) {
const string message = @"[b]bold[/b] \n" ;
const string escapedMessage = @"\[b]bold\[/b] \\n" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 1 , output . Count ) ;
Assert . AreEqual ( escapedMessage , output . First ( ) ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[TestMethod]
public async Task ProperlyEscapesSteamMessagePrefix ( ) {
const string prefix = "/pre []" ;
const string escapedPrefix = @"/pre \[]" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
const string message = "asdf" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message , prefix ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 1 , output . Count ) ;
Assert . AreEqual ( escapedPrefix + message , output . First ( ) ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[DataRow(false)]
[DataRow(true)]
[DataTestMethod]
public async Task ProperlySplitsLongSingleLine ( bool isAccountLimited ) {
int maxMessageBytes = isAccountLimited ? MaxMessageBytesForLimitedAccounts : MaxMessageBytesForUnlimitedAccounts ;
int longLineLength = maxMessageBytes - ReservedContinuationMessageBytes ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
string longLine = new ( 'a' , longLineLength ) ;
string message = longLine + longLine + longLine + longLine ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message , isAccountLimited : isAccountLimited ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 4 , output . Count ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( longLine + ContinuationCharacter , output [ 0 ] ) ;
Assert . AreEqual ( ContinuationCharacter + longLine + ContinuationCharacter , output [ 1 ] ) ;
Assert . AreEqual ( ContinuationCharacter + longLine + ContinuationCharacter , output [ 2 ] ) ;
Assert . AreEqual ( ContinuationCharacter + longLine , output [ 3 ] ) ;
}
[TestMethod]
public void ReservedSizeForEscapingIsProperlyCalculated ( ) = > Assert . AreEqual ( ReservedEscapeMessageBytes , Encoding . UTF8 . GetByteCount ( @"\" ) + 4 ) ; // Maximum amount of bytes per single UTF-8 character is 4, not 6 as from Encoding.UTF8.GetMaxByteCount(1)
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[TestMethod]
public async Task RyzhehvostInitialTestForSplitting ( ) {
const string prefix = "/me " ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
const string message = @ "<XLimited5> Уже имеет: app/1493800 | Aircraft Carrier Survival: Prolouge
2021-06-18 17:50:14 +00:00
< XLimited5 > У ж е и м е е т : app / 349520 | Armillo
< XLimited5 > У ж е и м е е т : app / 346330 | BrainBread 2
< XLimited5 > У ж е и м е е т : app / 1086690 | C - War 2
< XLimited5 > У ж е и м е е т : app / 730 | Counter - Strike : Global Offensive
< XLimited5 > У ж е и м е е т : app / 838380 | DEAD OR ALIVE 6
< XLimited5 > У ж е и м е е т : app / 582890 | Estranged : The Departure
< XLimited5 > У ж е и м е е т : app / 331470 | Everlasting Summer
< XLimited5 > У ж е и м е е т : app / 1078000 | Gamecraft
< XLimited5 > У ж е и м е е т : app / 266310 | GameGuru
< XLimited5 > У ж е и м е е т : app / 275390 | Guacamelee ! Super Turbo Championship Edition
< XLimited5 > У ж е и м е е т : app / 627690 | Idle Champions of the Forgotten Realms
< XLimited5 > У ж е и м е е т : app / 1048540 | Kao the Kangaroo : Round 2
< XLimited5 > У ж е и м е е т : app / 370910 | Kathy Rain
< XLimited5 > У ж е и м е е т : app / 343710 | KHOLAT
< XLimited5 > У ж е и м е е т : app / 253900 | Knights and Merchants
< XLimited5 > У ж е и м е е т : app / 224260 | No More Room in Hell
< XLimited5 > У ж е и м е е т : app / 343360 | Particula
< XLimited5 > У ж е и м е е т : app / 237870 | Planet Explorers
< XLimited5 > У ж е и м е е т : app / 684680 | Polygoneer
< XLimited5 > У ж е и м е е т : app / 1089130 | Quake II RTX
< XLimited5 > У ж е и м е е т : app / 755790 | Ring of Elysium
< XLimited5 > У ж е и м е е т : app / 1258080 | Shop Titans
< XLimited5 > У ж е и м е е т : app / 759530 | Struckd - 3D Game Creator
< XLimited5 > У ж е и м е е т : app / 269710 | Tumblestone
< XLimited5 > У ж е и м е е т : app / 304930 | Unturned
< XLimited5 > У ж е и м е е т : app / 1019250 | WWII TCG - World War 2 : The Card Game
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 1493800 | Aircraft Carrier Survival : Prolouge .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 349520 | Armillo .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 346330 | BrainBread 2.
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 1086690 | C - War 2.
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 730 | Counter - Strike : Global Offensive .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 838380 | DEAD OR ALIVE 6.
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 582890 | Estranged : The Departure .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 331470 | Everlasting Summer .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 1078000 | Gamecraft .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 266310 | GameGuru .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 275390 | Guacamelee ! Super Turbo Championship Edition .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 627690 | Idle Champions of the Forgotten Realms .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 1048540 | Kao the Kangaroo : Round 2.
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 370910 | Kathy Rain .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 343710 | KHOLAT .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 253900 | Knights and Merchants .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 224260 | No More Room in Hell .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 343360 | Particula .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 237870 | Planet Explorers .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 684680 | Polygoneer .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 1089130 | Quake II RTX .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 755790 | Ring of Elysium .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 1258080 | Shop Titans .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 759530 | Struckd - 3D Game Creator .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 269710 | Tumblestone .
< ASF > 1 / 1 б о т о в у ж е и м е ю т и г р у app / 304930 | Unturned . ";
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message , prefix ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 2 , output . Count ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
foreach ( string messagePart in output ) {
if ( ( messagePart . Length < = prefix . Length ) | | ! messagePart . StartsWith ( prefix , StringComparison . Ordinal ) ) {
Assert . Fail ( ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
return ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
string [ ] lines = messagePart . Split ( new [ ] { "\r\n" , "\r" , "\n" } , StringSplitOptions . None ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
int bytes = lines . Where ( static line = > line . Length > 0 ) . Sum ( Encoding . UTF8 . GetByteCount ) + ( ( lines . Length - 1 ) * NewlineWeight ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
if ( bytes > MaxMessageBytesForUnlimitedAccounts ) {
Assert . Fail ( ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
return ;
2021-06-18 17:50:14 +00:00
}
}
2021-11-10 20:23:24 +00:00
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[DataRow(false)]
[DataRow(true)]
[DataTestMethod]
public async Task SplitsOnNewlinesWithParagraphCharacter ( bool isAccountLimited ) {
int maxMessageBytes = isAccountLimited ? MaxMessageBytesForLimitedAccounts : MaxMessageBytesForUnlimitedAccounts ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
StringBuilder newlinePartBuilder = new ( ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
for ( ushort bytes = 0 ; bytes < maxMessageBytes - ReservedContinuationMessageBytes - NewlineWeight ; ) {
if ( newlinePartBuilder . Length > 0 ) {
bytes + = NewlineWeight ;
newlinePartBuilder . Append ( Environment . NewLine ) ;
2021-06-18 17:50:14 +00:00
}
2021-11-10 20:23:24 +00:00
bytes + + ;
newlinePartBuilder . Append ( 'a' ) ;
}
string newlinePart = newlinePartBuilder . ToString ( ) ;
string message = newlinePart + Environment . NewLine + newlinePart + Environment . NewLine + newlinePart + Environment . NewLine + newlinePart ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
List < string > output = await GetMessageParts ( message , isAccountLimited : isAccountLimited ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( 4 , output . Count ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . AreEqual ( newlinePart + ParagraphCharacter , output [ 0 ] ) ;
Assert . AreEqual ( newlinePart + ParagraphCharacter , output [ 1 ] ) ;
Assert . AreEqual ( newlinePart + ParagraphCharacter , output [ 2 ] ) ;
Assert . AreEqual ( newlinePart , output [ 3 ] ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[ExpectedException(typeof(ArgumentOutOfRangeException))]
[TestMethod]
public async Task ThrowsOnTooLongNewlinesPrefix ( ) {
string prefix = new ( '\n' , ( MaxMessagePrefixBytes / NewlineWeight ) + 1 ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
const string message = "asdf" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
await GetMessageParts ( message , prefix ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . Fail ( ) ;
}
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
[ExpectedException(typeof(ArgumentOutOfRangeException))]
[TestMethod]
public async Task ThrowsOnTooLongPrefix ( ) {
string prefix = new ( 'x' , MaxMessagePrefixBytes + 1 ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
const string message = "asdf" ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
await GetMessageParts ( message , prefix ) . ToListAsync ( ) . ConfigureAwait ( false ) ;
2021-06-18 17:50:14 +00:00
2021-11-10 20:23:24 +00:00
Assert . Fail ( ) ;
2021-06-18 17:50:14 +00:00
}
}