Files
Terminal.Gui/Tests/UnitTestsParallelizable/Text/StringTests.cs
2025-11-12 17:20:23 +00:00

205 lines
7.5 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

namespace UnitTests_Parallelizable.TextTests;
#nullable enable
public class StringTests
{
[Fact]
public void TestGetColumns_Empty ()
{
var str = string.Empty;
Assert.Equal (0, str.GetColumns ());
}
[Theory]
[InlineData ("a", 1)]
[InlineData ("á", 1)]
[InlineData ("ab", 2)]
[InlineData ("áé", 2)]
[InlineData ("abc", 3)]
[InlineData ("áéí", 3)]
[InlineData ("abcd", 4)]
public void TestGetColumns_MultiRune (string str, int expected) { Assert.Equal (expected, str.GetColumns ()); }
// Test non-BMP codepoints
// Face with Tears of Joy Emoji (😂), Unicode U+1F602 is 2 columns wide
[Theory]
[InlineData ("😂", 2)]
[InlineData ("😂😂", 4)]
public void TestGetColumns_MultiRune_NonBMP (string str, int expected) { Assert.Equal (expected, str.GetColumns ()); }
// Test known wide codepoints
[Theory]
[InlineData ("🙂", 1, 2)]
[InlineData ("a🙂", 2, 3)]
[InlineData ("🙂a", 2, 3)]
[InlineData ("👨‍👩‍👦‍👦", 1, 2)]
[InlineData ("👨‍👩‍👦‍👦🙂", 2, 4)]
[InlineData ("👨👩👦👦🙂a", 3, 5)]
[InlineData ("👨👩👦👦a🙂", 3, 5)]
[InlineData ("👨‍👩‍👦‍👦👨‍👩‍👦‍👦", 2, 4)]
[InlineData ("าำ", 1, 2)] // า U+0E32 - THAI CHARACTER SARA AA with ำ U+0E33 - THAI CHARACTER SARA AM
[InlineData ("山", 1, 2)] // The character for "mountain" in Chinese/Japanese/Korean (山), Unicode U+5C71
[InlineData ("山🙂", 2, 4)] // The character for "mountain" in Chinese/Japanese/Korean (山), Unicode U+5C71
//[InlineData ("\ufe20\ufe21", 2)] // Combining Ligature Left Half ︠ - U+fe20 -https://github.com/microsoft/terminal/blob/main/src/types/unicode_width_overrides.xml
// // Combining Ligature Right Half - U+fe21 -https://github.com/microsoft/terminal/blob/main/src/types/unicode_width_overrides.xml
public void TestGetColumns_MultiRune_WideBMP_Graphemes (string str, int graphemesCount, int expected)
{
Assert.Equal (graphemesCount, GraphemeHelper.GetGraphemes (str).ToArray ().Length);
Assert.Equal (expected, str.GetColumns ());
}
[Fact]
public void TestGetColumns_Null ()
{
string? str = null;
Assert.Equal (0, str!.GetColumns ());
}
[Fact]
public void TestGetColumns_SingleRune ()
{
var str = "a";
Assert.Equal (1, str.GetColumns ());
}
[Fact]
public void TestGetColumns_Zero_Width ()
{
var str = "\u200D";
Assert.Equal (0, str.GetColumns ());
}
[Theory]
[InlineData (null)]
[InlineData ("")]
public void TestGetColumns_Does_Not_Throws_With_Null_And_Empty_String (string? text)
{
if (text is null)
{
Assert.Equal (0, StringExtensions.GetColumns (text!));
}
else
{
Assert.Equal (0, text.GetColumns ());
}
}
public class ReadOnlySpanExtensionsTests
{
[Theory]
[InlineData ("12345", true)] // all ASCII digits
[InlineData ("0", true)] // single ASCII digit
[InlineData ("", false)] // empty span
[InlineData ("12a45", false)] // contains a letter
[InlineData ("", false)] // full-width Unicode digits (not ASCII)
[InlineData ("12 34", false)] // contains space
[InlineData ("١٢٣", false)] // Arabic-Indic digits
public void IsAllAsciiDigits_WorksAsExpected (string input, bool expected)
{
// Arrange
ReadOnlySpan<char> span = input.AsSpan ();
// Act
bool result = span.IsAllAsciiDigits ();
// Assert
Assert.Equal (expected, result);
}
}
[Theory]
[InlineData ("0", true)]
[InlineData ("9", true)]
[InlineData ("A", true)]
[InlineData ("F", true)]
[InlineData ("a", true)]
[InlineData ("f", true)]
[InlineData ("123ABC", true)]
[InlineData ("abcdef", true)]
[InlineData ("G", false)] // 'G' not hex
[InlineData ("Z9", false)] // 'Z' not hex
[InlineData ("12 34", false)] // space not hex
[InlineData ("", false)] // empty string
[InlineData ("", false)] // full-width digits, not ASCII
[InlineData ("0xFF", false)] // includes 'x'
public void IsAllAsciiHexDigits_ReturnsExpected (string input, bool expected)
{
// Arrange
ReadOnlySpan<char> span = input.AsSpan ();
// Act
bool result = span.IsAllAsciiHexDigits ();
// Assert
Assert.Equal (expected, result);
}
[Theory]
[MemberData (nameof (GetStringConcatCases))]
public void ToString_ReturnsExpected (IEnumerable<string> input, string expected)
{
// Act
string result = StringExtensions.ToString (input);
// Assert
Assert.Equal (expected, result);
}
public static IEnumerable<object []> GetStringConcatCases ()
{
yield return [new string [] { }, string.Empty]; // Empty sequence
yield return [new [] { "" }, string.Empty]; // Single empty string
yield return [new [] { "A" }, "A"]; // Single element
yield return [new [] { "A", "B" }, "AB"]; // Simple concatenation
yield return [new [] { "Hello", " ", "World" }, "Hello World"]; // Multiple parts
yield return [new [] { "123", "456", "789" }, "123456789"]; // Numeric strings
yield return [new [] { "👩‍", "🧒" }, "👩‍🧒"]; // Grapheme sequence
yield return [new [] { "α", "β", "γ" }, "αβγ"]; // Unicode letters
yield return [new [] { "A", null, "B" }, "AB"]; // Null ignored by string.Concat
}
[Theory]
[InlineData ("", false)] // Empty string
[InlineData ("A", false)] // Single BMP character
[InlineData ("AB", false)] // Two BMP chars, not a surrogate pair
[InlineData ("👩", true)] // Single emoji surrogate pair (U+1F469)
[InlineData ("🧒", true)] // Another emoji surrogate pair (U+1F9D2)
[InlineData ("𐍈", true)] // Gothic letter hwair (U+10348)
[InlineData ("A👩", false)] // One BMP + one surrogate half
[InlineData ("👩‍", false)] // Surrogate pair + ZWJ (length != 2)
public void IsSurrogatePair_ReturnsExpected (string input, bool expected)
{
// Act
bool result = input.IsSurrogatePair ();
// Assert
Assert.Equal (expected, result);
}
[Theory]
// Control characters (should be replaced with the "Control Pictures" block)
[InlineData ("\u0000", "\u2400")] // NULL → ␀
[InlineData ("\u0009", "\u2409")] // TAB → ␉
[InlineData ("\u000A", "\u240A")] // LF → ␊
[InlineData ("\u000D", "\u240D")] // CR → ␍
// Printable characters (should remain unchanged)
[InlineData ("A", "A")]
[InlineData (" ", " ")]
[InlineData ("~", "~")]
// Multi-character string (should return unchanged)
[InlineData ("AB", "AB")]
[InlineData ("Hello", "Hello")]
[InlineData ("\u0009A", "\u0009A")] // includes a control char, but length > 1
public void MakePrintable_ReturnsExpected (string input, string expected)
{
// Act
string result = input.MakePrintable ();
// Assert
Assert.Equal (expected, result);
}
}