File: HybridCacheEventSourceTests.cs
Web Access
Project: src\test\Libraries\Microsoft.Extensions.Caching.Hybrid.Tests\Microsoft.Extensions.Caching.Hybrid.Tests.csproj (Microsoft.Extensions.Caching.Hybrid.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.Diagnostics.Tracing;
using Microsoft.Extensions.Caching.Hybrid.Internal;
using Xunit.Abstractions;
 
namespace Microsoft.Extensions.Caching.Hybrid.Tests;
 
public class HybridCacheEventSourceTests(ITestOutputHelper log, TestEventListener listener) : IClassFixture<TestEventListener>
{
    // see notes in TestEventListener for context on fixture usage
 
    [SkippableFact]
    public void MatchesNameAndGuid()
    {
        // Assert
        Assert.Equal("Microsoft-Extensions-HybridCache", listener.Source.Name);
        Assert.Equal(Guid.Parse("b3aca39e-5dc9-5e21-f669-b72225b66cfc"), listener.Source.Guid); // from name
    }
 
    [SkippableFact]
    public async Task LocalCacheHit()
    {
        AssertEnabled();
 
        listener.Reset().Source.LocalCacheHit();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdLocalCacheHit, "LocalCacheHit", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("total-local-cache-hits", "Total Local Cache Hits", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task LocalCacheMiss()
    {
        AssertEnabled();
 
        listener.Reset().Source.LocalCacheMiss();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdLocalCacheMiss, "LocalCacheMiss", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("total-local-cache-misses", "Total Local Cache Misses", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task DistributedCacheGet()
    {
        AssertEnabled();
 
        listener.Reset().Source.DistributedCacheGet();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdDistributedCacheGet, "DistributedCacheGet", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("current-distributed-cache-fetches", "Current Distributed Cache Fetches", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task DistributedCacheHit()
    {
        AssertEnabled();
 
        listener.Reset().Source.DistributedCacheGet();
        listener.Reset(resetCounters: false).Source.DistributedCacheHit();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdDistributedCacheHit, "DistributedCacheHit", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("total-distributed-cache-hits", "Total Distributed Cache Hits", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task DistributedCacheMiss()
    {
        AssertEnabled();
 
        listener.Reset().Source.DistributedCacheGet();
        listener.Reset(resetCounters: false).Source.DistributedCacheMiss();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdDistributedCacheMiss, "DistributedCacheMiss", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("total-distributed-cache-misses", "Total Distributed Cache Misses", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task DistributedCacheFailed()
    {
        AssertEnabled();
 
        listener.Reset().Source.DistributedCacheGet();
        listener.Reset(resetCounters: false).Source.DistributedCacheFailed();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdDistributedCacheFailed, "DistributedCacheFailed", EventLevel.Error);
 
        await AssertCountersAsync();
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task DistributedCacheCanceled()
    {
        AssertEnabled();
 
        listener.Reset().Source.DistributedCacheGet();
        listener.Reset(resetCounters: false).Source.DistributedCacheCanceled();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdDistributedCacheCanceled, "DistributedCacheCanceled", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task UnderlyingDataQueryStart()
    {
        AssertEnabled();
 
        listener.Reset().Source.UnderlyingDataQueryStart();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdUnderlyingDataQueryStart, "UnderlyingDataQueryStart", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("current-data-query", "Current Data Queries", 1);
        listener.AssertCounter("total-data-query", "Total Data Queries", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task UnderlyingDataQueryComplete()
    {
        AssertEnabled();
 
        listener.Reset().Source.UnderlyingDataQueryStart();
        listener.Reset(resetCounters: false).Source.UnderlyingDataQueryComplete();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdUnderlyingDataQueryComplete, "UnderlyingDataQueryComplete", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("total-data-query", "Total Data Queries", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task UnderlyingDataQueryFailed()
    {
        AssertEnabled();
 
        listener.Reset().Source.UnderlyingDataQueryStart();
        listener.Reset(resetCounters: false).Source.UnderlyingDataQueryFailed();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdUnderlyingDataQueryFailed, "UnderlyingDataQueryFailed", EventLevel.Error);
 
        await AssertCountersAsync();
        listener.AssertCounter("total-data-query", "Total Data Queries", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task UnderlyingDataQueryCanceled()
    {
        AssertEnabled();
 
        listener.Reset().Source.UnderlyingDataQueryStart();
        listener.Reset(resetCounters: false).Source.UnderlyingDataQueryCanceled();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdUnderlyingDataQueryCanceled, "UnderlyingDataQueryCanceled", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("total-data-query", "Total Data Queries", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task LocalCacheWrite()
    {
        AssertEnabled();
 
        listener.Reset().Source.LocalCacheWrite();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdLocalCacheWrite, "LocalCacheWrite", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("total-local-cache-writes", "Total Local Cache Writes", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task DistributedCacheWrite()
    {
        AssertEnabled();
 
        listener.Reset().Source.DistributedCacheWrite();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdDistributedCacheWrite, "DistributedCacheWrite", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("total-distributed-cache-writes", "Total Distributed Cache Writes", 1);
        listener.AssertRemainingCountersZero();
    }
 
    [SkippableFact]
    public async Task StampedeJoin()
    {
        AssertEnabled();
 
        listener.Reset().Source.StampedeJoin();
        listener.AssertSingleEvent(HybridCacheEventSource.EventIdStampedeJoin, "StampedeJoin", EventLevel.Verbose);
 
        await AssertCountersAsync();
        listener.AssertCounter("total-stampede-joins", "Total Stampede Joins", 1);
        listener.AssertRemainingCountersZero();
    }
 
    private void AssertEnabled()
    {
        // including this data for visibility when tests fail - ETW subsystem can be ... weird
        log.WriteLine($".NET {Environment.Version} on {Environment.OSVersion}, {IntPtr.Size * 8}-bit");
 
        Skip.IfNot(listener.Source.IsEnabled(), "Event source not enabled");
    }
 
    private async Task AssertCountersAsync()
    {
        var count = await listener.TryAwaitCountersAsync();
 
        // ETW counters timing can be painfully unpredictable; generally
        // it'll work fine locally, especially on modern .NET, but:
        // CI servers and netfx in particular - not so much. The tests
        // can still observe and validate the simple events, though, which
        // should be enough to be credible that the eventing system is
        // fundamentally working. We're not meant to be testing that
        // the counters system *itself* works!
 
        Skip.If(count == 0, "No counters received");
    }
}