Add maximum member count to properties/fields in ArgumentFormatter.Format.
This commit is contained in:
Родитель
6dff14cd51
Коммит
0b16348230
|
@ -12,8 +12,9 @@ namespace Xunit.Sdk
|
|||
/// </summary>
|
||||
public static class ArgumentFormatter
|
||||
{
|
||||
const int MAX_DEPTH = 3;
|
||||
const int MAX_ENUMERABLE_LENGTH = 5;
|
||||
const int MAX_OBJECT_DEPTH = 3;
|
||||
const int MAX_OBJECT_PARAMETER_COUNT = 5;
|
||||
const int MAX_STRING_LENGTH = 50;
|
||||
|
||||
/// <summary>
|
||||
|
@ -38,6 +39,9 @@ namespace Xunit.Sdk
|
|||
if (value is char)
|
||||
return String.Format("'{0}'", value);
|
||||
|
||||
if (value is DateTime || value is DateTimeOffset)
|
||||
return String.Format("{0:o}", value);
|
||||
|
||||
string stringParameter = value as string;
|
||||
if (stringParameter != null)
|
||||
{
|
||||
|
@ -55,29 +59,40 @@ namespace Xunit.Sdk
|
|||
if (type.GetTypeInfo().IsValueType)
|
||||
return Convert.ToString(value, CultureInfo.CurrentCulture);
|
||||
|
||||
if (depth == MAX_OBJECT_DEPTH)
|
||||
return FormatCompledValue(value, depth, type);
|
||||
}
|
||||
|
||||
private static string FormatCompledValue(object value, int depth, Type type)
|
||||
{
|
||||
if (depth == MAX_DEPTH)
|
||||
return String.Format("{0} {{ ... }}", type.Name);
|
||||
|
||||
var fields = type.GetRuntimeFields()
|
||||
.Where(f => f.IsPublic && !f.IsStatic)
|
||||
.Select(f => new { name = f.Name, value = WrapAndGetFormattedValue(() => f.GetValue(value), depth) })
|
||||
.ToList();
|
||||
.Select(f => new { name = f.Name, value = WrapAndGetFormattedValue(() => f.GetValue(value), depth) });
|
||||
var properties = type.GetRuntimeProperties()
|
||||
.Where(p => p.GetMethod != null && p.GetMethod.IsPublic && !p.GetMethod.IsStatic)
|
||||
.Select(p => new { name = p.Name, value = WrapAndGetFormattedValue(() => p.GetValue(value), depth) })
|
||||
.ToList();
|
||||
var formattedParameters = fields.Concat(properties)
|
||||
.OrderBy(p => p.name)
|
||||
.Select(p => String.Format("{0} = {1}", p.name, p.value))
|
||||
.ToList();
|
||||
var parameterValues = formattedParameters.Count == 0 ? "{ }" : String.Format("{{ {0} }}", String.Join(", ", formattedParameters));
|
||||
.Select(p => new { name = p.Name, value = WrapAndGetFormattedValue(() => p.GetValue(value), depth) });
|
||||
var parameters = fields.Concat(properties)
|
||||
.OrderBy(p => p.name)
|
||||
.Take(MAX_OBJECT_PARAMETER_COUNT + 1)
|
||||
.ToList();
|
||||
|
||||
return String.Format("{0} {1}", type.Name, parameterValues);
|
||||
if (parameters.Count == 0)
|
||||
return String.Format("{0} {{ }}", type.Name);
|
||||
|
||||
var formattedParameters = String.Join(", ", parameters.Take(MAX_OBJECT_PARAMETER_COUNT)
|
||||
.Select(p => String.Format("{0} = {1}", p.name, p.value)));
|
||||
|
||||
if (parameters.Count > MAX_OBJECT_PARAMETER_COUNT)
|
||||
formattedParameters += ", ...";
|
||||
|
||||
return String.Format("{0} {{ {1} }}", type.Name, formattedParameters);
|
||||
}
|
||||
|
||||
private static string FormatEnumerable(IEnumerable<object> enumerableValues, int depth)
|
||||
{
|
||||
if (depth == MAX_OBJECT_DEPTH)
|
||||
if (depth == MAX_DEPTH)
|
||||
return "[...]";
|
||||
|
||||
var values = enumerableValues.Take(MAX_ENUMERABLE_LENGTH + 1).ToList();
|
||||
|
|
|
@ -38,6 +38,22 @@ public class ArgumentFormatterTests
|
|||
Assert.Equal(123.45M.ToString(CultureInfo.CurrentCulture), ArgumentFormatter.Format(123.45M));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void DateTimeValue()
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
Assert.Equal<object>(now.ToString("o"), ArgumentFormatter.Format(now));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void DateTimeOffsetValue()
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
|
||||
Assert.Equal<object>(now.ToString("o"), ArgumentFormatter.Format(now));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TypeValue()
|
||||
{
|
||||
|
@ -75,7 +91,7 @@ public class ArgumentFormatterTests
|
|||
public class ComplexTypes
|
||||
{
|
||||
[Fact]
|
||||
public static void ComplexTypeReturnsValuesInAlphabeticalOrder()
|
||||
public static void ReturnsValuesInAlphabeticalOrder()
|
||||
{
|
||||
var expected = String.Format("MyComplexType {{ MyPublicField = 42, MyPublicProperty = {0} }}", 21.12M.ToString(CultureInfo.CurrentCulture));
|
||||
|
||||
|
@ -116,13 +132,13 @@ public class ArgumentFormatterTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public static void EmptyComplexType()
|
||||
public static void Empty()
|
||||
{
|
||||
Assert.Equal("Object { }", ArgumentFormatter.Format(new object()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void ComplexTypeWithThrowingPropertyGetter()
|
||||
public static void WithThrowingPropertyGetter()
|
||||
{
|
||||
Assert.Equal("ThrowingGetter { MyThrowingProperty = (throws NotImplementedException) }", ArgumentFormatter.Format(new ThrowingGetter()));
|
||||
}
|
||||
|
@ -132,6 +148,35 @@ public class ArgumentFormatterTests
|
|||
public string MyThrowingProperty { get { throw new NotImplementedException(); } }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void LimitsOutputToFirstFewValues()
|
||||
{
|
||||
Assert.Equal(@"Big { MyField1 = 42, MyField2 = ""Hello, world!"", MyProp1 = 21.12, MyProp2 = typeof(ArgumentFormatterTests+ComplexTypes+Big), MyProp3 = 2014-04-17T07:45:23.0000000+00:00, ... }", ArgumentFormatter.Format(new Big()));
|
||||
}
|
||||
|
||||
public class Big
|
||||
{
|
||||
public string MyField2 = "Hello, world!";
|
||||
|
||||
public decimal MyProp1 { get; set; }
|
||||
|
||||
public object MyProp4 { get; set; }
|
||||
|
||||
public object MyProp3 { get; set; }
|
||||
|
||||
public int MyField1 = 42;
|
||||
|
||||
public Type MyProp2 { get; set; }
|
||||
|
||||
public Big()
|
||||
{
|
||||
MyProp1 = 21.12M;
|
||||
MyProp2 = typeof(Big);
|
||||
MyProp3 = new DateTimeOffset(2014, 04, 17, 07, 45, 23, TimeSpan.Zero);
|
||||
MyProp4 = "Should not be shown";
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TypesAreRenderedWithMaximumDepthToPreventInfiniteRecursion()
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче