<PackageReference Include="NUnit" Version="4.3.1" />

MsgUtils

static class 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 { [NullableContext(1)] [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) => (object val) => TryFormatTuple(val, TypeHelper.IsTuple, GetValueFromTuple) ?? next(val)); AddFormatter((ValueFormatter next) => delegate(object val) { if (!(val is ValueType)) return next(val); return string.Format(Fmt_ValueType, val); }); AddFormatter((ValueFormatter next) => (object val) => TryFormatKeyValuePair(val) ?? next(val)); AddFormatter((ValueFormatter next) => (object val) => TryFormatTuple(val, TypeHelper.IsValueTuple, GetValueFromValueTuple) ?? next(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) { Array array = val as Array; if (array == null) return next(val); return FormatArray(array); }); } private static string FormatValueWithoutThrowing([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([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(); } [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); } [NullableContext(2)] [return: 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: Nullable(2)] private static object GetValueFromTuple(Type type, string propertyName, object obj) { return type.GetProperty(propertyName)?.GetValue(obj, null); } [return: Nullable(2)] private static object GetValueFromValueTuple(Type type, string propertyName, object obj) { return type.GetField(propertyName)?.GetValue(obj); } [NullableContext(2)] private static string TryFormatTuple(object value, [Nullable(1)] Func<Type, bool> isTuple, [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, [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(); } [NullableContext(2)] [return: NotNullIfNotNull("s")] public static string EscapeControlChars(string s) { int index = 0; return EscapeControlChars(s, ref index); } [NullableContext(2)] [return: NotNullIfNotNull("s")] public static string EscapeControlChars(string s, ref int index) { if (s == null) return null; int num = index; StringBuilder stringBuilder = new StringBuilder(s.Length + 42); for (int i = 0; i < s.Length; i++) { char c = s[i]; string text = EscapeControlChars(c); if (text == null) stringBuilder.Append(c); else { stringBuilder.Append(text); if (num > i) index += text.Length - 1; } } return stringBuilder.ToString(); } [NullableContext(2)] private static string EscapeControlChars(char c) { switch (c) { case '\\': return "\\\\"; case '': return "\\0"; case '': return "\\a"; case '\b': return "\\b"; case ' ': return "\\f"; case '\n': return "\\n"; case '\r': return "\\r"; case '\t': return "\\t"; case ' ': return "\\v"; case '…': case '
': case '
': { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(2, 1); defaultInterpolatedStringHandler.AppendLiteral("\\x"); defaultInterpolatedStringHandler.AppendFormatted((int)c, "X4"); return defaultInterpolatedStringHandler.ToStringAndClear(); } default: return null; } } [NullableContext(2)] [return: NotNullIfNotNull("s")] public static string EscapeNullCharacters(string s) { if (s != null) { StringBuilder stringBuilder = new StringBuilder(s.Length + 42); 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 clipLength, int clipStart) { StringBuilder stringBuilder = new StringBuilder(s.Length + 2 * "...".Length); if (clipStart > 0) stringBuilder.Append("..."); int num = s.Length - clipStart; int count = Math.Min(num, clipLength); stringBuilder.Append(s, clipStart, count); if (num > clipLength) stringBuilder.Append("..."); return stringBuilder.ToString(); } public static string ClipWhenNeeded(string s, int length, int maxDisplayLength, ref int mismatchLocation) { if (length <= maxDisplayLength) return s; maxDisplayLength -= "...".Length; int num; if (mismatchLocation + 5 < maxDisplayLength) num = 0; else if (length - mismatchLocation + 5 < maxDisplayLength) { num = length - maxDisplayLength; } else { maxDisplayLength -= "...".Length; num = mismatchLocation - maxDisplayLength / 2; } if (num > 0) mismatchLocation -= num - "...".Length; return ClipString(s, maxDisplayLength, num); } public static void ClipExpectedAndActual(ref string expected, ref string actual, int maxDisplayLength, ref int mismatchExpected, ref int mismatchActual) { if (mismatchExpected != mismatchActual) throw new ArgumentException("The values for mismatchExpected and mismatchActual should be the same."); int num = Math.Max(expected.Length, actual.Length); if (num > maxDisplayLength) { expected = ClipWhenNeeded(expected, num, maxDisplayLength, ref mismatchExpected); actual = ClipWhenNeeded(actual, num, maxDisplayLength, ref mismatchActual); } } [return: Nullable(0)] public static (int, int) FindMismatchPosition(string expected, string actual, bool ignoreCase, bool ignoreWhiteSpace) { string text = ignoreCase ? expected.ToLower() : expected; string text2 = ignoreCase ? actual.ToLower() : actual; int num = 0; int num2 = 0; while (true) { if (ignoreWhiteSpace) { num = FindNonWhiteSpace(text, num); num2 = FindNonWhiteSpace(text2, num2); } if (num >= text.Length || num2 >= text2.Length) break; if (text[num] != text2[num2]) return (num, num2); num++; num2++; } if (num < text.Length || num2 < text2.Length) return (num, num2); return (-1, -1); } private static int FindNonWhiteSpace(string s, int i) { while (i < s.Length && char.IsWhiteSpace(s[i])) { i++; } return i; } } }