Skip to content

Commit f8d0c34

Browse files
add more UTs
1 parent 3b9c267 commit f8d0c34

File tree

3 files changed

+1054
-20
lines changed

3 files changed

+1054
-20
lines changed

src/Microsoft.FeatureManagement/FeatureFilters/Recurrence/RecurrenceEvaluator.cs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,17 @@ static class RecurrenceEvaluator
4949
const string Numbered = "Numbered";
5050
const string NoEnd = "NoEnd";
5151

52-
const int WeeklyUnitIntervalDuration = 7; // in days
53-
const int MonthlyUnitIntervalDuration = 28; // in days
54-
const int YearlyUnitIntervalDuration = 365; // in days
55-
52+
const int WeekDayNumber = 7;
53+
const int MinMonthDayNumber = 28;
54+
const int MinYearDayNumber = 365;
55+
56+
/// <summary>
57+
/// Checks if a provided timestamp is within any recurring time window specified by the Recurrence section in the time window filter settings.
58+
/// If the time window filter has an invalid recurrence setting, an exception will be thrown.
59+
/// <param name="time">A time stamp.</param>
60+
/// <param name="settings">The settings of time window filter.</param>
61+
/// <returns>True if the time stamp is within any recurring time window, false otherwise.</returns>
62+
/// </summary>
5663
public static bool MatchRecurrence(DateTimeOffset time, TimeWindowFilterSettings settings)
5764
{
5865
if (settings == null)
@@ -88,6 +95,13 @@ public static bool MatchRecurrence(DateTimeOffset time, TimeWindowFilterSettings
8895
return false;
8996
}
9097

98+
/// <summary>
99+
/// Try to find the closest previous recurrence occurrence before the provided time stamp according to the recurrence pattern.
100+
/// <param name="time">A time stamp.</param>
101+
/// <param name="settings">The settings of time window filter.</param>
102+
/// <param name="previousOccurrence">The closest orevious occurrence.</param>
103+
/// /// <returns>True if the closest previous occurrence is within the recurrence range, false otherwise.</returns>
104+
/// </summary>
91105
private static bool TryGetPreviousOccurrence(DateTimeOffset time, TimeWindowFilterSettings settings, out DateTimeOffset previousOccurrence)
92106
{
93107
previousOccurrence = DateTimeOffset.MaxValue;
@@ -619,13 +633,13 @@ private static bool TryValidateWeeklyRecurrencePattern(TimeWindowFilterSettings
619633

620634
RecurrencePattern pattern = settings.Recurrence.Pattern;
621635

622-
TimeSpan intervalDuration = TimeSpan.FromDays(pattern.Interval * WeeklyUnitIntervalDuration);
636+
TimeSpan intervalDuration = TimeSpan.FromDays(pattern.Interval * WeekDayNumber);
623637

624638
TimeSpan timeWindowDuration = settings.End.Value - settings.Start.Value;
625639

626640
//
627641
// Time window duration must be shorter than how frequently it occurs
628-
if (settings.End.Value - settings.Start.Value > intervalDuration)
642+
if (timeWindowDuration > intervalDuration)
629643
{
630644
paramName = $"{nameof(settings.End)}";
631645

@@ -684,7 +698,7 @@ private static bool TryValidateAbsoluteMonthlyRecurrencePattern(TimeWindowFilter
684698

685699
RecurrencePattern pattern = settings.Recurrence.Pattern;
686700

687-
TimeSpan intervalDuration = TimeSpan.FromDays(pattern.Interval * MonthlyUnitIntervalDuration);
701+
TimeSpan intervalDuration = TimeSpan.FromDays(pattern.Interval * MinMonthDayNumber);
688702

689703
//
690704
// Time window duration must be shorter than how frequently it occurs
@@ -730,7 +744,7 @@ private static bool TryValidateRelativeMonthlyRecurrencePattern(TimeWindowFilter
730744

731745
RecurrencePattern pattern = settings.Recurrence.Pattern;
732746

733-
TimeSpan intervalDuration = TimeSpan.FromDays(pattern.Interval * MonthlyUnitIntervalDuration);
747+
TimeSpan intervalDuration = TimeSpan.FromDays(pattern.Interval * MinMonthDayNumber);
734748

735749
//
736750
// Time window duration must be shorter than how frequently it occurs
@@ -782,7 +796,7 @@ private static bool TryValidateAbsoluteYearlyRecurrencePattern(TimeWindowFilterS
782796

783797
RecurrencePattern pattern = settings.Recurrence.Pattern;
784798

785-
TimeSpan intervalDuration = TimeSpan.FromDays(pattern.Interval * YearlyUnitIntervalDuration);
799+
TimeSpan intervalDuration = TimeSpan.FromDays(pattern.Interval * MinYearDayNumber);
786800

787801
//
788802
// Time window duration must be shorter than how frequently it occurs
@@ -833,7 +847,7 @@ private static bool TryValidateRelativeYearlyRecurrencePattern(TimeWindowFilterS
833847

834848
RecurrencePattern pattern = settings.Recurrence.Pattern;
835849

836-
TimeSpan intervalDuration = TimeSpan.FromDays(pattern.Interval * YearlyUnitIntervalDuration);
850+
TimeSpan intervalDuration = TimeSpan.FromDays(pattern.Interval * MinYearDayNumber);
837851

838852
//
839853
// Time window duration must be shorter than how frequently it occurs
@@ -1211,9 +1225,17 @@ private static TimeSpan GetRecurrenceTimeZone(TimeWindowFilterSettings settings)
12111225
return timeZoneOffset;
12121226
}
12131227

1228+
/// <summary>
1229+
/// Check whether the duration is shorter than the minimum gap between recurrence of days of week.
1230+
/// </summary>
1231+
/// <param name="duration">The time span of the duration.</param>
1232+
/// <param name="interval">The recurrence interval.</param>
1233+
/// <param name="daysOfWeek">The days of the week when the recurrence will occur.</param>
1234+
/// <param name="firstDayOfWeek">The first day of the week.</param>
1235+
/// <returns>True if the duration is compliant with days of week, false otherwise.</returns>
12141236
private static bool IsDurationCompliantWithDaysOfWeek(TimeSpan duration, int interval, IEnumerable<string> daysOfWeek, string firstDayOfWeek)
12151237
{
1216-
if (daysOfWeek == null || daysOfWeek.Count() < 1)
1238+
if (daysOfWeek == null || !daysOfWeek.Any())
12171239
{
12181240
throw new ArgumentException(nameof(daysOfWeek));
12191241
}

tests/Tests.FeatureManagement/FeatureManagement.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ public async Task TimeWindow()
256256
string feature2 = "feature2";
257257
string feature3 = "feature3";
258258
string feature4 = "feature4";
259+
string feature5 = "feature5";
260+
string feature6 = "feature6";
259261

260262
Environment.SetEnvironmentVariable($"FeatureManagement:{feature1}:EnabledFor:0:Name", "TimeWindow");
261263
Environment.SetEnvironmentVariable($"FeatureManagement:{feature1}:EnabledFor:0:Parameters:End", DateTimeOffset.UtcNow.AddDays(1).ToString("r"));
@@ -269,6 +271,19 @@ public async Task TimeWindow()
269271
Environment.SetEnvironmentVariable($"FeatureManagement:{feature4}:EnabledFor:0:Name", "TimeWindow");
270272
Environment.SetEnvironmentVariable($"FeatureManagement:{feature4}:EnabledFor:0:Parameters:Start", DateTimeOffset.UtcNow.AddDays(1).ToString("r"));
271273

274+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature5}:EnabledFor:0:Name", "TimeWindow");
275+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature5}:EnabledFor:0:Parameters:Start", DateTimeOffset.UtcNow.AddDays(-2).ToString("r"));
276+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature5}:EnabledFor:0:Parameters:End", DateTimeOffset.UtcNow.AddDays(-1).ToString("r"));
277+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature5}:EnabledFor:0:Parameters:Recurrence:Pattern:Type", "Daily");
278+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature5}:EnabledFor:0:Parameters:Recurrence:Range:Type", "NoEnd");
279+
280+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature6}:EnabledFor:0:Name", "TimeWindow");
281+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature6}:EnabledFor:0:Parameters:Start", DateTimeOffset.UtcNow.AddDays(-2).ToString("r"));
282+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature6}:EnabledFor:0:Parameters:End", DateTimeOffset.UtcNow.AddDays(-1).ToString("r"));
283+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature6}:EnabledFor:0:Parameters:Recurrence:Pattern:Type", "Daily");
284+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature6}:EnabledFor:0:Parameters:Recurrence:Pattern:Interval", "3");
285+
Environment.SetEnvironmentVariable($"FeatureManagement:{feature6}:EnabledFor:0:Parameters:Recurrence:Range:Type", "NoEnd");
286+
272287
IConfiguration config = new ConfigurationBuilder().AddEnvironmentVariables().Build();
273288

274289
var serviceCollection = new ServiceCollection();
@@ -285,6 +300,8 @@ public async Task TimeWindow()
285300
Assert.False(await featureManager.IsEnabledAsync(feature2));
286301
Assert.True(await featureManager.IsEnabledAsync(feature3));
287302
Assert.False(await featureManager.IsEnabledAsync(feature4));
303+
Assert.True(await featureManager.IsEnabledAsync(feature5));
304+
Assert.False(await featureManager.IsEnabledAsync(feature6));
288305
}
289306

290307
[Fact]

0 commit comments

Comments
 (0)