Skip to content

Commit 76969fa

Browse files
Add testcases for time window filter cache entry (#445)
* add test for time window filter cache entry * check there is no cache entry before evaluation * track the count of timewindow calculation * use customized IMemoryCache
1 parent 325271b commit 76969fa

File tree

3 files changed

+187
-63
lines changed

3 files changed

+187
-63
lines changed

tests/Tests.FeatureManagement/FeatureManagementTest.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,13 @@ public async Task TimeWindow()
849849
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:Start", DateTimeOffset.UtcNow.AddDays(-2).ToString("r"));
850850
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:End", DateTimeOffset.UtcNow.AddDays(-1).ToString("r"));
851851
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:Recurrence:Pattern:Type", "Weekly");
852+
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:Recurrence:Pattern:DaysOfWeek:0", "Monday");
853+
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:Recurrence:Pattern:DaysOfWeek:1", "Tuesday");
854+
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:Recurrence:Pattern:DaysOfWeek:2", "Wednesday");
855+
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:Recurrence:Pattern:DaysOfWeek:3", "Thursday");
856+
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:Recurrence:Pattern:DaysOfWeek:4", "Friday");
857+
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:Recurrence:Pattern:DaysOfWeek:5", "Saturday");
858+
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:Recurrence:Pattern:DaysOfWeek:6", "Sunday");
852859
Environment.SetEnvironmentVariable("feature_management:feature_flags:6:conditions:client_filters:0:parameters:Recurrence:Range:Type", "NoEnd");
853860

854861
foreach (DayOfWeek day in Enum.GetValues(typeof(DayOfWeek)))
@@ -874,11 +881,7 @@ public async Task TimeWindow()
874881
Assert.False(await featureManager.IsEnabledAsync(feature4));
875882
Assert.True(await featureManager.IsEnabledAsync(feature5));
876883
Assert.False(await featureManager.IsEnabledAsync(feature6));
877-
878-
for (int i = 0; i < 10; i++)
879-
{
880-
Assert.True(await featureManager.IsEnabledAsync(feature7));
881-
}
884+
Assert.True(await featureManager.IsEnabledAsync(feature7));
882885
}
883886

884887
[Fact]

tests/Tests.FeatureManagement/RecurrenceEvaluation.cs

Lines changed: 134 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,17 +1617,17 @@ public void FindWeeklyClosestStartTest()
16171617
[Fact]
16181618
public async Task RecurrenceEvaluationThroughCacheTest()
16191619
{
1620-
OnDemandClock mockedTimeProvider = new OnDemandClock();
1620+
var mockedTimeProvider = new OnDemandClock();
16211621

1622-
var mockedTimeWindowFilter = new TimeWindowFilter()
1622+
using (var cache = new TestCache())
16231623
{
1624-
Cache = new MemoryCache(new MemoryCacheOptions()),
1625-
SystemClock = mockedTimeProvider
1626-
};
1624+
var mockedTimeWindowFilter = new TimeWindowFilter()
1625+
{
1626+
Cache = cache,
1627+
SystemClock = mockedTimeProvider
1628+
};
16271629

1628-
var context = new FeatureFilterEvaluationContext()
1629-
{
1630-
Settings = new TimeWindowFilterSettings()
1630+
TimeWindowFilterSettings settings = new TimeWindowFilterSettings()
16311631
{
16321632
Start = DateTimeOffset.Parse("2024-2-1T00:00:00+08:00"), // Thursday
16331633
End = DateTimeOffset.Parse("2024-2-1T12:00:00+08:00"),
@@ -1644,43 +1644,80 @@ public async Task RecurrenceEvaluationThroughCacheTest()
16441644
EndDate = DateTimeOffset.Parse("2024-2-5T12:00:00+08:00")
16451645
}
16461646
}
1647-
}
1648-
};
1647+
};
16491648

1650-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-2T23:00:00+08:00");
1649+
var context = new FeatureFilterEvaluationContext()
1650+
{
1651+
Settings = settings
1652+
};
16511653

1652-
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1654+
DateTimeOffset? closestStart;
1655+
Assert.False(cache.TryGetValue(settings, out closestStart));
1656+
Assert.Equal(0, cache.CountOfEntryCreation);
16531657

1654-
for (int i = 0; i < 12; i++)
1655-
{
1656-
mockedTimeProvider.UtcNow = mockedTimeProvider.UtcNow.AddHours(1);
1657-
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1658-
}
1658+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-2T23:00:00+08:00");
1659+
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1660+
Assert.True(cache.TryGetValue(settings, out closestStart));
1661+
Assert.Equal(DateTimeOffset.Parse("2024-2-3T00:00:00+08:00"), closestStart);
1662+
Assert.Equal(1, cache.CountOfEntryCreation);
16591663

