Add maximum member count to properties/fields in ArgumentFormatter.Format.

This commit is contained in:
Brad Wilson 2014-04-17 08:04:37 -07:00
Родитель 6dff14cd51
Коммит 0b16348230
2 изменённых файлов: 76 добавлений и 16 удалений

Просмотреть файл

@ -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()
{