|
#pragma warning disable CA1052 // Static holder types should be static
#pragma warning disable IDE0018 // Inline variable declaration
#pragma warning disable IDE0028 // Simplify collection initialization
#pragma warning disable IDE0040 // Add accessibility modifiers
#pragma warning disable IDE0058 // Expression value is never used
#pragma warning disable IDE0090 // Use 'new(...)'
#pragma warning disable IDE0161 // Convert to file-scoped namespace
#if XUNIT_NULLABLE
#nullable enable
#else
// In case this is source-imported with global nullable enabled but no XUNIT_NULLABLE
#pragma warning disable CS8604
#endif
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
using Xunit.Internal;
using Xunit.Sdk;
namespace Xunit
{
#if XUNIT_VISIBILITY_INTERNAL
internal
#else
public
#endif
partial class Assert
{
/// <summary>
/// Verifies that a string contains a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the sub-string is not present inside the string</exception>
public static void Contains(
string expectedSubstring,
#if XUNIT_NULLABLE
string? actualString) =>
#else
string actualString) =>
#endif
Contains(expectedSubstring, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string contains a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the sub-string is not present inside the string</exception>
public static void Contains(
string expectedSubstring,
#if XUNIT_NULLABLE
string? actualString,
#else
string actualString,
#endif
StringComparison comparisonType)
{
GuardArgumentNotNull(nameof(expectedSubstring), expectedSubstring);
if (actualString == null || actualString.IndexOf(expectedSubstring, comparisonType) < 0)
throw ContainsException.ForSubStringNotFound(expectedSubstring, actualString);
}
#if XUNIT_SPAN
/// <summary>
/// Verifies that a string contains a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the sub-string is not present inside the string</exception>
public static void Contains(
Memory<char> expectedSubstring,
Memory<char> actualString) =>
Contains((ReadOnlyMemory<char>)expectedSubstring, (ReadOnlyMemory<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string contains a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the sub-string is not present inside the string</exception>
public static void Contains(
Memory<char> expectedSubstring,
ReadOnlyMemory<char> actualString) =>
Contains((ReadOnlyMemory<char>)expectedSubstring, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string contains a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the sub-string is not present inside the string</exception>
public static void Contains(
ReadOnlyMemory<char> expectedSubstring,
Memory<char> actualString) =>
Contains(expectedSubstring, (ReadOnlyMemory<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string contains a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the sub-string is not present inside the string</exception>
public static void Contains(
ReadOnlyMemory<char> expectedSubstring,
ReadOnlyMemory<char> actualString) =>
Contains(expectedSubstring, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string contains a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the sub-string is not present inside the string</exception>
public static void Contains(
Memory<char> expectedSubstring,
Memory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
Contains((ReadOnlyMemory<char>)expectedSubstring, (ReadOnlyMemory<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string contains a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the sub-string is not present inside the string</exception>
public static void Contains(
Memory<char> expectedSubstring,
ReadOnlyMemory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
Contains((ReadOnlyMemory<char>)expectedSubstring, actualString, comparisonType);
/// <summary>
/// Verifies that a string contains a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the sub-string is not present inside the string</exception>
public static void Contains(
ReadOnlyMemory<char> expectedSubstring,
Memory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
Contains(expectedSubstring, (ReadOnlyMemory<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string contains a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the sub-string is not present inside the string</exception>
public static void Contains(
ReadOnlyMemory<char> expectedSubstring,
ReadOnlyMemory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture)
{
GuardArgumentNotNull(nameof(expectedSubstring), expectedSubstring);
Contains(expectedSubstring.Span, actualString.Span, comparisonType);
}
/// <summary>
/// Verifies that a string contains a given string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the string is not present inside the string</exception>
public static void Contains(
Span<char> expectedSubstring,
Span<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
Contains((ReadOnlySpan<char>)expectedSubstring, (ReadOnlySpan<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string contains a given string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the string is not present inside the string</exception>
public static void Contains(
Span<char> expectedSubstring,
ReadOnlySpan<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
Contains((ReadOnlySpan<char>)expectedSubstring, actualString, comparisonType);
/// <summary>
/// Verifies that a string contains a given string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the string is not present inside the string</exception>
public static void Contains(
ReadOnlySpan<char> expectedSubstring,
Span<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
Contains(expectedSubstring, (ReadOnlySpan<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string contains a given string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the string is not present inside the string</exception>
public static void Contains(
ReadOnlySpan<char> expectedSubstring,
ReadOnlySpan<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture)
{
if (actualString.IndexOf(expectedSubstring, comparisonType) < 0)
throw ContainsException.ForSubStringNotFound(
expectedSubstring.ToString(),
actualString.ToString()
);
}
/// <summary>
/// Verifies that a string contains a given string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the string is not present inside the string</exception>
public static void Contains(
Span<char> expectedSubstring,
Span<char> actualString) =>
Contains((ReadOnlySpan<char>)expectedSubstring, (ReadOnlySpan<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string contains a given string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the string is not present inside the string</exception>
public static void Contains(
Span<char> expectedSubstring,
ReadOnlySpan<char> actualString) =>
Contains((ReadOnlySpan<char>)expectedSubstring, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string contains a given string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the string is not present inside the string</exception>
public static void Contains(
ReadOnlySpan<char> expectedSubstring,
Span<char> actualString) =>
Contains(expectedSubstring, (ReadOnlySpan<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string contains a given string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The string expected to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the string is not present inside the string</exception>
public static void Contains(
ReadOnlySpan<char> expectedSubstring,
ReadOnlySpan<char> actualString) =>
Contains(expectedSubstring, actualString, StringComparison.CurrentCulture);
#endif
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
string expectedSubstring,
#if XUNIT_NULLABLE
string? actualString) =>
#else
string actualString) =>
#endif
DoesNotContain(expectedSubstring, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
string expectedSubstring,
#if XUNIT_NULLABLE
string? actualString,
#else
string actualString,
#endif
StringComparison comparisonType)
{
GuardArgumentNotNull(nameof(expectedSubstring), expectedSubstring);
if (actualString != null)
{
var idx = actualString.IndexOf(expectedSubstring, comparisonType);
if (idx >= 0)
throw DoesNotContainException.ForSubStringFound(expectedSubstring, idx, actualString);
}
}
#if XUNIT_SPAN
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
Memory<char> expectedSubstring,
Memory<char> actualString) =>
DoesNotContain((ReadOnlyMemory<char>)expectedSubstring, (ReadOnlyMemory<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
Memory<char> expectedSubstring,
ReadOnlyMemory<char> actualString) =>
DoesNotContain((ReadOnlyMemory<char>)expectedSubstring, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
ReadOnlyMemory<char> expectedSubstring,
Memory<char> actualString) =>
DoesNotContain(expectedSubstring, (ReadOnlyMemory<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
ReadOnlyMemory<char> expectedSubstring,
ReadOnlyMemory<char> actualString) =>
DoesNotContain(expectedSubstring, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
Memory<char> expectedSubstring,
Memory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
DoesNotContain((ReadOnlyMemory<char>)expectedSubstring, (ReadOnlyMemory<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
Memory<char> expectedSubstring,
ReadOnlyMemory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
DoesNotContain((ReadOnlyMemory<char>)expectedSubstring, actualString, comparisonType);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
ReadOnlyMemory<char> expectedSubstring,
Memory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
DoesNotContain(expectedSubstring, (ReadOnlyMemory<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
ReadOnlyMemory<char> expectedSubstring,
ReadOnlyMemory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture)
{
GuardArgumentNotNull(nameof(expectedSubstring), expectedSubstring);
DoesNotContain(expectedSubstring.Span, actualString.Span, comparisonType);
}
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
Span<char> expectedSubstring,
Span<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
DoesNotContain((ReadOnlySpan<char>)expectedSubstring, (ReadOnlySpan<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
Span<char> expectedSubstring,
ReadOnlySpan<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
DoesNotContain((ReadOnlySpan<char>)expectedSubstring, actualString, comparisonType);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
ReadOnlySpan<char> expectedSubstring,
Span<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
DoesNotContain(expectedSubstring, (ReadOnlySpan<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
ReadOnlySpan<char> expectedSubstring,
ReadOnlySpan<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture)
{
var idx = actualString.IndexOf(expectedSubstring, comparisonType);
if (idx > -1)
throw DoesNotContainException.ForSubStringFound(expectedSubstring.ToString(), idx, actualString.ToString());
}
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
Span<char> expectedSubstring,
Span<char> actualString) =>
DoesNotContain((ReadOnlySpan<char>)expectedSubstring, (ReadOnlySpan<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
Span<char> expectedSubstring,
ReadOnlySpan<char> actualString) =>
DoesNotContain((ReadOnlySpan<char>)expectedSubstring, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
ReadOnlySpan<char> expectedSubstring,
Span<char> actualString) =>
DoesNotContain(expectedSubstring, (ReadOnlySpan<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string does not contain a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedSubstring">The sub-string expected not to be in the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotContainException">Thrown when the sub-string is present inside the string</exception>
public static void DoesNotContain(
ReadOnlySpan<char> expectedSubstring,
ReadOnlySpan<char> actualString) =>
DoesNotContain(expectedSubstring, actualString, StringComparison.CurrentCulture);
#endif
/// <summary>
/// Verifies that a string does not match a regular expression.
/// </summary>
/// <param name="expectedRegexPattern">The regex pattern expected not to match</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotMatchException">Thrown when the string matches the regex pattern</exception>
public static void DoesNotMatch(
[StringSyntax(StringSyntaxAttribute.Regex)]
string expectedRegexPattern,
#if XUNIT_NULLABLE
string? actualString)
#else
string actualString)
#endif
{
GuardArgumentNotNull(nameof(expectedRegexPattern), expectedRegexPattern);
if (actualString != null)
{
var match = Regex.Match(actualString, expectedRegexPattern);
if (match.Success)
{
int pointerIndent;
var formattedExpected = AssertHelper.ShortenAndEncodeString(expectedRegexPattern);
var formattedActual = AssertHelper.ShortenAndEncodeString(actualString, match.Index, out pointerIndent);
throw DoesNotMatchException.ForMatch(formattedExpected, match.Index, pointerIndent, formattedActual);
}
}
}
/// <summary>
/// Verifies that a string does not match a regular expression.
/// </summary>
/// <param name="expectedRegex">The regex expected not to match</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="DoesNotMatchException">Thrown when the string matches the regex</exception>
public static void DoesNotMatch(
Regex expectedRegex,
#if XUNIT_NULLABLE
string? actualString)
#else
string actualString)
#endif
{
GuardArgumentNotNull(nameof(expectedRegex), expectedRegex);
if (actualString != null)
{
var match = expectedRegex.Match(actualString);
if (match.Success)
{
int pointerIndent;
var formattedExpected = AssertHelper.ShortenAndEncodeString(expectedRegex.ToString());
var formattedActual = AssertHelper.ShortenAndEncodeString(actualString, match.Index, out pointerIndent);
throw DoesNotMatchException.ForMatch(formattedExpected, match.Index, pointerIndent, formattedActual);
}
}
}
/// <summary>
/// Verifies that a string is empty.
/// </summary>
/// <param name="value">The string value to be inspected</param>
/// <exception cref="ArgumentNullException">Thrown when the string is null</exception>
/// <exception cref="EmptyException">Thrown when the string is not empty</exception>
public static void Empty(string value)
{
GuardArgumentNotNull(nameof(value), value);
if (value.Length != 0)
throw EmptyException.ForNonEmptyString(value);
}
/// <summary>
/// Verifies that a string ends with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
#if XUNIT_NULLABLE
string? expectedEndString,
string? actualString) =>
#else
string expectedEndString,
string actualString) =>
#endif
EndsWith(expectedEndString, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
#if XUNIT_NULLABLE
string? expectedEndString,
string? actualString,
#else
string expectedEndString,
string actualString,
#endif
StringComparison comparisonType)
{
if (expectedEndString == null || actualString == null || !actualString.EndsWith(expectedEndString, comparisonType))
throw EndsWithException.ForStringNotFound(expectedEndString, actualString);
}
#if XUNIT_SPAN
/// <summary>
/// Verifies that a string ends with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
Memory<char> expectedEndString,
Memory<char> actualString) =>
EndsWith((ReadOnlyMemory<char>)expectedEndString, (ReadOnlyMemory<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
Memory<char> expectedEndString,
ReadOnlyMemory<char> actualString) =>
EndsWith((ReadOnlyMemory<char>)expectedEndString, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
ReadOnlyMemory<char> expectedEndString,
Memory<char> actualString) =>
EndsWith(expectedEndString, (ReadOnlyMemory<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
ReadOnlyMemory<char> expectedEndString,
ReadOnlyMemory<char> actualString) =>
EndsWith(expectedEndString, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
Memory<char> expectedEndString,
Memory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
EndsWith((ReadOnlyMemory<char>)expectedEndString, (ReadOnlyMemory<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
Memory<char> expectedEndString,
ReadOnlyMemory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
EndsWith((ReadOnlyMemory<char>)expectedEndString, actualString, comparisonType);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
ReadOnlyMemory<char> expectedEndString,
Memory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
EndsWith(expectedEndString, (ReadOnlyMemory<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
ReadOnlyMemory<char> expectedEndString,
ReadOnlyMemory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture)
{
GuardArgumentNotNull(nameof(expectedEndString), expectedEndString);
EndsWith(expectedEndString.Span, actualString.Span, comparisonType);
}
/// <summary>
/// Verifies that a string ends with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
Span<char> expectedEndString,
Span<char> actualString) =>
EndsWith((ReadOnlySpan<char>)expectedEndString, (ReadOnlySpan<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
Span<char> expectedEndString,
ReadOnlySpan<char> actualString) =>
EndsWith((ReadOnlySpan<char>)expectedEndString, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
ReadOnlySpan<char> expectedEndString,
Span<char> actualString) =>
EndsWith(expectedEndString, (ReadOnlySpan<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
ReadOnlySpan<char> expectedEndString,
ReadOnlySpan<char> actualString) =>
EndsWith(expectedEndString, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
Span<char> expectedEndString,
Span<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
EndsWith((ReadOnlySpan<char>)expectedEndString, (ReadOnlySpan<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
Span<char> expectedEndString,
ReadOnlySpan<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
EndsWith((ReadOnlySpan<char>)expectedEndString, actualString, comparisonType);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
ReadOnlySpan<char> expectedEndString,
Span<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
EndsWith(expectedEndString, (ReadOnlySpan<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string ends with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedEndString">The sub-string expected to be at the end of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="EndsWithException">Thrown when the string does not end with the expected sub-string</exception>
public static void EndsWith(
ReadOnlySpan<char> expectedEndString,
ReadOnlySpan<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture)
{
if (!actualString.EndsWith(expectedEndString, comparisonType))
throw EndsWithException.ForStringNotFound(expectedEndString.ToString(), actualString.ToString());
}
#endif
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
#if XUNIT_NULLABLE
string? expected,
string? actual) =>
#else
string expected,
string actual) =>
#endif
Equal(expected, actual, false, false, false, false);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <param name="ignoreCase">If set to <c>true</c>, ignores cases differences. The invariant culture is used.</param>
/// <param name="ignoreLineEndingDifferences">If set to <c>true</c>, treats \r\n, \r, and \n as equivalent.</param>
/// <param name="ignoreWhiteSpaceDifferences">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks) in any non-zero quantity as equivalent.</param>
/// <param name="ignoreAllWhiteSpace">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks), including zero quantities, as equivalent.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
/// <remarks>
/// The <paramref name="ignoreWhiteSpaceDifferences"/> and <paramref name="ignoreAllWhiteSpace"/> flags consider
/// the following characters to be white-space:
/// <see href="https://unicode-explorer.com/c/0009">Tab</see> (\t),
/// <see href="https://unicode-explorer.com/c/0020">Space</see> (\u0020),
/// <see href="https://unicode-explorer.com/c/00A0">No-Break Space</see> (\u00A0),
/// <see href="https://unicode-explorer.com/c/1680">Ogham Space Mark</see> (\u1680),
/// <see href="https://unicode-explorer.com/c/180E">Mongolian Vowel Separator</see> (\u180E),
/// <see href="https://unicode-explorer.com/c/2000">En Quad</see> (\u2000),
/// <see href="https://unicode-explorer.com/c/2001">Em Quad</see> (\u2001),
/// <see href="https://unicode-explorer.com/c/2002">En Space</see> (\u2002),
/// <see href="https://unicode-explorer.com/c/2003">Em Space</see> (\u2003),
/// <see href="https://unicode-explorer.com/c/2004">Three-Per-Em Space</see> (\u2004),
/// <see href="https://unicode-explorer.com/c/2005">Four-Per-Em Space</see> (\u2004),
/// <see href="https://unicode-explorer.com/c/2006">Six-Per-Em Space</see> (\u2006),
/// <see href="https://unicode-explorer.com/c/2007">Figure Space</see> (\u2007),
/// <see href="https://unicode-explorer.com/c/2008">Punctuation Space</see> (\u2008),
/// <see href="https://unicode-explorer.com/c/2009">Thin Space</see> (\u2009),
/// <see href="https://unicode-explorer.com/c/200A">Hair Space</see> (\u200A),
/// <see href="https://unicode-explorer.com/c/200B">Zero Width Space</see> (\u200B),
/// <see href="https://unicode-explorer.com/c/202F">Narrow No-Break Space</see> (\u202F),
/// <see href="https://unicode-explorer.com/c/205F">Medium Mathematical Space</see> (\u205F),
/// <see href="https://unicode-explorer.com/c/3000">Ideographic Space</see> (\u3000),
/// and <see href="https://unicode-explorer.com/c/FEFF">Zero Width No-Break Space</see> (\uFEFF).
/// In particular, it does not include carriage return (\r) or line feed (\n), which are covered by
/// <paramref name="ignoreLineEndingDifferences"/>.
/// </remarks>
public static void Equal(
#if XUNIT_SPAN
ReadOnlySpan<char> expected,
ReadOnlySpan<char> actual,
#elif XUNIT_NULLABLE
string? expected,
string? actual,
#else
string expected,
string actual,
#endif
bool ignoreCase = false,
bool ignoreLineEndingDifferences = false,
bool ignoreWhiteSpaceDifferences = false,
bool ignoreAllWhiteSpace = false)
{
#if !XUNIT_SPAN
if (expected == null && actual == null)
return;
if (expected == null || actual == null)
throw EqualException.ForMismatchedStrings(expected, actual, -1, -1);
#endif
// Walk the string, keeping separate indices since we can skip variable amounts of
// data based on ignoreLineEndingDifferences and ignoreWhiteSpaceDifferences.
var expectedIndex = 0;
var actualIndex = 0;
var expectedLength = expected.Length;
var actualLength = actual.Length;
// Block used to fix edge case of Equal("", " ") when ignoreAllWhiteSpace enabled.
if (ignoreAllWhiteSpace)
{
if (expectedLength == 0 && SkipWhitespace(actual, 0) == actualLength)
return;
if (actualLength == 0 && SkipWhitespace(expected, 0) == expectedLength)
return;
}
while (expectedIndex < expectedLength && actualIndex < actualLength)
{
var expectedChar = expected[expectedIndex];
var actualChar = actual[actualIndex];
if (ignoreLineEndingDifferences && charsLineEndings.Contains(expectedChar) && charsLineEndings.Contains(actualChar))
{
expectedIndex = SkipLineEnding(expected, expectedIndex);
actualIndex = SkipLineEnding(actual, actualIndex);
}
else if (ignoreAllWhiteSpace && (charsWhitespace.Contains(expectedChar) || charsWhitespace.Contains(actualChar)))
{
expectedIndex = SkipWhitespace(expected, expectedIndex);
actualIndex = SkipWhitespace(actual, actualIndex);
}
else if (ignoreWhiteSpaceDifferences && charsWhitespace.Contains(expectedChar) && charsWhitespace.Contains(actualChar))
{
expectedIndex = SkipWhitespace(expected, expectedIndex);
actualIndex = SkipWhitespace(actual, actualIndex);
}
else
{
if (ignoreCase)
{
expectedChar = char.ToUpperInvariant(expectedChar);
actualChar = char.ToUpperInvariant(actualChar);
}
if (expectedChar != actualChar)
break;
expectedIndex++;
actualIndex++;
}
}
if (expectedIndex < expectedLength || actualIndex < actualLength)
throw EqualException.ForMismatchedStrings(expected.ToString(), actual.ToString(), expectedIndex, actualIndex);
}
#if XUNIT_SPAN
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
Memory<char> expected,
Memory<char> actual) =>
Equal((ReadOnlyMemory<char>)expected, (ReadOnlyMemory<char>)actual, false, false, false, false);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
Memory<char> expected,
ReadOnlyMemory<char> actual) =>
Equal((ReadOnlyMemory<char>)expected, actual, false, false, false, false);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
ReadOnlyMemory<char> expected,
Memory<char> actual) =>
Equal(expected, (ReadOnlyMemory<char>)actual, false, false, false, false);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
ReadOnlyMemory<char> expected,
ReadOnlyMemory<char> actual) =>
Equal(expected, actual, false, false, false, false);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <param name="ignoreCase">If set to <c>true</c>, ignores cases differences. The invariant culture is used.</param>
/// <param name="ignoreLineEndingDifferences">If set to <c>true</c>, treats \r\n, \r, and \n as equivalent.</param>
/// <param name="ignoreWhiteSpaceDifferences">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks) in any non-zero quantity as equivalent.</param>
/// <param name="ignoreAllWhiteSpace">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks), including zero quantities, as equivalent.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
Memory<char> expected,
Memory<char> actual,
bool ignoreCase = false,
bool ignoreLineEndingDifferences = false,
bool ignoreWhiteSpaceDifferences = false,
bool ignoreAllWhiteSpace = false) =>
Equal((ReadOnlyMemory<char>)expected, (ReadOnlyMemory<char>)actual, ignoreCase, ignoreLineEndingDifferences, ignoreWhiteSpaceDifferences, ignoreAllWhiteSpace);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <param name="ignoreCase">If set to <c>true</c>, ignores cases differences. The invariant culture is used.</param>
/// <param name="ignoreLineEndingDifferences">If set to <c>true</c>, treats \r\n, \r, and \n as equivalent.</param>
/// <param name="ignoreWhiteSpaceDifferences">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks) in any non-zero quantity as equivalent.</param>
/// <param name="ignoreAllWhiteSpace">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks), including zero quantities, as equivalent.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
Memory<char> expected,
ReadOnlyMemory<char> actual,
bool ignoreCase = false,
bool ignoreLineEndingDifferences = false,
bool ignoreWhiteSpaceDifferences = false,
bool ignoreAllWhiteSpace = false) =>
Equal((ReadOnlyMemory<char>)expected, actual, ignoreCase, ignoreLineEndingDifferences, ignoreWhiteSpaceDifferences, ignoreAllWhiteSpace);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <param name="ignoreCase">If set to <c>true</c>, ignores cases differences. The invariant culture is used.</param>
/// <param name="ignoreLineEndingDifferences">If set to <c>true</c>, treats \r\n, \r, and \n as equivalent.</param>
/// <param name="ignoreWhiteSpaceDifferences">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks) in any non-zero quantity as equivalent.</param>
/// <param name="ignoreAllWhiteSpace">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks), including zero quantities, as equivalent.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
ReadOnlyMemory<char> expected,
Memory<char> actual,
bool ignoreCase = false,
bool ignoreLineEndingDifferences = false,
bool ignoreWhiteSpaceDifferences = false,
bool ignoreAllWhiteSpace = false) =>
Equal(expected, (ReadOnlyMemory<char>)actual, ignoreCase, ignoreLineEndingDifferences, ignoreWhiteSpaceDifferences, ignoreAllWhiteSpace);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <param name="ignoreCase">If set to <c>true</c>, ignores cases differences. The invariant culture is used.</param>
/// <param name="ignoreLineEndingDifferences">If set to <c>true</c>, treats \r\n, \r, and \n as equivalent.</param>
/// <param name="ignoreWhiteSpaceDifferences">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks) in any non-zero quantity as equivalent.</param>
/// <param name="ignoreAllWhiteSpace">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks), including zero quantities, as equivalent.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
ReadOnlyMemory<char> expected,
ReadOnlyMemory<char> actual,
bool ignoreCase = false,
bool ignoreLineEndingDifferences = false,
bool ignoreWhiteSpaceDifferences = false,
bool ignoreAllWhiteSpace = false)
{
GuardArgumentNotNull(nameof(expected), expected);
Equal(
expected.Span,
actual.Span,
ignoreCase,
ignoreLineEndingDifferences,
ignoreWhiteSpaceDifferences,
ignoreAllWhiteSpace
);
}
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
Span<char> expected,
Span<char> actual) =>
Equal((ReadOnlySpan<char>)expected, (ReadOnlySpan<char>)actual, false, false, false, false);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
Span<char> expected,
ReadOnlySpan<char> actual) =>
Equal((ReadOnlySpan<char>)expected, actual, false, false, false, false);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
ReadOnlySpan<char> expected,
Span<char> actual) =>
Equal(expected, (ReadOnlySpan<char>)actual, false, false, false, false);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
public static void Equal(
ReadOnlySpan<char> expected,
ReadOnlySpan<char> actual) =>
Equal(expected, actual, false, false, false, false);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <param name="ignoreCase">If set to <c>true</c>, ignores cases differences. The invariant culture is used.</param>
/// <param name="ignoreLineEndingDifferences">If set to <c>true</c>, treats \r\n, \r, and \n as equivalent.</param>
/// <param name="ignoreWhiteSpaceDifferences">If set to <c>true</c>, treats spaces and tabs (in any non-zero quantity) as equivalent.</param>
/// <param name="ignoreAllWhiteSpace">If set to <c>true</c>, ignores all white space differences during comparison.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
/// <remarks>
/// The <paramref name="ignoreWhiteSpaceDifferences"/> and <paramref name="ignoreAllWhiteSpace"/> flags consider
/// the following characters to be white-space:
/// <see href="https://unicode-explorer.com/c/0009">Tab</see> (\t),
/// <see href="https://unicode-explorer.com/c/0020">Space</see> (\u0020),
/// <see href="https://unicode-explorer.com/c/00A0">No-Break Space</see> (\u00A0),
/// <see href="https://unicode-explorer.com/c/1680">Ogham Space Mark</see> (\u1680),
/// <see href="https://unicode-explorer.com/c/180E">Mongolian Vowel Separator</see> (\u180E),
/// <see href="https://unicode-explorer.com/c/2000">En Quad</see> (\u2000),
/// <see href="https://unicode-explorer.com/c/2001">Em Quad</see> (\u2001),
/// <see href="https://unicode-explorer.com/c/2002">En Space</see> (\u2002),
/// <see href="https://unicode-explorer.com/c/2003">Em Space</see> (\u2003),
/// <see href="https://unicode-explorer.com/c/2004">Three-Per-Em Space</see> (\u2004),
/// <see href="https://unicode-explorer.com/c/2005">Four-Per-Em Space</see> (\u2004),
/// <see href="https://unicode-explorer.com/c/2006">Six-Per-Em Space</see> (\u2006),
/// <see href="https://unicode-explorer.com/c/2007">Figure Space</see> (\u2007),
/// <see href="https://unicode-explorer.com/c/2008">Punctuation Space</see> (\u2008),
/// <see href="https://unicode-explorer.com/c/2009">Thin Space</see> (\u2009),
/// <see href="https://unicode-explorer.com/c/200A">Hair Space</see> (\u200A),
/// <see href="https://unicode-explorer.com/c/200B">Zero Width Space</see> (\u200B),
/// <see href="https://unicode-explorer.com/c/202F">Narrow No-Break Space</see> (\u202F),
/// <see href="https://unicode-explorer.com/c/205F">Medium Mathematical Space</see> (\u205F),
/// <see href="https://unicode-explorer.com/c/3000">Ideographic Space</see> (\u3000),
/// and <see href="https://unicode-explorer.com/c/FEFF">Zero Width No-Break Space</see> (\uFEFF).
/// In particular, it does not include carriage return (\r) or line feed (\n), which are covered by
/// <paramref name="ignoreLineEndingDifferences"/>.
/// </remarks>
public static void Equal(
Span<char> expected,
Span<char> actual,
bool ignoreCase = false,
bool ignoreLineEndingDifferences = false,
bool ignoreWhiteSpaceDifferences = false,
bool ignoreAllWhiteSpace = false) =>
Equal((ReadOnlySpan<char>)expected, (ReadOnlySpan<char>)actual, ignoreCase, ignoreLineEndingDifferences, ignoreWhiteSpaceDifferences, ignoreAllWhiteSpace);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <param name="ignoreCase">If set to <c>true</c>, ignores cases differences. The invariant culture is used.</param>
/// <param name="ignoreLineEndingDifferences">If set to <c>true</c>, treats \r\n, \r, and \n as equivalent.</param>
/// <param name="ignoreWhiteSpaceDifferences">If set to <c>true</c>, treats spaces and tabs (in any non-zero quantity) as equivalent.</param>
/// <param name="ignoreAllWhiteSpace">If set to <c>true</c>, ignores all white space differences during comparison.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
/// <remarks>
/// The <paramref name="ignoreWhiteSpaceDifferences"/> and <paramref name="ignoreAllWhiteSpace"/> flags consider
/// the following characters to be white-space:
/// <see href="https://unicode-explorer.com/c/0009">Tab</see> (\t),
/// <see href="https://unicode-explorer.com/c/0020">Space</see> (\u0020),
/// <see href="https://unicode-explorer.com/c/00A0">No-Break Space</see> (\u00A0),
/// <see href="https://unicode-explorer.com/c/1680">Ogham Space Mark</see> (\u1680),
/// <see href="https://unicode-explorer.com/c/180E">Mongolian Vowel Separator</see> (\u180E),
/// <see href="https://unicode-explorer.com/c/2000">En Quad</see> (\u2000),
/// <see href="https://unicode-explorer.com/c/2001">Em Quad</see> (\u2001),
/// <see href="https://unicode-explorer.com/c/2002">En Space</see> (\u2002),
/// <see href="https://unicode-explorer.com/c/2003">Em Space</see> (\u2003),
/// <see href="https://unicode-explorer.com/c/2004">Three-Per-Em Space</see> (\u2004),
/// <see href="https://unicode-explorer.com/c/2005">Four-Per-Em Space</see> (\u2004),
/// <see href="https://unicode-explorer.com/c/2006">Six-Per-Em Space</see> (\u2006),
/// <see href="https://unicode-explorer.com/c/2007">Figure Space</see> (\u2007),
/// <see href="https://unicode-explorer.com/c/2008">Punctuation Space</see> (\u2008),
/// <see href="https://unicode-explorer.com/c/2009">Thin Space</see> (\u2009),
/// <see href="https://unicode-explorer.com/c/200A">Hair Space</see> (\u200A),
/// <see href="https://unicode-explorer.com/c/200B">Zero Width Space</see> (\u200B),
/// <see href="https://unicode-explorer.com/c/202F">Narrow No-Break Space</see> (\u202F),
/// <see href="https://unicode-explorer.com/c/205F">Medium Mathematical Space</see> (\u205F),
/// <see href="https://unicode-explorer.com/c/3000">Ideographic Space</see> (\u3000),
/// and <see href="https://unicode-explorer.com/c/FEFF">Zero Width No-Break Space</see> (\uFEFF).
/// In particular, it does not include carriage return (\r) or line feed (\n), which are covered by
/// <paramref name="ignoreLineEndingDifferences"/>.
/// </remarks>
public static void Equal(
Span<char> expected,
ReadOnlySpan<char> actual,
bool ignoreCase = false,
bool ignoreLineEndingDifferences = false,
bool ignoreWhiteSpaceDifferences = false,
bool ignoreAllWhiteSpace = false) =>
Equal((ReadOnlySpan<char>)expected, actual, ignoreCase, ignoreLineEndingDifferences, ignoreWhiteSpaceDifferences, ignoreAllWhiteSpace);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <param name="ignoreCase">If set to <c>true</c>, ignores cases differences. The invariant culture is used.</param>
/// <param name="ignoreLineEndingDifferences">If set to <c>true</c>, treats \r\n, \r, and \n as equivalent.</param>
/// <param name="ignoreWhiteSpaceDifferences">If set to <c>true</c>, treats spaces and tabs (in any non-zero quantity) as equivalent.</param>
/// <param name="ignoreAllWhiteSpace">If set to <c>true</c>, removes all whitespaces and tabs before comparing.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
/// <remarks>
/// The <paramref name="ignoreWhiteSpaceDifferences"/> and <paramref name="ignoreAllWhiteSpace"/> flags consider
/// the following characters to be white-space:
/// <see href="https://unicode-explorer.com/c/0009">Tab</see> (\t),
/// <see href="https://unicode-explorer.com/c/0020">Space</see> (\u0020),
/// <see href="https://unicode-explorer.com/c/00A0">No-Break Space</see> (\u00A0),
/// <see href="https://unicode-explorer.com/c/1680">Ogham Space Mark</see> (\u1680),
/// <see href="https://unicode-explorer.com/c/180E">Mongolian Vowel Separator</see> (\u180E),
/// <see href="https://unicode-explorer.com/c/2000">En Quad</see> (\u2000),
/// <see href="https://unicode-explorer.com/c/2001">Em Quad</see> (\u2001),
/// <see href="https://unicode-explorer.com/c/2002">En Space</see> (\u2002),
/// <see href="https://unicode-explorer.com/c/2003">Em Space</see> (\u2003),
/// <see href="https://unicode-explorer.com/c/2004">Three-Per-Em Space</see> (\u2004),
/// <see href="https://unicode-explorer.com/c/2005">Four-Per-Em Space</see> (\u2004),
/// <see href="https://unicode-explorer.com/c/2006">Six-Per-Em Space</see> (\u2006),
/// <see href="https://unicode-explorer.com/c/2007">Figure Space</see> (\u2007),
/// <see href="https://unicode-explorer.com/c/2008">Punctuation Space</see> (\u2008),
/// <see href="https://unicode-explorer.com/c/2009">Thin Space</see> (\u2009),
/// <see href="https://unicode-explorer.com/c/200A">Hair Space</see> (\u200A),
/// <see href="https://unicode-explorer.com/c/200B">Zero Width Space</see> (\u200B),
/// <see href="https://unicode-explorer.com/c/202F">Narrow No-Break Space</see> (\u202F),
/// <see href="https://unicode-explorer.com/c/205F">Medium Mathematical Space</see> (\u205F),
/// <see href="https://unicode-explorer.com/c/3000">Ideographic Space</see> (\u3000),
/// and <see href="https://unicode-explorer.com/c/FEFF">Zero Width No-Break Space</see> (\uFEFF).
/// In particular, it does not include carriage return (\r) or line feed (\n), which are covered by
/// <paramref name="ignoreLineEndingDifferences"/>.
/// </remarks>
public static void Equal(
ReadOnlySpan<char> expected,
Span<char> actual,
bool ignoreCase = false,
bool ignoreLineEndingDifferences = false,
bool ignoreWhiteSpaceDifferences = false,
bool ignoreAllWhiteSpace = false) =>
Equal(expected, (ReadOnlySpan<char>)actual, ignoreCase, ignoreLineEndingDifferences, ignoreWhiteSpaceDifferences, ignoreAllWhiteSpace);
/// <summary>
/// Verifies that two strings are equivalent.
/// </summary>
/// <param name="expected">The expected string value.</param>
/// <param name="actual">The actual string value.</param>
/// <param name="ignoreCase">If set to <c>true</c>, ignores cases differences. The invariant culture is used.</param>
/// <param name="ignoreLineEndingDifferences">If set to <c>true</c>, treats \r\n, \r, and \n as equivalent.</param>
/// <param name="ignoreWhiteSpaceDifferences">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks) in any non-zero quantity as equivalent.</param>
/// <param name="ignoreAllWhiteSpace">If set to <c>true</c>, treats horizontal white-space (i.e. spaces, tabs, and others; see remarks), including zero quantities, as equivalent.</param>
/// <exception cref="EqualException">Thrown when the strings are not equivalent.</exception>
/// <remarks>
/// The <paramref name="ignoreWhiteSpaceDifferences"/> and <paramref name="ignoreAllWhiteSpace"/> flags consider
/// the following characters to be white-space:
/// <see href="https://unicode-explorer.com/c/0009">Tab</see> (\t),
/// <see href="https://unicode-explorer.com/c/0020">Space</see> (\u0020),
/// <see href="https://unicode-explorer.com/c/00A0">No-Break Space</see> (\u00A0),
/// <see href="https://unicode-explorer.com/c/1680">Ogham Space Mark</see> (\u1680),
/// <see href="https://unicode-explorer.com/c/180E">Mongolian Vowel Separator</see> (\u180E),
/// <see href="https://unicode-explorer.com/c/2000">En Quad</see> (\u2000),
/// <see href="https://unicode-explorer.com/c/2001">Em Quad</see> (\u2001),
/// <see href="https://unicode-explorer.com/c/2002">En Space</see> (\u2002),
/// <see href="https://unicode-explorer.com/c/2003">Em Space</see> (\u2003),
/// <see href="https://unicode-explorer.com/c/2004">Three-Per-Em Space</see> (\u2004),
/// <see href="https://unicode-explorer.com/c/2005">Four-Per-Em Space</see> (\u2004),
/// <see href="https://unicode-explorer.com/c/2006">Six-Per-Em Space</see> (\u2006),
/// <see href="https://unicode-explorer.com/c/2007">Figure Space</see> (\u2007),
/// <see href="https://unicode-explorer.com/c/2008">Punctuation Space</see> (\u2008),
/// <see href="https://unicode-explorer.com/c/2009">Thin Space</see> (\u2009),
/// <see href="https://unicode-explorer.com/c/200A">Hair Space</see> (\u200A),
/// <see href="https://unicode-explorer.com/c/200B">Zero Width Space</see> (\u200B),
/// <see href="https://unicode-explorer.com/c/202F">Narrow No-Break Space</see> (\u202F),
/// <see href="https://unicode-explorer.com/c/205F">Medium Mathematical Space</see> (\u205F),
/// <see href="https://unicode-explorer.com/c/3000">Ideographic Space</see> (\u3000),
/// and <see href="https://unicode-explorer.com/c/FEFF">Zero Width No-Break Space</see> (\uFEFF).
/// In particular, it does not include carriage return (\r) or line feed (\n), which are covered by
/// <paramref name="ignoreLineEndingDifferences"/>.
/// </remarks>
public static void Equal(
#if XUNIT_NULLABLE
string? expected,
string? actual,
#else
string expected,
string actual,
#endif
bool ignoreCase = false,
bool ignoreLineEndingDifferences = false,
bool ignoreWhiteSpaceDifferences = false,
bool ignoreAllWhiteSpace = false)
{
// This overload is inside #if XUNIT_SPAN because the string version is dynamically converted
// to a span version, so this string version is a backup that then delegates to the span version.
if (expected == null && actual == null)
return;
if (expected == null || actual == null)
throw EqualException.ForMismatchedStrings(expected, actual, -1, -1);
Equal(expected.AsSpan(), actual.AsSpan(), ignoreCase, ignoreLineEndingDifferences, ignoreWhiteSpaceDifferences, ignoreAllWhiteSpace);
}
#endif
/// <summary>
/// Verifies that a string matches a regular expression.
/// </summary>
/// <param name="expectedRegexPattern">The regex pattern expected to match</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="MatchesException">Thrown when the string does not match the regex pattern</exception>
public static void Matches(
[StringSyntax(StringSyntaxAttribute.Regex)]
string expectedRegexPattern,
#if XUNIT_NULLABLE
string? actualString)
#else
string actualString)
#endif
{
GuardArgumentNotNull(nameof(expectedRegexPattern), expectedRegexPattern);
if (actualString == null || !Regex.IsMatch(actualString, expectedRegexPattern))
throw MatchesException.ForMatchNotFound(expectedRegexPattern, actualString);
}
/// <summary>
/// Verifies that a string matches a regular expression.
/// </summary>
/// <param name="expectedRegex">The regex expected to match</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="MatchesException">Thrown when the string does not match the regex</exception>
public static void Matches(
Regex expectedRegex,
#if XUNIT_NULLABLE
string? actualString)
#else
string actualString)
#endif
{
GuardArgumentNotNull(nameof(expectedRegex), expectedRegex);
if (actualString == null || !expectedRegex.IsMatch(actualString))
throw MatchesException.ForMatchNotFound(expectedRegex.ToString(), actualString);
}
/// <summary>
/// Verifies that a string starts with a given string, using the current culture.
/// </summary>
/// <param name="expectedStartString">The string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="ContainsException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
#if XUNIT_NULLABLE
string? expectedStartString,
string? actualString) =>
#else
string expectedStartString,
string actualString) =>
#endif
StartsWith(expectedStartString, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="ContainsException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
#if XUNIT_NULLABLE
string? expectedStartString,
string? actualString,
#else
string expectedStartString,
string actualString,
#endif
StringComparison comparisonType)
{
if (expectedStartString == null || actualString == null || !actualString.StartsWith(expectedStartString, comparisonType))
throw StartsWithException.ForStringNotFound(expectedStartString, actualString);
}
#if XUNIT_SPAN
/// <summary>
/// Verifies that a string starts with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
Memory<char> expectedStartString,
Memory<char> actualString) =>
StartsWith((ReadOnlyMemory<char>)expectedStartString, (ReadOnlyMemory<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
Memory<char> expectedStartString,
ReadOnlyMemory<char> actualString) =>
StartsWith((ReadOnlyMemory<char>)expectedStartString, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
ReadOnlyMemory<char> expectedStartString,
Memory<char> actualString) =>
StartsWith(expectedStartString, (ReadOnlyMemory<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the default StringComparison.CurrentCulture comparison type.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
ReadOnlyMemory<char> expectedStartString,
ReadOnlyMemory<char> actualString) =>
StartsWith(expectedStartString, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
Memory<char> expectedStartString,
Memory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
StartsWith((ReadOnlyMemory<char>)expectedStartString, (ReadOnlyMemory<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
Memory<char> expectedStartString,
ReadOnlyMemory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
StartsWith((ReadOnlyMemory<char>)expectedStartString, actualString, comparisonType);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
ReadOnlyMemory<char> expectedStartString,
Memory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
StartsWith(expectedStartString, (ReadOnlyMemory<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
ReadOnlyMemory<char> expectedStartString,
ReadOnlyMemory<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture)
{
GuardArgumentNotNull(nameof(expectedStartString), expectedStartString);
StartsWith(expectedStartString.Span, actualString.Span, comparisonType);
}
/// <summary>
/// Verifies that a string starts with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
Span<char> expectedStartString,
Span<char> actualString) =>
StartsWith((ReadOnlySpan<char>)expectedStartString, (ReadOnlySpan<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
Span<char> expectedStartString,
ReadOnlySpan<char> actualString) =>
StartsWith((ReadOnlySpan<char>)expectedStartString, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
ReadOnlySpan<char> expectedStartString,
Span<char> actualString) =>
StartsWith(expectedStartString, (ReadOnlySpan<char>)actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the current culture.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
ReadOnlySpan<char> expectedStartString,
ReadOnlySpan<char> actualString) =>
StartsWith(expectedStartString, actualString, StringComparison.CurrentCulture);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
Span<char> expectedStartString,
Span<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
StartsWith((ReadOnlySpan<char>)expectedStartString, (ReadOnlySpan<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
Span<char> expectedStartString,
ReadOnlySpan<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
StartsWith((ReadOnlySpan<char>)expectedStartString, actualString, comparisonType);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
ReadOnlySpan<char> expectedStartString,
Span<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture) =>
StartsWith(expectedStartString, (ReadOnlySpan<char>)actualString, comparisonType);
/// <summary>
/// Verifies that a string starts with a given sub-string, using the given comparison type.
/// </summary>
/// <param name="expectedStartString">The sub-string expected to be at the start of the string</param>
/// <param name="actualString">The string to be inspected</param>
/// <param name="comparisonType">The type of string comparison to perform</param>
/// <exception cref="StartsWithException">Thrown when the string does not start with the expected sub-string</exception>
public static void StartsWith(
ReadOnlySpan<char> expectedStartString,
ReadOnlySpan<char> actualString,
StringComparison comparisonType = StringComparison.CurrentCulture)
{
if (!actualString.StartsWith(expectedStartString, comparisonType))
throw StartsWithException.ForStringNotFound(expectedStartString.ToString(), actualString.ToString());
}
#endif
static readonly HashSet<char> charsLineEndings = new HashSet<char>()
{
'\r', // Carriage Return
'\n', // Line feed
};
static readonly HashSet<char> charsWhitespace = new HashSet<char>()
{
'\t', // Tab
' ', // Space
'\u00A0', // No-Break Space
'\u1680', // Ogham Space Mark
'\u180E', // Mongolian Vowel Separator
'\u2000', // En Quad
'\u2001', // Em Quad
'\u2002', // En Space
'\u2003', // Em Space
'\u2004', // Three-Per-Em Space
'\u2005', // Four-Per-Em Space
'\u2006', // Six-Per-Em Space
'\u2007', // Figure Space
'\u2008', // Punctuation Space
'\u2009', // Thin Space
'\u200A', // Hair Space
'\u200B', // Zero Width Space
'\u202F', // Narrow No-Break Space
'\u205F', // Medium Mathematical Space
'\u3000', // Ideographic Space
'\uFEFF', // Zero Width No-Break Space
};
static int SkipLineEnding(
#if XUNIT_SPAN
ReadOnlySpan<char> value,
#else
string value,
#endif
int index)
{
if (value[index] == '\r')
++index;
if (index < value.Length && value[index] == '\n')
++index;
return index;
}
static int SkipWhitespace(
#if XUNIT_SPAN
ReadOnlySpan<char> value,
#else
string value,
#endif
int index)
{
while (index < value.Length)
{
if (charsWhitespace.Contains(value[index]))
index++;
else
return index;
}
return index;
}
}
}
|