File: CachedResponseBodyTests.cs
Web Access
Project: src\src\Middleware\ResponseCaching\test\Microsoft.AspNetCore.ResponseCaching.Tests.csproj (Microsoft.AspNetCore.ResponseCaching.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Buffers;
using System.Diagnostics;
using System.IO.Pipelines;
 
namespace Microsoft.AspNetCore.ResponseCaching.Tests;
 
public class CachedResponseBodyTests
{
    private readonly int _timeout = Debugger.IsAttached ? -1 : 5000;
 
    [Fact]
    public void GetSegments()
    {
        var segments = new List<byte[]>();
        var body = new CachedResponseBody(segments, 0);
 
        Assert.Same(segments, body.Segments);
    }
 
    [Fact]
    public void GetLength()
    {
        var segments = new List<byte[]>();
        var body = new CachedResponseBody(segments, 42);
 
        Assert.Equal(42, body.Length);
    }
 
    [Fact]
    public async Task Copy_DoNothingWhenNoSegments()
    {
        var segments = new List<byte[]>();
        var receivedSegments = new List<byte[]>();
        var body = new CachedResponseBody(segments, 0);
 
        var pipe = new Pipe();
        using var cts = new CancellationTokenSource(_timeout);
 
        var receiverTask = ReceiveDataAsync(pipe.Reader, receivedSegments, cts.Token);
        var copyTask = body.CopyToAsync(pipe.Writer, cts.Token).ContinueWith(_ => pipe.Writer.CompleteAsync());
 
        await Task.WhenAll(receiverTask, copyTask);
 
        Assert.Empty(receivedSegments);
    }
 
    [Fact]
    public async Task Copy_SingleSegment()
    {
        var segments = new List<byte[]>
            {
                new byte[] { 1 }
            };
        var receivedSegments = new List<byte[]>();
        var body = new CachedResponseBody(segments, 0);
 
        var pipe = new Pipe();
 
        using var cts = new CancellationTokenSource(_timeout);
 
        var receiverTask = ReceiveDataAsync(pipe.Reader, receivedSegments, cts.Token);
        var copyTask = CopyDataAsync(body, pipe.Writer, cts.Token);
 
        await Task.WhenAll(receiverTask, copyTask);
 
        Assert.Equal(segments, receivedSegments);
    }
 
    [Fact]
    public async Task Copy_MultipleSegments()
    {
        var segments = new List<byte[]>
            {
                new byte[] { 1 },
                new byte[] { 2, 3 }
            };
        var receivedSegments = new List<byte[]>();
        var body = new CachedResponseBody(segments, 0);
 
        var pipe = new Pipe();
 
        using var cts = new CancellationTokenSource(_timeout);
 
        var receiverTask = ReceiveDataAsync(pipe.Reader, receivedSegments, cts.Token);
        var copyTask = CopyDataAsync(body, pipe.Writer, cts.Token);
 
        await Task.WhenAll(receiverTask, copyTask);
 
        Assert.Equal(new byte[] { 1, 2, 3 }, receivedSegments.SelectMany(x => x).ToArray());
    }
 
    static async Task CopyDataAsync(CachedResponseBody body, PipeWriter writer, CancellationToken cancellationToken)
    {
        await body.CopyToAsync(writer, cancellationToken);
        await writer.CompleteAsync();
    }
 
    static async Task ReceiveDataAsync(PipeReader reader, List<byte[]> receivedSegments, CancellationToken cancellationToken)
    {
        while (true)
        {
            var result = await reader.ReadAsync(cancellationToken);
            var buffer = result.Buffer;
 
            foreach (var memory in buffer)
            {
                receivedSegments.Add(memory.ToArray());
            }
 
            reader.AdvanceTo(buffer.End, buffer.End);
 
            if (result.IsCompleted)
            {
                break;
            }
        }
        await reader.CompleteAsync();
    }
}