| File: Latency\AddServerTimingHeaderMiddlewareTests.cs | Web Access |
| Project: src\test\Libraries\Microsoft.AspNetCore.Diagnostics.Middleware.Tests\Microsoft.AspNetCore.Diagnostics.Middleware.Tests.csproj (Microsoft.AspNetCore.Diagnostics.Middleware.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; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.Latency; using Xunit; namespace Microsoft.AspNetCore.Diagnostics.Latency.Test; public class AddServerTimingHeaderMiddlewareTests { private static readonly RequestDelegate _stubRequestDelegate = static _ => Task.CompletedTask; [Fact] public async Task Middleware_ReturnsTotalMillisecondsElapsed_InsteadOfFraction() { const long TimeAdvanceMs = 1500L; // We need to use any value greater than 1000 (1 second) using FakeLatencyContext fakeLatencyContextController = new(); Checkpoint checkpoint = new(RequestCheckpointConstants.ElapsedTillHeaders, TimeAdvanceMs, 1000); ArraySegment<Checkpoint> checkpoints = new(new[] { checkpoint }); fakeLatencyContextController.LatencyData = new LatencyData(default, checkpoints, default, default, default); using var serviceProvider = new ServiceCollection() .AddSingleton<ILatencyContext>(_ => fakeLatencyContextController) .BuildServiceProvider(); var context = new DefaultHttpContext { RequestServices = serviceProvider }; var fakeHttpResponseFeature = new FakeHttpResponseFeature(); context.Features.Set<IHttpResponseFeature>(fakeHttpResponseFeature); var middleware = new AddServerTimingHeaderMiddleware(_stubRequestDelegate); await middleware.InvokeAsync(context); await fakeHttpResponseFeature.StartAsync(); var header = context.Response.Headers[AddServerTimingHeaderMiddleware.ServerTimingHeaderName]; Assert.True(header.Count > 0); Assert.Equal($"reqlatency;dur={TimeAdvanceMs}", header[0]); } private sealed class FakeHttpResponseFeature : HttpResponseFeature { private Func<Task> _responseStartingAsync = static () => Task.CompletedTask; public override void OnStarting(Func<object, Task> callback, object state) { var prior = _responseStartingAsync; _responseStartingAsync = async () => { await callback(state); await prior(); }; } public async Task StartAsync() => await _responseStartingAsync(); } private sealed class FakeLatencyContext : ILatencyContext { public LatencyData LatencyData { get; set; } public void AddCheckpoint(CheckpointToken token) => throw new NotSupportedException(); public void AddMeasure(MeasureToken token, long value) => throw new NotSupportedException(); public void Dispose() { // Method intentionally left empty. } public void Freeze() => throw new NotSupportedException(); public void RecordMeasure(MeasureToken _0, long _1) => throw new NotSupportedException(); public void SetTag(TagToken _0, string _1) => throw new NotSupportedException(); } }