-
Notifications
You must be signed in to change notification settings - Fork 217
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update in-memory cache expiry to take into account user-provided value (
#2514) * Update in-memory cache expiry to take into account user-provided value. Add tests. Update comments. Rename variables. * Typo. * Update comment.
- Loading branch information
Showing
7 changed files
with
123 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
tests/Microsoft.Identity.Web.Test.Common/AssertExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using Xunit; | ||
|
||
namespace Microsoft.Identity.Web.Test.Common | ||
{ | ||
public class Asserts | ||
{ | ||
/// <summary> | ||
/// Verifies that a value is within a given range. | ||
/// </summary> | ||
/// <param name="actual">The actual value to be evaluated</param> | ||
/// <param name="expected">The expected middle of the range.</param> | ||
/// <param name="variance">The variance below and above the expected value.</param> | ||
public static void WithinVariance(TimeSpan actual, TimeSpan expected, TimeSpan variance) | ||
{ | ||
Assert.InRange(actual, expected.Add(-variance), expected.Add(variance)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 56 additions & 26 deletions
82
tests/Microsoft.Identity.Web.Test/MsalTokenCacheProviderTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,76 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using Microsoft.Extensions.Caching.Memory; | ||
using Microsoft.Extensions.Options; | ||
using Microsoft.Identity.Web.Test.Common; | ||
using Microsoft.Identity.Web.Test.Common.TestHelpers; | ||
using Microsoft.Identity.Web.TokenCacheProviders; | ||
using Microsoft.Identity.Web.TokenCacheProviders.InMemory; | ||
using Xunit; | ||
|
||
|
||
namespace Microsoft.Identity.Web.Test | ||
{ | ||
public class MsalTokenCacheProviderTests | ||
{ | ||
/// <summary> | ||
/// Implementation based on a Memory cache, But could be Redis, SQL, ... | ||
/// </summary> | ||
/// <returns>In memory cache.</returns> | ||
private static IMemoryCache GetMemoryCache() | ||
{ | ||
if (s_memoryCache == null) | ||
{ | ||
IOptions<MemoryCacheOptions> options = Options.Create(new MemoryCacheOptions()); | ||
s_memoryCache = new MemoryCache(options); | ||
} | ||
|
||
return s_memoryCache; | ||
} | ||
|
||
private static IMemoryCache? s_memoryCache; | ||
|
||
private static IMsalTokenCacheProvider CreateTokenCacheSerializer() | ||
{ | ||
IOptions<MsalMemoryTokenCacheOptions> msalCacheOptions = Options.Create(new MsalMemoryTokenCacheOptions()); | ||
|
||
MsalMemoryTokenCacheProvider memoryTokenCacheProvider = new MsalMemoryTokenCacheProvider(GetMemoryCache(), msalCacheOptions); | ||
return memoryTokenCacheProvider; | ||
} | ||
|
||
[Fact] | ||
public void CreateTokenCacheSerializerTest() | ||
{ | ||
IMsalTokenCacheProvider tokenCacheProvider = CreateTokenCacheSerializer(); | ||
Assert.NotNull(tokenCacheProvider); | ||
} | ||
|
||
[Theory, MemberData(nameof(CacheExpiryData))] | ||
public void CacheEntryExpiry_SetCorrectly_Test(TimeSpan? optionsCacheExpiry, DateTimeOffset? suggestedCacheExpiry, TimeSpan expectedCacheExpiry) | ||
{ | ||
// Arrange | ||
var msalCacheOptions = new MsalMemoryTokenCacheOptions(); | ||
if (optionsCacheExpiry.HasValue) | ||
{ | ||
msalCacheOptions.AbsoluteExpirationRelativeToNow = optionsCacheExpiry.Value; | ||
} | ||
|
||
var msalCacheProvider = new MsalMemoryTokenCacheProvider(GetMemoryCache(), Options.Create(msalCacheOptions)); | ||
var cacheHints = new CacheSerializerHints() | ||
{ | ||
SuggestedCacheExpiry = suggestedCacheExpiry, | ||
}; | ||
|
||
// Act | ||
TimeSpan? calculatedCacheExpiry = msalCacheProvider.DetermineCacheEntryExpiry(cacheHints); | ||
|
||
// Assert | ||
Assert.NotNull(calculatedCacheExpiry); | ||
// Using InRange because internal logic uses current date/time, which is variable and not constant. | ||
Asserts.WithinVariance(calculatedCacheExpiry.Value, expectedCacheExpiry, TimeSpan.FromMinutes(2)); | ||
} | ||
|
||
// TimeSpan? optionsCacheExpiry, DateTimeOffset? suggestedCacheExpiry, TimeSpan expectedCacheExpiry | ||
public static IEnumerable<object?[]> CacheExpiryData => | ||
new List<object?[]> | ||
{ | ||
new object?[] { null, null, MsalMemoryTokenCacheOptions.DefaultAbsoluteExpirationRelativeToNow }, // no user-provided expiry, no suggested expiry (e.g. user flows) | ||
new object?[] { null, DateTimeOffset.Now.AddHours(5), TimeSpan.FromHours(5) }, // no user-provided expiry, suggested expiry (e.g. app flows) | ||
new object?[] { TimeSpan.FromHours(1), null, TimeSpan.FromHours(1) }, // user-provided expiry, no suggested expiry (e.g. user flows) | ||
new object?[] { TimeSpan.FromHours(1), DateTimeOffset.Now.AddHours(5), TimeSpan.FromHours(1) }, // user-provided expiry shorter than suggested | ||
new object?[] { TimeSpan.FromHours(10), DateTimeOffset.Now.AddHours(5), TimeSpan.FromHours(5) }, // user-provided expiry longer than suggested | ||
new object?[] { null, DateTimeOffset.Now.AddHours(-5), TimeSpan.Zero }, // Negative suggested expiry | ||
}; | ||
|
||
private IMemoryCache GetMemoryCache() | ||
{ | ||
IOptions<MemoryCacheOptions> options = Options.Create(new MemoryCacheOptions()); | ||
return new MemoryCache(options); | ||
} | ||
|
||
private IMsalTokenCacheProvider CreateTokenCacheSerializer() | ||
{ | ||
IOptions<MsalMemoryTokenCacheOptions> msalCacheOptions = Options.Create(new MsalMemoryTokenCacheOptions()); | ||
|
||
MsalMemoryTokenCacheProvider memoryTokenCacheProvider = new MsalMemoryTokenCacheProvider(GetMemoryCache(), msalCacheOptions); | ||
return memoryTokenCacheProvider; | ||
} | ||
} | ||
} |