MsgUtils
Static methods used in creating messages
using NUnit.Framework.Internal;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
namespace NUnit.Framework.Constraints
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
internal static class MsgUtils
{
internal const int DefaultMaxItems = 10;
private const string ELLIPSIS = "...";
private static readonly string Fmt_Null;
private static readonly string Fmt_EmptyString;
private static readonly string Fmt_EmptyCollection;
private static readonly string Fmt_String;
private static readonly string Fmt_Char;
private static readonly string Fmt_DateTime;
private static readonly string Fmt_DateTimeOffset;
private static readonly string Fmt_ValueType;
private static readonly string Fmt_Default;
private static readonly string Fmt_ExceptionThrown;
public static ValueFormatter DefaultValueFormatter { get; set; }
static MsgUtils()
{
Fmt_Null = "null";
Fmt_EmptyString = "<string.Empty>";
Fmt_EmptyCollection = "<empty>";
Fmt_String = "\"{0}\"";
Fmt_Char = "'{0}'";
Fmt_DateTime = "yyyy-MM-dd HH:mm:ss.FFFFFFF";
Fmt_DateTimeOffset = "yyyy-MM-dd HH:mm:ss.FFFFFFFzzz";
Fmt_ValueType = "{0}";
Fmt_Default = "<{0}>";
Fmt_ExceptionThrown = "<! {0} !>";
DefaultValueFormatter = FormatValueWithoutThrowing;
AddFormatter((ValueFormatter next) => delegate(object val) {
if (!(val is ValueType))
return next(val);
return string.Format(Fmt_ValueType, val);
});
AddFormatter((ValueFormatter next) => delegate(object val) {
if (!(val is DateTime))
return next(val);
DateTime dt = (DateTime)val;
return FormatDateTime(dt);
});
AddFormatter((ValueFormatter next) => delegate(object val) {
if (!(val is DateTimeOffset))
return next(val);
DateTimeOffset dto = (DateTimeOffset)val;
return FormatDateTimeOffset(dto);
});
AddFormatter((ValueFormatter next) => delegate(object val) {
if (!(val is decimal))
return next(val);
decimal d2 = (decimal)val;
return FormatDecimal(d2);
});
AddFormatter((ValueFormatter next) => delegate(object val) {
if (!(val is float))
return next(val);
float f = (float)val;
return FormatFloat(f);
});
AddFormatter((ValueFormatter next) => delegate(object val) {
if (!(val is double))
return next(val);
double d = (double)val;
return FormatDouble(d);
});
AddFormatter((ValueFormatter next) => delegate(object val) {
if (!(val is char))
return next(val);
return string.Format(Fmt_Char, val);
});
AddFormatter((ValueFormatter next) => delegate(object val) {
IEnumerable enumerable = val as IEnumerable;
if (enumerable == null)
return next(val);
return FormatCollection(enumerable, 0, 10);
});
AddFormatter((ValueFormatter next) => delegate(object val) {
string text = val as string;
if (text == null)
return next(val);
return FormatString(text);
});
AddFormatter((ValueFormatter next) => delegate(object val) {
if (!(val is DictionaryEntry))
return next(val);
DictionaryEntry dictionaryEntry = (DictionaryEntry)val;
return FormatKeyValuePair(dictionaryEntry.Key, dictionaryEntry.Value);
});
AddFormatter((ValueFormatter next) => delegate(object val) {
if (!val.GetType().IsArray)
return next(val);
return FormatArray((Array)val);
});
AddFormatter((ValueFormatter next) => (object val) => TryFormatKeyValuePair(val) ?? next(val));
AddFormatter((ValueFormatter next) => (object val) => TryFormatTuple(val, TypeHelper.IsTuple, GetValueFromTuple) ?? next(val));
AddFormatter((ValueFormatter next) => (object val) => TryFormatTuple(val, TypeHelper.IsValueTuple, GetValueFromValueTuple) ?? next(val));
}
private static string FormatValueWithoutThrowing([System.Runtime.CompilerServices.Nullable(2)] object val)
{
string arg;
try {
arg = val?.ToString();
} catch (Exception ex) {
return string.Format(Fmt_ExceptionThrown, ex.GetType().Name + " was thrown by " + val.GetType().Name + ".ToString()");
}
return string.Format(Fmt_Default, arg);
}
public static void AddFormatter(ValueFormatterFactory formatterFactory)
{
DefaultValueFormatter = formatterFactory(DefaultValueFormatter);
}
public static string FormatValue([System.Runtime.CompilerServices.Nullable(2)] object val)
{
if (val == null)
return Fmt_Null;
TestExecutionContext currentContext = TestExecutionContext.CurrentContext;
if (currentContext != null)
return currentContext.CurrentValueFormatter(val);
return DefaultValueFormatter(val);
}
public static string FormatCollection(IEnumerable collection, long start = 0, int max = 10)
{
int num = 0;
int num2 = 0;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("< ");
if (start > 0)
stringBuilder.Append("...");
foreach (object item in collection) {
if (num2++ >= start) {
if (++num > max)
break;
if (num > 1)
stringBuilder.Append(", ");
stringBuilder.Append(FormatValue(item));
}
}
if (num == 0)
return Fmt_EmptyCollection;
if (num > max)
stringBuilder.Append("...");
stringBuilder.Append(" >");
return stringBuilder.ToString();
}
private static string FormatArray(Array array)
{
if (array.Length == 0)
return Fmt_EmptyCollection;
int rank = array.Rank;
int[] array2 = new int[rank];
int num = 1;
int num2 = rank;
while (--num2 >= 0) {
num = (array2[num2] = num * array.GetLength(num2));
}
int num3 = 0;
StringBuilder stringBuilder = new StringBuilder();
foreach (object item in array) {
if (num3 > 0)
stringBuilder.Append(", ");
bool flag = false;
for (int i = 0; i < rank; i++) {
flag = (flag || num3 % array2[i] == 0);
if (flag)
stringBuilder.Append("< ");
}
stringBuilder.Append(FormatValue(item));
num3++;
bool flag2 = false;
for (int j = 0; j < rank; j++) {
flag2 = (flag2 || num3 % array2[j] == 0);
if (flag2)
stringBuilder.Append(" >");
}
}
return stringBuilder.ToString();
}
[System.Runtime.CompilerServices.NullableContext(2)]
private static string TryFormatKeyValuePair(object value)
{
if (value == null)
return null;
Type type = value.GetType();
if (!type.IsGenericType)
return null;
Type genericTypeDefinition = type.GetGenericTypeDefinition();
if (genericTypeDefinition != typeof(KeyValuePair<, >))
return null;
object key = type.GetProperty("Key")?.GetValue(value, null);
object value2 = type.GetProperty("Value")?.GetValue(value, null);
return FormatKeyValuePair(key, value2);
}
[System.Runtime.CompilerServices.NullableContext(2)]
[return: System.Runtime.CompilerServices.Nullable(1)]
private static string FormatKeyValuePair(object key, object value)
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(4, 2);
defaultInterpolatedStringHandler.AppendLiteral("[");
defaultInterpolatedStringHandler.AppendFormatted(FormatValue(key));
defaultInterpolatedStringHandler.AppendLiteral(", ");
defaultInterpolatedStringHandler.AppendFormatted(FormatValue(value));
defaultInterpolatedStringHandler.AppendLiteral("]");
return defaultInterpolatedStringHandler.ToStringAndClear();
}
[return: System.Runtime.CompilerServices.Nullable(2)]
private static object GetValueFromTuple(Type type, string propertyName, object obj)
{
return type.GetProperty(propertyName)?.GetValue(obj, null);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
private static object GetValueFromValueTuple(Type type, string propertyName, object obj)
{
return type.GetField(propertyName)?.GetValue(obj);
}
[System.Runtime.CompilerServices.NullableContext(2)]
private static string TryFormatTuple(object value, [System.Runtime.CompilerServices.Nullable(1)] Func<Type, bool> isTuple, [System.Runtime.CompilerServices.Nullable(new byte[] {
1,
1,
1,
1,
2
})] Func<Type, string, object, object> getValue)
{
if (value == null)
return null;
Type type = value.GetType();
if (!isTuple(type))
return null;
return FormatTuple(value, true, getValue);
}
private static string FormatTuple(object value, bool printParentheses, [System.Runtime.CompilerServices.Nullable(new byte[] {
1,
1,
1,
1,
2
})] Func<Type, string, object, object> getValue)
{
Type type = value.GetType();
int num = type.GetGenericArguments().Length;
StringBuilder stringBuilder = new StringBuilder();
if (printParentheses)
stringBuilder.Append("(");
for (int i = 0; i < num; i++) {
if (i > 0)
stringBuilder.Append(", ");
bool flag = i < 7;
string arg = flag ? ("Item" + (i + 1).ToString()) : "Rest";
object obj = getValue(type, arg, value);
string value2 = flag ? FormatValue(obj) : FormatTuple(obj, false, getValue);
stringBuilder.Append(value2);
}
if (printParentheses)
stringBuilder.Append(")");
return stringBuilder.ToString();
}
private static string FormatString(string s)
{
if (!(s == string.Empty))
return string.Format(Fmt_String, s);
return Fmt_EmptyString;
}
private static string FormatDouble(double d)
{
if (double.IsNaN(d) || double.IsInfinity(d))
return d.ToString();
string text = d.ToString("G17", CultureInfo.InvariantCulture);
if (text.IndexOf('.') > 0)
return text + "d";
return text + ".0d";
}
private static string FormatFloat(float f)
{
if (float.IsNaN(f) || float.IsInfinity(f))
return f.ToString();
string text = f.ToString("G9", CultureInfo.InvariantCulture);
if (text.IndexOf('.') > 0)
return text + "f";
return text + ".0f";
}
private static string FormatDecimal(decimal d)
{
return d.ToString("G29", CultureInfo.InvariantCulture) + "m";
}
private static string FormatDateTime(DateTime dt)
{
return dt.ToString(Fmt_DateTime, CultureInfo.InvariantCulture);
}
private static string FormatDateTimeOffset(DateTimeOffset dto)
{
return dto.ToString(Fmt_DateTimeOffset, CultureInfo.InvariantCulture);
}
public static string GetTypeRepresentation(object obj)
{
Array array = obj as Array;
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler;
if (array == null) {
defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(2, 1);
defaultInterpolatedStringHandler.AppendLiteral("<");
defaultInterpolatedStringHandler.AppendFormatted(obj.GetType());
defaultInterpolatedStringHandler.AppendLiteral(">");
return defaultInterpolatedStringHandler.ToStringAndClear();
}
StringBuilder stringBuilder = new StringBuilder();
Type type = array.GetType();
int num = 0;
while (type.IsArray) {
type = type.GetElementType();
num++;
}
stringBuilder.Append(type);
stringBuilder.Append('[');
for (int i = 0; i < array.Rank; i++) {
if (i > 0)
stringBuilder.Append(',');
stringBuilder.Append(array.GetLength(i));
}
stringBuilder.Append(']');
while (--num > 0) {
stringBuilder.Append("[]");
}
defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(2, 1);
defaultInterpolatedStringHandler.AppendLiteral("<");
defaultInterpolatedStringHandler.AppendFormatted(stringBuilder);
defaultInterpolatedStringHandler.AppendLiteral(">");
return defaultInterpolatedStringHandler.ToStringAndClear();
}
[System.Runtime.CompilerServices.NullableContext(2)]
[return: NotNullIfNotNull("s")]
public static string EscapeControlChars(string s)
{
if (s != null) {
StringBuilder stringBuilder = new StringBuilder();
string text = s;
foreach (char c in text) {
switch (c) {
case '\\':
stringBuilder.Append("\\\\");
break;
case ' ':
stringBuilder.Append("\\0");
break;
case '':
stringBuilder.Append("\\a");
break;
case '\b':
stringBuilder.Append("\\b");
break;
case '':
stringBuilder.Append("\\f");
break;
case '\n':
stringBuilder.Append("\\n");
break;
case '\r':
stringBuilder.Append("\\r");
break;
case '\t':
stringBuilder.Append("\\t");
break;
case '':
stringBuilder.Append("\\v");
break;
case '
':
case '
':
case '
': {
StringBuilder stringBuilder2 = stringBuilder;
StringBuilder stringBuilder3 = stringBuilder2;
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2);
handler.AppendLiteral("\\x");
handler.AppendFormatted((int)c, "X4");
stringBuilder3.Append(ref handler);
break;
}
default:
stringBuilder.Append(c);
break;
}
}
s = stringBuilder.ToString();
}
return s;
}
[System.Runtime.CompilerServices.NullableContext(2)]
[return: NotNullIfNotNull("s")]
public static string EscapeNullCharacters(string s)
{
if (s != null) {
StringBuilder stringBuilder = new StringBuilder();
string text = s;
foreach (char c in text) {
if (c == ' ')
stringBuilder.Append("\\0");
else
stringBuilder.Append(c);
}
s = stringBuilder.ToString();
}
return s;
}
public static string GetArrayIndicesAsString(int[] indices)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append('[');
for (int i = 0; i < indices.Length; i++) {
if (i > 0)
stringBuilder.Append(',');
stringBuilder.Append(indices[i].ToString());
}
stringBuilder.Append(']');
return stringBuilder.ToString();
}
public static int[] GetArrayIndicesFromCollectionIndex(IEnumerable collection, long index)
{
Array array = collection as Array;
int num = array?.Rank ?? 1;
int[] array2 = new int[num];
int num2 = num;
while (--num2 > 0) {
int length = array.GetLength(num2);
array2[num2] = (int)index % length;
index /= length;
}
array2[0] = (int)index;
return array2;
}
public static string ClipString(string s, int maxStringLength, int clipStart)
{
int num = maxStringLength;
StringBuilder stringBuilder = new StringBuilder();
if (clipStart > 0) {
num -= "...".Length;
stringBuilder.Append("...");
}
if (s.Length - clipStart > num) {
num -= "...".Length;
stringBuilder.Append(s.Substring(clipStart, num));
stringBuilder.Append("...");
} else if (clipStart > 0) {
stringBuilder.Append(s.Substring(clipStart));
} else {
stringBuilder.Append(s);
}
return stringBuilder.ToString();
}
public static void ClipExpectedAndActual(ref string expected, ref string actual, int maxDisplayLength, int mismatch)
{
int num = Math.Max(expected.Length, actual.Length);
if (num > maxDisplayLength) {
int num2 = maxDisplayLength - "...".Length;
int num3 = num - num2;
if (num3 > mismatch)
num3 = Math.Max(0, mismatch - num2 / 2);
expected = ClipString(expected, maxDisplayLength, num3);
actual = ClipString(actual, maxDisplayLength, num3);
}
}
public static int FindMismatchPosition(string expected, string actual, int istart, bool ignoreCase)
{
int num = Math.Min(expected.Length, actual.Length);
string text = ignoreCase ? expected.ToLower() : expected;
string text2 = ignoreCase ? actual.ToLower() : actual;
for (int i = istart; i < num; i++) {
if (text[i] != text2[i])
return i;
}
if (expected.Length != actual.Length)
return num;
return -1;
}
}
}