/// <summary> /// Creates a new <see cref="NewtonsoftJsonResultExecutor"/>. /// </summary> /// <param name="writerFactory">The <see cref="IHttpResponseStreamWriterFactory"/>.</param> /// <param name="logger">The <see cref="ILogger{NewtonsoftJsonResultExecutor}"/>.</param> /// <param name="mvcOptions">Accessor to <see cref="MvcOptions"/>.</param> /// <param name="jsonOptions">Accessor to <see cref="MvcNewtonsoftJsonOptions"/>.</param> /// <param name="charPool">The <see cref="ArrayPool{Char}"/> for creating <see cref="T:char[]"/> buffers.</param> public NewtonsoftJsonResultExecutor( IHttpResponseStreamWriterFactory writerFactory, ILogger <NewtonsoftJsonResultExecutor> logger, IOptions <MvcOptions> mvcOptions, IOptions <MvcNewtonsoftJsonOptions> jsonOptions, ArrayPool <char> charPool) { if (writerFactory == null) { throw new ArgumentNullException(nameof(writerFactory)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (jsonOptions == null) { throw new ArgumentNullException(nameof(jsonOptions)); } if (charPool == null) { throw new ArgumentNullException(nameof(charPool)); } _writerFactory = writerFactory; _logger = logger; _mvcOptions = mvcOptions?.Value ?? throw new ArgumentNullException(nameof(mvcOptions)); _jsonOptions = jsonOptions.Value; _charPool = new JsonArrayPool <char>(charPool); _asyncEnumerableReaderFactory = new AsyncEnumerableReader(_mvcOptions); }
/// <summary> /// Initializes a new <see cref="NewtonsoftJsonOutputFormatter"/> instance. /// </summary> /// <param name="serializerSettings"> /// The <see cref="JsonSerializerSettings"/>. Should be either the application-wide settings /// (<see cref="MvcNewtonsoftJsonOptions.SerializerSettings"/>) or an instance /// <see cref="JsonSerializerSettingsProvider.CreateSerializerSettings"/> initially returned. /// </param> /// <param name="charPool">The <see cref="ArrayPool{Char}"/>.</param> /// <param name="mvcOptions">The <see cref="MvcOptions"/>.</param> /// <param name="jsonOptions">The <see cref="MvcNewtonsoftJsonOptions"/>.</param> public NewtonsoftJsonOutputFormatter( JsonSerializerSettings serializerSettings, ArrayPool <char> charPool, MvcOptions mvcOptions, MvcNewtonsoftJsonOptions?jsonOptions) { if (serializerSettings == null) { throw new ArgumentNullException(nameof(serializerSettings)); } if (charPool == null) { throw new ArgumentNullException(nameof(charPool)); } SerializerSettings = serializerSettings; _charPool = new JsonArrayPool <char>(charPool); _mvcOptions = mvcOptions ?? throw new ArgumentNullException(nameof(mvcOptions)); _jsonOptions = jsonOptions; SupportedEncodings.Add(Encoding.UTF8); SupportedEncodings.Add(Encoding.Unicode); SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationJson); SupportedMediaTypes.Add(MediaTypeHeaderValues.TextJson); SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationAnyJsonSyntax); _asyncEnumerableReaderFactory = new AsyncEnumerableReader(_mvcOptions); }
public async Task Reader_ThrowsIfIAsyncEnumerableThrows() { // Arrange var enumerable = ThrowingAsyncEnumerable(); var options = new MvcOptions(); var readerFactory = new AsyncEnumerableReader(options); // Act & Assert Assert.True(readerFactory.TryGetReader(enumerable.GetType(), out var reader)); await Assert.ThrowsAsync <TimeZoneNotFoundException>(() => reader(enumerable, default)); }
public void TryGetReader_ReturnsFalse_IfTypeIsNotIAsyncEnumerable(Type type) { // Arrange var options = new MvcOptions(); var readerFactory = new AsyncEnumerableReader(options); var asyncEnumerable = TestEnumerable(); // Act var result = readerFactory.TryGetReader(type, out var reader); // Assert Assert.False(result); }
public void TryGetReader_ReturnsCachedDelegate_WhenTypeImplementsMultipleIAsyncEnumerableContracts() { // Arrange var options = new MvcOptions(); var readerFactory = new AsyncEnumerableReader(options); var asyncEnumerable1 = new MultiAsyncEnumerable(); var asyncEnumerable2 = new MultiAsyncEnumerable(); // Act Assert.True(readerFactory.TryGetReader(asyncEnumerable1.GetType(), out var reader1)); Assert.True(readerFactory.TryGetReader(asyncEnumerable2.GetType(), out var reader2)); // Assert Assert.Same(reader1, reader2); }
public void TryGetReader_ReturnsCachedDelegate() { // Arrange var options = new MvcOptions(); var readerFactory = new AsyncEnumerableReader(options); var asyncEnumerable1 = TestEnumerable(); var asyncEnumerable2 = TestEnumerable(); // Act Assert.True(readerFactory.TryGetReader(asyncEnumerable1.GetType(), out var reader1)); Assert.True(readerFactory.TryGetReader(asyncEnumerable2.GetType(), out var reader2)); // Assert Assert.Same(reader1, reader2); }
public void TryGetReader_ReturnsDifferentInstancesForDifferentEnumerables() { // Arrange var options = new MvcOptions(); var readerFactory = new AsyncEnumerableReader(options); var enumerable1 = TestEnumerable(); var enumerable2 = TestEnumerable2(); // Act Assert.True(readerFactory.TryGetReader(enumerable1.GetType(), out var reader1)); Assert.True(readerFactory.TryGetReader(enumerable2.GetType(), out var reader2)); // Assert Assert.NotSame(reader1, reader2); }
public async Task CachedDelegate_CanReadEnumerableInstanceMultipleTimes_ThatProduceDifferentResults() { // Arrange var options = new MvcOptions(); var readerFactory = new AsyncEnumerableReader(options); var asyncEnumerable1 = TestEnumerable(); var asyncEnumerable2 = TestEnumerable(4); // Act Assert.True(readerFactory.TryGetReader(asyncEnumerable1.GetType(), out var reader)); // Assert Assert.Equal(new[] { "0", "1", "2" }, await reader(asyncEnumerable1, default)); Assert.Equal(new[] { "0", "1", "2", "3" }, await reader(asyncEnumerable2, default)); }
public async Task Reader_PassesCancellationTokenToIAsyncEnumerable() { // Arrange var enumerable = AsyncEnumerable(); var options = new MvcOptions(); CancellationToken token = default; var readerFactory = new AsyncEnumerableReader(options); var cts = new CancellationTokenSource(); // Act & Assert Assert.True(readerFactory.TryGetReader(enumerable.GetType(), out var reader)); await reader(enumerable, cts.Token); cts.Cancel(); Assert.Equal(cts.Token, token); async IAsyncEnumerable <string> AsyncEnumerable([EnumeratorCancellation] CancellationToken cancellationToken = default)
public async Task TryGetReader_ReturnsReaderForIAsyncEnumerableOfValueType() { // Arrange var options = new MvcOptions(); var readerFactory = new AsyncEnumerableReader(options); var asyncEnumerable = PrimitiveEnumerable(); // Act var result = readerFactory.TryGetReader(asyncEnumerable.GetType(), out var reader); // Assert Assert.True(result); var readCollection = await reader(asyncEnumerable, default); var collection = Assert.IsAssignableFrom <ICollection <int> >(readCollection); Assert.Equal(new[] { 0, 1, 2, }, collection); }
public async Task TryGetReader_ReturnsReaderForIAsyncEnumerable() { // Arrange var options = new MvcOptions(); var readerFactory = new AsyncEnumerableReader(options); var asyncEnumerable = TestEnumerable(); // Act var result = readerFactory.TryGetReader(asyncEnumerable.GetType(), out var reader); // Assert Assert.True(result); var readCollection = await reader(asyncEnumerable, default); var collection = Assert.IsAssignableFrom <ICollection <string> >(readCollection); Assert.Equal(new[] { "0", "1", "2", }, collection); }
public async Task Reader_ThrowsIfBufferLimitIsReached() { // Arrange var enumerable = TestEnumerable(11); var expected = $"'AsyncEnumerableReader' reached the configured maximum size of the buffer when enumerating a value of type '{enumerable.GetType()}'. " + "This limit is in place to prevent infinite streams of 'IAsyncEnumerable<>' from continuing indefinitely. If this is not a programming mistake, " + $"consider ways to reduce the collection size, or consider manually converting '{enumerable.GetType()}' into a list rather than increasing the limit."; var options = new MvcOptions { MaxIAsyncEnumerableBufferLimit = 10 }; var readerFactory = new AsyncEnumerableReader(options); // Act Assert.True(readerFactory.TryGetReader(enumerable.GetType(), out var reader)); var ex = await Assert.ThrowsAsync <InvalidOperationException>(() => reader(enumerable, default)); // Assert Assert.Equal(expected, ex.Message); }
public async Task Reader_ReadsIAsyncEnumerable_ImplementingMultipleAsyncEnumerableInterfaces() { // This test ensures the reader does not fail if you have a type that implements IAsyncEnumerable for multiple Ts // Arrange var options = new MvcOptions(); var readerFactory = new AsyncEnumerableReader(options); var asyncEnumerable = new MultiAsyncEnumerable(); // Act var result = readerFactory.TryGetReader(asyncEnumerable.GetType(), out var reader); // Assert Assert.True(result); var readCollection = await reader(asyncEnumerable, default); var collection = Assert.IsAssignableFrom <ICollection <object> >(readCollection); Assert.Equal(new[] { "0", "1", "2", }, collection); }