1660-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-3T11:59:59+08:00");
1661-
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1664+
for (int i = 0; i < 12; i++)
1665+
{
1666+
mockedTimeProvider.UtcNow = mockedTimeProvider.UtcNow.AddHours(1);
1667+
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1668+
Assert.True(cache.TryGetValue(settings, out closestStart));
1669+
Assert.Equal(DateTimeOffset.Parse("2024-2-3T00:00:00+08:00"), closestStart);
1670+
Assert.Equal(1, cache.CountOfEntryCreation);
1671+
}
16621672

1663-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-3T12:00:00+08:00");
1664-
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1673+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-3T11:59:59+08:00");
1674+
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1675+
Assert.True(cache.TryGetValue(settings, out closestStart));
1676+
Assert.Equal(DateTimeOffset.Parse("2024-2-3T00:00:00+08:00"), closestStart);
1677+
Assert.Equal(1, cache.CountOfEntryCreation);
16651678

1666-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-5T00:00:00+08:00");
1667-
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1679+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-3T12:00:00+08:00");
1680+
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1681+
Assert.True(cache.TryGetValue(settings, out closestStart));
1682+
Assert.Equal(DateTimeOffset.Parse("2024-2-5T00:00:00+08:00"), closestStart);
16681683

1669-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-5T12:00:00+08:00");
1670-
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1684+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-5T00:00:00+08:00");
1685+
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1686+
Assert.True(cache.TryGetValue(settings, out closestStart));
1687+
Assert.Equal(DateTimeOffset.Parse("2024-2-5T00:00:00+08:00"), closestStart);
1688+
Assert.Equal(2, cache.CountOfEntryCreation);
16711689

1672-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-7T00:00:00+08:00");
1673-
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1690+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-5T12:00:00+08:00");
1691+
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1692+
Assert.True(cache.TryGetValue(settings, out closestStart));
1693+
Assert.Null(closestStart);
1694+
Assert.Equal(3, cache.CountOfEntryCreation);
16741695

1675-
for (int i = 0; i < 10; i++)
1676-
{
1677-
mockedTimeProvider.UtcNow = mockedTimeProvider.UtcNow.AddDays(1);
1696+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-7T00:00:00+08:00");
16781697
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1698+
Assert.True(cache.TryGetValue(settings, out closestStart));
1699+
Assert.Null(closestStart);
1700+
Assert.Equal(3, cache.CountOfEntryCreation);
1701+
1702+
for (int i = 0; i < 10; i++)
1703+
{
1704+
mockedTimeProvider.UtcNow = mockedTimeProvider.UtcNow.AddDays(1);
1705+
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1706+
Assert.True(cache.TryGetValue(settings, out closestStart));
1707+
Assert.Null(closestStart);
1708+
Assert.Equal(3, cache.CountOfEntryCreation);
1709+
}
16791710
}
16801711

1681-
context = new FeatureFilterEvaluationContext()
1712+
using (var cache = new TestCache())
16821713
{
1683-
Settings = new TimeWindowFilterSettings()
1714+
var mockedTimeWindowFilter = new TimeWindowFilter()
1715+
{
1716+
Cache = cache,
1717+
SystemClock = mockedTimeProvider
1718+
};
1719+
1720+
var settings = new TimeWindowFilterSettings()
16841721
{
16851722
Start = DateTimeOffset.Parse("2024-2-1T00:00:00+08:00"), // Thursday
16861723
End = DateTimeOffset.Parse("2024-2-1T12:00:00+08:00"),
@@ -1698,43 +1735,82 @@ public async Task RecurrenceEvaluationThroughCacheTest()
16981735
NumberOfOccurrences = 2
16991736
}
17001737
}
1701-
}
1702-
};
1738+
};
17031739

1704-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-1-31T23:00:00+08:00");
1705-
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1740+
var context = new FeatureFilterEvaluationContext()
1741+
{
1742+
Settings = settings
1743+
};
17061744

1707-
for (int i = 0; i < 12; i++)
1708-
{
1709-
mockedTimeProvider.UtcNow = mockedTimeProvider.UtcNow.AddHours(1);
1710-
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1711-
}
1745+
DateTimeOffset? closestStart;
1746+
Assert.False(cache.TryGetValue(settings, out closestStart));
1747+
Assert.Equal(0, cache.CountOfEntryCreation);
17121748

1713-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-1T11:59:59+08:00");
1714-
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1749+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-1-31T23:00:00+08:00");
1750+
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1751+
Assert.True(cache.TryGetValue(settings, out closestStart));
1752+
Assert.Equal(DateTimeOffset.Parse("2024-2-1T00:00:00+08:00"), closestStart);
1753+
Assert.Equal(1, cache.CountOfEntryCreation);
17151754

