TestNameGenerator
TestNameGenerator is able to create test names according to
a coded pattern.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Text;
namespace NUnit.Framework.Internal
{
public class TestNameGenerator
{
private abstract class NameFragment
{
private const string THREE_DOTS = "...";
public virtual string GetText(TestMethod testMethod, object[] args)
{
return GetText(testMethod.Method.MethodInfo, args);
}
public abstract string GetText(MethodInfo method, object[] args);
protected static void AppendGenericTypeNames(StringBuilder sb, MethodInfo method)
{
sb.Append("<");
int num = 0;
Type[] genericArguments = method.GetGenericArguments();
foreach (Type type in genericArguments) {
if (num++ > 0)
sb.Append(",");
sb.Append(type.Name);
}
sb.Append(">");
}
protected static string GetDisplayString(object arg, int stringMax)
{
string text = (arg == null) ? "null" : Convert.ToString(arg, CultureInfo.InvariantCulture);
Array array = arg as Array;
if (array != null && array.Rank == 1) {
if (array.Length == 0)
text = "[]";
else {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("[");
int num = Math.Min(array.Length, 5);
for (int i = 0; i < num; i++) {
if (i > 0)
stringBuilder.Append(", ");
object value = array.GetValue(i);
Array array2 = value as Array;
if (array2 != null && array2.Rank == 1) {
stringBuilder.Append(array2.GetType().GetElementType().Name);
stringBuilder.Append("[]");
} else {
string displayString = GetDisplayString(value, stringMax);
stringBuilder.Append(displayString);
}
}
if (array.Length > 5)
stringBuilder.Append(", ...");
stringBuilder.Append("]");
text = stringBuilder.ToString();
}
} else if (arg is double) {
double num2 = (double)arg;
if (double.IsNaN(num2))
text = "double.NaN";
else if (double.IsPositiveInfinity(num2)) {
text = "double.PositiveInfinity";
} else if (double.IsNegativeInfinity(num2)) {
text = "double.NegativeInfinity";
} else if (num2 == 1.7976931348623157E+308) {
text = "double.MaxValue";
} else if (num2 == -1.7976931348623157E+308) {
text = "double.MinValue";
} else {
if (text.IndexOf('.') == -1)
text += ".0";
text += "d";
}
} else if (arg is float) {
float num3 = (float)arg;
if (float.IsNaN(num3))
text = "float.NaN";
else if (float.IsPositiveInfinity(num3)) {
text = "float.PositiveInfinity";
} else if (float.IsNegativeInfinity(num3)) {
text = "float.NegativeInfinity";
} else if (num3 == 3.4028235E+38) {
text = "float.MaxValue";
} else if (num3 == -3.4028235E+38) {
text = "float.MinValue";
} else {
if (text.IndexOf('.') == -1)
text += ".0";
text += "f";
}
} else if (arg is decimal) {
decimal d = (decimal)arg;
text = ((d == decimal.MinValue) ? "decimal.MinValue" : ((!(d == decimal.MaxValue)) ? (text + "m") : "decimal.MaxValue"));
} else if (arg is long) {
text = (arg.Equals(-9223372036854775808) ? "long.MinValue" : ((!arg.Equals(9223372036854775807)) ? (text + "L") : "long.MaxValue"));
} else if (arg is ulong) {
switch ((ulong)arg) {
case 0:
text = "ulong.MinValue";
break;
case ulong.MaxValue:
text = "ulong.MaxValue";
break;
default:
text += "UL";
break;
}
} else if (arg is string) {
string text2 = (string)arg;
bool flag = stringMax > 0 && text2.Length > stringMax;
int num4 = flag ? (stringMax - "...".Length) : 0;
StringBuilder stringBuilder2 = new StringBuilder();
stringBuilder2.Append("\"");
string text3 = text2;
foreach (char c in text3) {
stringBuilder2.Append(EscapeCharInString(c));
if (flag && stringBuilder2.Length > num4) {
stringBuilder2.Append("...");
break;
}
}
stringBuilder2.Append("\"");
text = stringBuilder2.ToString();
} else if (arg is char) {
text = "'" + EscapeSingleChar((char)arg) + "'";
} else if (arg is int) {
if (arg.Equals(2147483647))
text = "int.MaxValue";
else if (arg.Equals(-2147483648)) {
text = "int.MinValue";
}
} else if (arg is uint) {
if (arg.Equals(uint.MaxValue))
text = "uint.MaxValue";
else if (arg.Equals(0)) {
text = "uint.MinValue";
}
} else if (arg is short) {
if (arg.Equals((short)short.MaxValue))
text = "short.MaxValue";
else if (arg.Equals((short)short.MinValue)) {
text = "short.MinValue";
}
} else if (arg is ushort) {
if (arg.Equals((ushort)ushort.MaxValue))
text = "ushort.MaxValue";
else if (arg.Equals((ushort)0)) {
text = "ushort.MinValue";
}
} else if (arg is byte) {
if (arg.Equals((byte)byte.MaxValue))
text = "byte.MaxValue";
else if (arg.Equals((byte)0)) {
text = "byte.MinValue";
}
} else if (arg is sbyte) {
if (arg.Equals((sbyte)sbyte.MaxValue))
text = "sbyte.MaxValue";
else if (arg.Equals((sbyte)sbyte.MinValue)) {
text = "sbyte.MinValue";
}
}
return text;
}
private static string EscapeSingleChar(char c)
{
if (c == '\'')
return "\\'";
return EscapeControlChar(c);
}
private static string EscapeCharInString(char c)
{
if (c == '"')
return "\\\"";
return EscapeControlChar(c);
}
private static string EscapeControlChar(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 '
':
return $"""{(int)c:""}";
default:
return c.ToString();
}
}
}
private class TestIDFragment : NameFragment
{
public override string GetText(MethodInfo method, object[] args)
{
return "{i}";
}
public override string GetText(TestMethod testMethod, object[] args)
{
return testMethod.Id;
}
}
private class FixedTextFragment : NameFragment
{
private readonly string _text;
public FixedTextFragment(string text)
{
_text = text;
}
public override string GetText(MethodInfo method, object[] args)
{
return _text;
}
}
private class MethodNameFragment : NameFragment
{
public override string GetText(MethodInfo method, object[] args)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(method.Name);
if (method.IsGenericMethod)
NameFragment.AppendGenericTypeNames(stringBuilder, method);
return stringBuilder.ToString();
}
}
private class NamespaceFragment : NameFragment
{
public override string GetText(MethodInfo method, object[] args)
{
return method.DeclaringType.Namespace;
}
}
private class MethodFullNameFragment : NameFragment
{
public override string GetText(MethodInfo method, object[] args)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(method.DeclaringType.FullName);
stringBuilder.Append('.');
stringBuilder.Append(method.Name);
if (method.IsGenericMethod)
NameFragment.AppendGenericTypeNames(stringBuilder, method);
return stringBuilder.ToString();
}
}
private class ClassNameFragment : NameFragment
{
public override string GetText(MethodInfo method, object[] args)
{
return method.DeclaringType.Name;
}
}
private class ClassFullNameFragment : NameFragment
{
public override string GetText(MethodInfo method, object[] args)
{
return method.DeclaringType.FullName;
}
}
private class ArgListFragment : NameFragment
{
private readonly int _maxStringLength;
public ArgListFragment(int maxStringLength)
{
_maxStringLength = maxStringLength;
}
public override string GetText(MethodInfo method, object[] arglist)
{
StringBuilder stringBuilder = new StringBuilder();
if (arglist != null) {
stringBuilder.Append('(');
for (int i = 0; i < arglist.Length; i++) {
if (i > 0)
stringBuilder.Append(",");
stringBuilder.Append(NameFragment.GetDisplayString(arglist[i], _maxStringLength));
}
stringBuilder.Append(')');
}
return stringBuilder.ToString();
}
}
private class ArgumentFragment : NameFragment
{
private readonly int _index;
private readonly int _maxStringLength;
public ArgumentFragment(int index, int maxStringLength)
{
_index = index;
_maxStringLength = maxStringLength;
}
public override string GetText(MethodInfo method, object[] args)
{
if (_index >= args.Length)
return string.Empty;
return NameFragment.GetDisplayString(args[_index], _maxStringLength);
}
}
public static string DefaultTestNamePattern = "{m}{a}";
private readonly string _pattern;
private List<NameFragment> _fragments;
public TestNameGenerator()
{
_pattern = DefaultTestNamePattern;
}
public TestNameGenerator(string pattern)
{
_pattern = pattern;
}
public string GetDisplayName(TestMethod testMethod)
{
return GetDisplayName(testMethod, null);
}
public string GetDisplayName(TestMethod testMethod, object[] args)
{
if (_fragments == null)
_fragments = BuildFragmentList(_pattern);
StringBuilder stringBuilder = new StringBuilder();
foreach (NameFragment fragment in _fragments) {
stringBuilder.Append(fragment.GetText(testMethod, args));
}
return stringBuilder.ToString();
}
private static List<NameFragment> BuildFragmentList(string pattern)
{
List<NameFragment> list = new List<NameFragment>();
int num;
int num3;
for (num = 0; num < pattern.Length; num = num3 + 1) {
int num2 = pattern.IndexOf('{', num);
if (num2 < 0)
break;
num3 = pattern.IndexOf('}', num2);
if (num3 < 0)
break;
if (num2 > num)
list.Add(new FixedTextFragment(pattern.Substring(num, num2 - num)));
string text = pattern.Substring(num2, num3 - num2 + 1);
switch (text) {
case "{m}":
list.Add(new MethodNameFragment());
break;
case "{i}":
list.Add(new TestIDFragment());
break;
case "{n}":
list.Add(new NamespaceFragment());
break;
case "{c}":
list.Add(new ClassNameFragment());
break;
case "{C}":
list.Add(new ClassFullNameFragment());
break;
case "{M}":
list.Add(new MethodFullNameFragment());
break;
case "{a}":
list.Add(new ArgListFragment(0));
break;
case "{0}":
case "{1}":
case "{2}":
case "{3}":
case "{4}":
case "{5}":
case "{6}":
case "{7}":
case "{8}":
case "{9}": {
int index = text[1] - 48;
list.Add(new ArgumentFragment(index, 40));
break;
}
default: {
char c = text[1];
int result;
if (text.Length >= 5 && text[2] == ':' && (c == 'a' || char.IsDigit(c)) && int.TryParse(text.Substring(3, text.Length - 4), out result) && result > 0) {
if (c == 'a')
list.Add(new ArgListFragment(result));
else
list.Add(new ArgumentFragment(c - 48, result));
} else
list.Add(new FixedTextFragment(text));
break;
}
}
}
if (num < pattern.Length)
list.Add(new FixedTextFragment(pattern.Substring(num)));
return list;
}
}
}