From 3bcd8f154b31718df7e77ccfcac3d4133085cf1f Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Wed, 10 Jul 2024 10:26:31 +0100 Subject: [PATCH] fix #56581 - RemoveKeyAsync incorrectly calling RemoveByTagAsync - add Remove tests - drive-by fix async void tests (probably auto-IDE) --- src/Caching/Hybrid/src/Runtime/HybridCache.cs | 2 +- src/Caching/Hybrid/test/FunctionalTests.cs | 82 +++++++++++++++++++ src/Caching/Hybrid/test/SampleUsage.cs | 13 +-- 3 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 src/Caching/Hybrid/test/FunctionalTests.cs diff --git a/src/Caching/Hybrid/src/Runtime/HybridCache.cs b/src/Caching/Hybrid/src/Runtime/HybridCache.cs index 090da99bf867..8c239c82106d 100644 --- a/src/Caching/Hybrid/src/Runtime/HybridCache.cs +++ b/src/Caching/Hybrid/src/Runtime/HybridCache.cs @@ -81,7 +81,7 @@ public virtual ValueTask RemoveAsync(IEnumerable keys, CancellationToken { // for consistency with GetOrCreate/Set: interpret null as "none" null or ICollection { Count: 0 } => default, - ICollection { Count: 1 } => RemoveByTagAsync(keys.Single(), token), + ICollection { Count: 1 } => RemoveAsync(keys.Single(), token), _ => ForEachAsync(this, keys, token), }; diff --git a/src/Caching/Hybrid/test/FunctionalTests.cs b/src/Caching/Hybrid/test/FunctionalTests.cs new file mode 100644 index 000000000000..65993939aa1e --- /dev/null +++ b/src/Caching/Hybrid/test/FunctionalTests.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using Microsoft.Extensions.Caching.Hybrid.Internal; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.Extensions.Caching.Hybrid.Tests; +public class FunctionalTests +{ + static ServiceProvider GetDefaultCache(out DefaultHybridCache cache, Action? config = null) + { + var services = new ServiceCollection(); + config?.Invoke(services); + services.AddHybridCache(); + var provider = services.BuildServiceProvider(); + cache = Assert.IsType(provider.GetRequiredService()); + return provider; + } + + [Fact] + public async Task RemoveSingleKey() + { + using var provider = GetDefaultCache(out var cache); + var key = Me(); + Assert.Equal(42, await cache.GetOrCreateAsync(key, _ => new ValueTask(42))); + + // now slightly different func to show delta; should use cached value initially + await cache.RemoveAsync("unrelated"); + Assert.Equal(42, await cache.GetOrCreateAsync(key, _ => new ValueTask(96))); + + // now remove and repeat - should get updated value + await cache.RemoveAsync(key); + Assert.Equal(96, await cache.GetOrCreateAsync(key, _ => new ValueTask(96))); + } + + [Fact] + public async Task RemoveNoKeyViaArray() + { + using var provider = GetDefaultCache(out var cache); + var key = Me(); + Assert.Equal(42, await cache.GetOrCreateAsync(key, _ => new ValueTask(42))); + + // now slightly different func to show delta; should use same cached value + await cache.RemoveAsync([]); + Assert.Equal(42, await cache.GetOrCreateAsync(key, _ => new ValueTask(96))); + } + + [Fact] + public async Task RemoveSingleKeyViaArray() + { + using var provider = GetDefaultCache(out var cache); + var key = Me(); + Assert.Equal(42, await cache.GetOrCreateAsync(key, _ => new ValueTask(42))); + + // now slightly different func to show delta; should use cached value initially + await cache.RemoveAsync(["unrelated"]); + Assert.Equal(42, await cache.GetOrCreateAsync(key, _ => new ValueTask(96))); + + // now remove and repeat - should get updated value + await cache.RemoveAsync([key]); + Assert.Equal(96, await cache.GetOrCreateAsync(key, _ => new ValueTask(96))); + } + + [Fact] + public async Task RemoveMultipleKeysViaArray() + { + using var provider = GetDefaultCache(out var cache); + var key = Me(); + Assert.Equal(42, await cache.GetOrCreateAsync(key, _ => new ValueTask(42))); + + // now slightly different func to show delta; should use cached value initially + Assert.Equal(42, await cache.GetOrCreateAsync(key, _ => new ValueTask(96))); + + // now remove and repeat - should get updated value + await cache.RemoveAsync([key, "unrelated"]); + Assert.Equal(96, await cache.GetOrCreateAsync(key, _ => new ValueTask(96))); + } + + private static string Me([CallerMemberName] string caller = "") => caller; + +} diff --git a/src/Caching/Hybrid/test/SampleUsage.cs b/src/Caching/Hybrid/test/SampleUsage.cs index f2bcc19de6cd..8d65d5aeff9f 100644 --- a/src/Caching/Hybrid/test/SampleUsage.cs +++ b/src/Caching/Hybrid/test/SampleUsage.cs @@ -1,13 +1,8 @@ // 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.Collections.Generic; using System.ComponentModel; -using System.Linq; -using System.Text; using System.Text.Json; -using System.Threading.Tasks; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.DependencyInjection; @@ -16,7 +11,7 @@ namespace Microsoft.Extensions.Caching.Hybrid.Tests; public class SampleUsage { [Fact] - public async void DistributedCacheWorks() + public async Task DistributedCacheWorks() { var services = new ServiceCollection(); services.AddDistributedMemoryCache(); @@ -36,7 +31,7 @@ public async void DistributedCacheWorks() } [Fact] - public async void HybridCacheWorks() + public async Task HybridCacheWorks() { var services = new ServiceCollection(); services.AddHybridCache(); @@ -56,7 +51,7 @@ public async void HybridCacheWorks() } [Fact] - public async void HybridCacheNoCaptureWorks() + public async Task HybridCacheNoCaptureWorks() { var services = new ServiceCollection(); services.AddHybridCache(); @@ -76,7 +71,7 @@ public async void HybridCacheNoCaptureWorks() } [Fact] - public async void HybridCacheNoCaptureObjReuseWorks() + public async Task HybridCacheNoCaptureObjReuseWorks() { var services = new ServiceCollection(); services.AddHybridCache();