1716-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-1T12:00:00+08:00");
1717-
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1755+
for (int i = 0; i < 12; i++)
1756+
{
1757+
mockedTimeProvider.UtcNow = mockedTimeProvider.UtcNow.AddHours(1);
1758+
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1759+
Assert.True(cache.TryGetValue(settings, out closestStart));
1760+
Assert.Equal(DateTimeOffset.Parse("2024-2-1T00:00:00+08:00"), closestStart);
1761+
Assert.Equal(1, cache.CountOfEntryCreation);
1762+
}
17181763

1719-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-2T00:00:00+08:00"); // Friday
1720-
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1764+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-1T11:59:59+08:00");
1765+
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1766+
Assert.True(cache.TryGetValue(settings, out closestStart));
1767+
Assert.Equal(DateTimeOffset.Parse("2024-2-1T00:00:00+08:00"), closestStart);
1768+
Assert.Equal(1, cache.CountOfEntryCreation);
17211769

1722-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-4T00:00:00+08:00"); // Sunday
1723-
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1770+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-1T12:00:00+08:00");
1771+
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1772+
Assert.True(cache.TryGetValue(settings, out closestStart));
1773+
Assert.Equal(DateTimeOffset.Parse("2024-2-4T00:00:00+08:00"), closestStart);
1774+
Assert.Equal(2, cache.CountOfEntryCreation);
17241775

1725-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-4T06:00:00+08:00");
1726-
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1776+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-2T00:00:00+08:00"); // Friday
1777+
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1778+
Assert.True(cache.TryGetValue(settings, out closestStart));
1779+
Assert.Equal(DateTimeOffset.Parse("2024-2-4T00:00:00+08:00"), closestStart);
1780+
Assert.Equal(2, cache.CountOfEntryCreation);
17271781

1728-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-4T12:01:00+08:00");
1729-
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1782+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-4T00:00:00+08:00"); // Sunday
1783+
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1784+
Assert.True(cache.TryGetValue(settings, out closestStart));
1785+
Assert.Equal(DateTimeOffset.Parse("2024-2-4T00:00:00+08:00"), closestStart);
1786+
Assert.Equal(2, cache.CountOfEntryCreation);
17301787

1731-
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-8T00:00:00+08:00");
1732-
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1788+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-4T06:00:00+08:00");
1789+
Assert.True(await mockedTimeWindowFilter.EvaluateAsync(context));
1790+
Assert.True(cache.TryGetValue(settings, out closestStart));
1791+
Assert.Equal(DateTimeOffset.Parse("2024-2-4T00:00:00+08:00"), closestStart);
1792+
Assert.Equal(2, cache.CountOfEntryCreation);
17331793

1734-
for (int i = 0; i < 10; i++)
1735-
{
1736-
mockedTimeProvider.UtcNow = mockedTimeProvider.UtcNow.AddDays(1);
1794+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-4T12:01:00+08:00");
17371795
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1796+
Assert.True(cache.TryGetValue(settings, out closestStart));
1797+
Assert.Null(closestStart);
1798+
Assert.Equal(3, cache.CountOfEntryCreation);
1799+
1800+
mockedTimeProvider.UtcNow = DateTimeOffset.Parse("2024-2-8T00:00:00+08:00");
1801+
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1802+
Assert.True(cache.TryGetValue(settings, out closestStart));
1803+
Assert.Null(closestStart);
1804+
Assert.Equal(3, cache.CountOfEntryCreation);
1805+
1806+
for (int i = 0; i < 10; i++)
1807+
{
1808+
mockedTimeProvider.UtcNow = mockedTimeProvider.UtcNow.AddDays(1);
1809+
Assert.False(await mockedTimeWindowFilter.EvaluateAsync(context));
1810+
Assert.True(cache.TryGetValue(settings, out closestStart));
1811+
Assert.Null(closestStart);
1812+
Assert.Equal(3, cache.CountOfEntryCreation);
1813+
}
17381814
}
17391815
}
17401816
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
//
4+
using Microsoft.Extensions.Caching.Memory;
5+
6+
namespace Tests.FeatureManagement
7+
{
8+
class TestCache : IMemoryCache
9+
{
10+
private readonly IMemoryCache _cache;
11+
private int _countOfEntryCreation;
12+
13+
public TestCache()
14+
{
15+
_cache = new MemoryCache(new MemoryCacheOptions());
16+
}
17+
18+
public int CountOfEntryCreation
19+
{
20+
get => _countOfEntryCreation;
21+
}
22+
23+
public bool TryGetValue(object key, out object value)
24+
{
25+
return _cache.TryGetValue(key, out value);
26+
}
27+
28+
public ICacheEntry CreateEntry(object key)
29+
{
30+
_countOfEntryCreation += 1;
31+
32+
return _cache.CreateEntry(key);
33+
}
34+
35+
public void Remove(object key)
36+
{
37+
_cache.Remove(key);
38+
}
39+
40+
public void Dispose()
41+
{
42+
_cache.Dispose();
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)