Test fixes and feedback

This commit is contained in:
Ryan Brandenburg 2019-06-19 09:35:21 -07:00
parent e69cca6461
commit c7b401ffd7
5 changed files with 97 additions and 8 deletions

View File

@ -118,6 +118,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
}
else
{
Log.JsonInputSuccess(_logger, context.ModelType);
return InputFormatterResult.Success(model);
}
}
@ -134,18 +135,26 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
private static class Log
{
private static readonly Action<ILogger, Exception> _jsonInputFormatterException;
private static readonly Action<ILogger, string, Exception> _jsonInputFormatterException;
private static readonly Action<ILogger, string, Exception> _jsonInputSuccess;
static Log()
{
_jsonInputFormatterException = LoggerMessage.Define(
LogLevel.Debug,
new EventId(1, "SystemTextJsonInputException"),
"JSON input formatter threw an exception.");
_jsonInputFormatterException = LoggerMessage.Define<string>(
LogLevel.Debug,
new EventId(1, "SystemTextJsonInputException"),
"JSON input formatter threw an exception: {Message}");
_jsonInputSuccess = LoggerMessage.Define<string>(
LogLevel.Debug,
new EventId(2, "SystemTextJsonInputSuccess"),
"JSON input formatter succeeded, deserializing to type '{TypeName}'");
}
public static void JsonInputException(ILogger logger, Exception exception)
=> _jsonInputFormatterException(logger, exception);
=> _jsonInputFormatterException(logger, exception.Message, exception);
public static void JsonInputSuccess(ILogger logger, Type modelType)
=> _jsonInputSuccess(logger, modelType.FullName, null);
}
}
}

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
@ -18,6 +19,14 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
{
public abstract class JsonInputFormatterTestBase : LoggedTest
{
internal enum Formatter
{
Newtonsoft,
SystemText
}
internal abstract Formatter CurrentFormatter { get; }
[Theory]
[InlineData("application/json", true)]
[InlineData("application/*", false)]
@ -106,6 +115,67 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
Assert.Equal("abcd", stringValue);
}
[Fact]
public async Task JsonFormatter_EscapedKeys_Bracket()
{
// Arrange
var content = "[{\"It[s a key\":1234556}]";
var formatter = GetInputFormatter();
var contentBytes = Encoding.UTF8.GetBytes(content);
var httpContext = GetHttpContext(contentBytes);
var formatterContext = CreateInputFormatterContext(typeof(IEnumerable<IDictionary<string, short>>), httpContext);
// Act
var result = await formatter.ReadAsync(formatterContext);
// Assert
Assert.True(result.HasError);
Assert.Collection(
formatterContext.ModelState.OrderBy(k => k.Key),
kvp =>
{
Assert.Equal("[0][\'It[s a key\']", kvp.Key);
});
}
[Fact]
public async Task JsonFormatter_EscapedKeys()
{
// Arrange
var content = "[{\"It\\\"s a key\": 1234556}]";
var formatter = GetInputFormatter();
var contentBytes = Encoding.UTF8.GetBytes(content);
var httpContext = GetHttpContext(contentBytes);
var formatterContext = CreateInputFormatterContext(
typeof(IEnumerable<IDictionary<string, short>>), httpContext);
// Act
var result = await formatter.ReadAsync(formatterContext);
// Assert
Assert.True(result.HasError);
Assert.Collection(
formatterContext.ModelState.OrderBy(k => k.Key),
kvp =>
{
switch(CurrentFormatter)
{
case Formatter.Newtonsoft:
Assert.Equal("[0]['It\"s a key']", kvp.Key);
break;
case Formatter.SystemText:
Assert.Equal("[0][\'It\\u0022s a key\']", kvp.Key);
break;
default:
throw new NotImplementedException();
}
});
}
[Fact]
public virtual async Task JsonFormatterReadsDateTimeValue()
{
@ -280,7 +350,12 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
// Assert
Assert.True(result.HasError);
Assert.Single(formatterContext.ModelState["names[1].Small"].Errors);
Assert.Collection(
formatterContext.ModelState.OrderBy(k => k.Key),
kvp => {
Assert.Equal("names[1].Small", kvp.Key);
Assert.Single(kvp.Value.Errors);
});
}
[Fact]

View File

@ -13,6 +13,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
{
public class SystemTextJsonInputFormatterTest : JsonInputFormatterTestBase
{
internal override Formatter CurrentFormatter => Formatter.SystemText;
[Fact]
public override Task ReadAsync_AddsModelValidationErrorsToModelState()
{

View File

@ -227,6 +227,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
else
{
addMember = !path.EndsWith("." + member, StringComparison.Ordinal)
&& !path.EndsWith("['" + member + "']", StringComparison.Ordinal)
&& !path.EndsWith("[" + member + "]", StringComparison.Ordinal);
}
}

View File

@ -24,6 +24,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
private static readonly ObjectPoolProvider _objectPoolProvider = new DefaultObjectPoolProvider();
private static readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings();
internal override Formatter CurrentFormatter => Formatter.Newtonsoft;
[Fact]
public async Task Constructor_BuffersRequestBody_UsingDefaultOptions()
{
@ -253,7 +255,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
// Assert
Assert.Collection(
formatterContext.ModelState.OrderBy(k => k),
formatterContext.ModelState.OrderBy(k => k.Key),
kvp =>
{
Assert.Equal("[1]", kvp.Key);