Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HybridCache - fix RemoveKeyAsync incorrectly calling RemoveByTagAsync #56719

Merged
merged 1 commit into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Caching/Hybrid/src/Runtime/HybridCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public virtual ValueTask RemoveAsync(IEnumerable<string> keys, CancellationToken
{
// for consistency with GetOrCreate/Set: interpret null as "none"
null or ICollection<string> { Count: 0 } => default,
ICollection<string> { Count: 1 } => RemoveByTagAsync(keys.Single(), token),
ICollection<string> { Count: 1 } => RemoveAsync(keys.Single(), token),
_ => ForEachAsync(this, keys, token),
};

Expand Down
82 changes: 82 additions & 0 deletions src/Caching/Hybrid/test/FunctionalTests.cs
Original file line number Diff line number Diff line change
@@ -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<ServiceCollection>? config = null)
{
var services = new ServiceCollection();
config?.Invoke(services);
services.AddHybridCache();
var provider = services.BuildServiceProvider();
cache = Assert.IsType<DefaultHybridCache>(provider.GetRequiredService<HybridCache>());
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<int>(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<int>(96)));

// now remove and repeat - should get updated value
await cache.RemoveAsync(key);
Assert.Equal(96, await cache.GetOrCreateAsync(key, _ => new ValueTask<int>(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<int>(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<int>(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<int>(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<int>(96)));

// now remove and repeat - should get updated value
await cache.RemoveAsync([key]);
Assert.Equal(96, await cache.GetOrCreateAsync(key, _ => new ValueTask<int>(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<int>(42)));

// now slightly different func to show delta; should use cached value initially
Assert.Equal(42, await cache.GetOrCreateAsync(key, _ => new ValueTask<int>(96)));

// now remove and repeat - should get updated value
await cache.RemoveAsync([key, "unrelated"]);
Assert.Equal(96, await cache.GetOrCreateAsync(key, _ => new ValueTask<int>(96)));
}

private static string Me([CallerMemberName] string caller = "") => caller;

}
13 changes: 4 additions & 9 deletions src/Caching/Hybrid/test/SampleUsage.cs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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();
Expand All @@ -36,7 +31,7 @@ public async void DistributedCacheWorks()
}

[Fact]
public async void HybridCacheWorks()
public async Task HybridCacheWorks()
{
var services = new ServiceCollection();
services.AddHybridCache();
Expand All @@ -56,7 +51,7 @@ public async void HybridCacheWorks()
}

[Fact]
public async void HybridCacheNoCaptureWorks()
public async Task HybridCacheNoCaptureWorks()
{
var services = new ServiceCollection();
services.AddHybridCache();
Expand All @@ -76,7 +71,7 @@ public async void HybridCacheNoCaptureWorks()
}

[Fact]
public async void HybridCacheNoCaptureObjReuseWorks()
public async Task HybridCacheNoCaptureObjReuseWorks()
{
var services = new ServiceCollection();
services.AddHybridCache();
Expand Down
Loading