File: ResponseCompressionBodyTest.cs
Web Access
Project: src\src\Middleware\ResponseCompression\test\Microsoft.AspNetCore.ResponseCompression.Tests.csproj (Microsoft.AspNetCore.ResponseCompression.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Microsoft.AspNetCore.Http;
 
namespace Microsoft.AspNetCore.ResponseCompression.Tests;
 
public class ResponseCompressionBodyTest
{
    [Theory]
    [InlineData(null, "Accept-Encoding")]
    [InlineData("", "Accept-Encoding")]
    [InlineData("AnotherHeader", "AnotherHeader,Accept-Encoding")]
    [InlineData("Accept-Encoding", "Accept-Encoding")]
    [InlineData("accepT-encodinG", "accepT-encodinG")]
    [InlineData("accept-encoding,AnotherHeader", "accept-encoding,AnotherHeader")]
    public void OnWrite_AppendsAcceptEncodingToVaryHeader_IfNotPresent(string providedVaryHeader, string expectedVaryHeader)
    {
        var httpContext = new DefaultHttpContext();
        httpContext.Response.Headers.Vary = providedVaryHeader;
        var stream = new ResponseCompressionBody(httpContext, new MockResponseCompressionProvider(flushable: true), new StreamResponseBodyFeature(new MemoryStream()));
 
        stream.Write(new byte[] { }, 0, 0);
 
        Assert.Equal(expectedVaryHeader, httpContext.Response.Headers.Vary);
    }
 
    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public void Write_IsPassedToUnderlyingStream_WhenDisableResponseBuffering(bool flushable)
    {
 
        var buffer = new byte[] { 1 };
 
        var memoryStream = new MemoryStream();
        var stream = new ResponseCompressionBody(new DefaultHttpContext(), new MockResponseCompressionProvider(flushable), new StreamResponseBodyFeature(memoryStream));
 
        stream.DisableBuffering();
        stream.Write(buffer, 0, buffer.Length);
 
        Assert.Equal(buffer, memoryStream.ToArray());
    }
 
    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public async Task WriteAsync_IsPassedToUnderlyingStream_WhenDisableResponseBuffering(bool flushable)
    {
        var buffer = new byte[] { 1 };
 
        var memoryStream = new MemoryStream();
        var stream = new ResponseCompressionBody(new DefaultHttpContext(), new MockResponseCompressionProvider(flushable), new StreamResponseBodyFeature(memoryStream));
 
        stream.DisableBuffering();
        await stream.WriteAsync(buffer, 0, buffer.Length);
 
        Assert.Equal(buffer, memoryStream.ToArray());
    }
 
    [Fact]
    public async Task SendFileAsync_IsPassedToUnderlyingStream_WhenDisableResponseBuffering()
    {
        var memoryStream = new MemoryStream();
 
        var stream = new ResponseCompressionBody(new DefaultHttpContext(), new MockResponseCompressionProvider(true), new StreamResponseBodyFeature(memoryStream));
 
        stream.DisableBuffering();
 
        var path = "testfile1kb.txt";
        await stream.SendFileAsync(path, 0, null, CancellationToken.None);
 
        Assert.Equal(File.ReadAllBytes(path), memoryStream.ToArray());
    }
 
    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public void BeginWrite_IsPassedToUnderlyingStream_WhenDisableResponseBuffering(bool flushable)
    {
        var buffer = new byte[] { 1 };
 
        var memoryStream = new MemoryStream();
 
        var stream = new ResponseCompressionBody(new DefaultHttpContext(), new MockResponseCompressionProvider(flushable), new StreamResponseBodyFeature(memoryStream));
 
        stream.DisableBuffering();
        stream.BeginWrite(buffer, 0, buffer.Length, (o) => { }, null);
 
        Assert.Equal(buffer, memoryStream.ToArray());
    }
 
    private class MockResponseCompressionProvider : IResponseCompressionProvider
    {
        private readonly bool _flushable;
 
        public MockResponseCompressionProvider(bool flushable)
        {
            _flushable = flushable;
        }
 
        public ICompressionProvider GetCompressionProvider(HttpContext context)
        {
            return new MockCompressionProvider(_flushable);
        }
 
        public bool ShouldCompressResponse(HttpContext context)
        {
            return true;
        }
 
        public bool CheckRequestAcceptsCompression(HttpContext context)
        {
            return true;
        }
    }
 
    private class MockCompressionProvider : ICompressionProvider
    {
        public MockCompressionProvider(bool flushable)
        {
            SupportsFlush = flushable;
        }
 
        public string EncodingName { get; }
 
        public bool SupportsFlush { get; }
 
        public Stream CreateStream(Stream outputStream)
        {
            if (SupportsFlush)
            {
                return new BufferedStream(outputStream);
            }
            else
            {
                return new NoFlushBufferedStream(outputStream);
            }
 
        }
    }
 
    private class NoFlushBufferedStream : Stream
    {
        private readonly BufferedStream _bufferedStream;
 
        public NoFlushBufferedStream(Stream outputStream)
        {
            _bufferedStream = new BufferedStream(outputStream);
        }
 
        public override void Flush()
        {
        }
 
        public override int Read(byte[] buffer, int offset, int count) => _bufferedStream.Read(buffer, offset, count);
 
        public override long Seek(long offset, SeekOrigin origin) => _bufferedStream.Seek(offset, origin);
 
        public override void SetLength(long value) => _bufferedStream.SetLength(value);
 
        public override void Write(byte[] buffer, int offset, int count) => _bufferedStream.Write(buffer, offset, count);
 
        public override bool CanRead => _bufferedStream.CanRead;
 
        public override bool CanSeek => _bufferedStream.CanSeek;
 
        public override bool CanWrite => _bufferedStream.CanWrite;
 
        public override long Length => _bufferedStream.Length;
 
        public override long Position
        {
            get { return _bufferedStream.Position; }
            set { _bufferedStream.Position = value; }
        }
 
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            _bufferedStream.Flush();
        }
    }
}