-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tests for advanced flag override use cases
- Loading branch information
Showing
15 changed files
with
408 additions
and
135 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,13 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using System.Threading.Tasks; | ||
using ConfigCat.Client.Configuration; | ||
using ConfigCat.Client.Evaluation; | ||
using ConfigCat.Client.Tests.Helpers; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using Moq; | ||
|
||
namespace ConfigCat.Client.Tests; | ||
|
||
|
@@ -92,21 +94,15 @@ public void SegmentMatrixTests(string configLocation, string settingKey, string | |
[TestMethod] | ||
public void CircularDependencyTest() | ||
{ | ||
var config = new ConfigLocation.LocalFile("data", "sample_circulardependency_v6.json").FetchConfig(); | ||
var config = new ConfigLocation.LocalFile("data", "test_circulardependency_v6.json").FetchConfig(); | ||
|
||
var logEvents = new List<(LogLevel Level, LogEventId EventId, FormattableLogMessage Message, Exception? Exception)>(); | ||
var logEvents = new List<LogEvent>(); | ||
var logger = LoggingHelper.CreateCapturingLogger(logEvents); | ||
|
||
var loggerMock = new Mock<IConfigCatLogger>(); | ||
loggerMock.SetupGet(logger => logger.LogLevel).Returns(LogLevel.Info); | ||
loggerMock.Setup(logger => logger.Log(It.IsAny<LogLevel>(), It.IsAny<LogEventId>(), ref It.Ref<FormattableLogMessage>.IsAny, It.IsAny<Exception>())) | ||
.Callback(delegate (LogLevel level, LogEventId eventId, ref FormattableLogMessage msg, Exception ex) { logEvents.Add((level, eventId, msg, ex)); }); | ||
|
||
var loggerWrapper = loggerMock.Object.AsWrapper(); | ||
|
||
var evaluator = new RolloutEvaluator(loggerWrapper); | ||
var evaluator = new RolloutEvaluator(logger); | ||
|
||
const string key = "key1"; | ||
var evaluationDetails = evaluator.Evaluate<object?>(config!.Settings, key, defaultValue: null, user: null, remoteConfig: null, loggerWrapper); | ||
var evaluationDetails = evaluator.Evaluate<object?>(config!.Settings, key, defaultValue: null, user: null, remoteConfig: null, logger); | ||
|
||
Assert.AreEqual(4, logEvents.Count); | ||
|
||
|
@@ -138,7 +134,77 @@ public void CircularDependencyTest() | |
StringAssert.Matches((string?)evaluateLogEvent.Message.ArgValues[0], new Regex( | ||
"THEN 'key3-prereq1' => " + Regex.Escape(RolloutEvaluator.CircularDependencyError) + Environment.NewLine | ||
+ @"\s+" + Regex.Escape(RolloutEvaluator.TargetingRuleIgnoredMessage))); | ||
} | ||
|
||
var inv = loggerMock.Invocations[0]; | ||
[DataTestMethod] | ||
[DataRow("stringDependsOnString", "1", "[email protected]", null, "Dog")] | ||
[DataRow("stringDependsOnString", "1", "[email protected]", OverrideBehaviour.RemoteOverLocal, "Dog")] | ||
[DataRow("stringDependsOnString", "1", "[email protected]", OverrideBehaviour.LocalOverRemote, "Dog")] | ||
[DataRow("stringDependsOnString", "1", "[email protected]", OverrideBehaviour.LocalOnly, null)] | ||
[DataRow("stringDependsOnString", "2", "[email protected]", null, "Cat")] | ||
[DataRow("stringDependsOnString", "2", "[email protected]", OverrideBehaviour.RemoteOverLocal, "Cat")] | ||
[DataRow("stringDependsOnString", "2", "[email protected]", OverrideBehaviour.LocalOverRemote, "Dog")] | ||
[DataRow("stringDependsOnString", "2", "[email protected]", OverrideBehaviour.LocalOnly, null)] | ||
[DataRow("stringDependsOnInt", "1", "[email protected]", null, "Dog")] | ||
[DataRow("stringDependsOnInt", "1", "[email protected]", OverrideBehaviour.RemoteOverLocal, "Dog")] | ||
[DataRow("stringDependsOnInt", "1", "[email protected]", OverrideBehaviour.LocalOverRemote, "Cat")] | ||
[DataRow("stringDependsOnInt", "1", "[email protected]", OverrideBehaviour.LocalOnly, null)] | ||
[DataRow("stringDependsOnInt", "2", "[email protected]", null, "Cat")] | ||
[DataRow("stringDependsOnInt", "2", "[email protected]", OverrideBehaviour.RemoteOverLocal, "Cat")] | ||
[DataRow("stringDependsOnInt", "2", "[email protected]", OverrideBehaviour.LocalOverRemote, "Dog")] | ||
[DataRow("stringDependsOnInt", "2", "[email protected]", OverrideBehaviour.LocalOnly, null)] | ||
public async Task PrerequisiteFlagOverrideTest(string key, string userId, string email, OverrideBehaviour? overrideBehaviour, object expectedValue) | ||
{ | ||
var cdnLocation = (ConfigLocation.Cdn)new FlagDependencyMatrixTestsDescriptor().ConfigLocation; | ||
|
||
var options = new ConfigCatClientOptions | ||
{ | ||
// The flag override uses a different config json salt than the downloaded one and overrides the following segments: | ||
// * Beta Users: User.Email IS ONE OF ['[email protected]'] | ||
// * Developers: User.Email IS ONE OF ['[email protected]'] | ||
FlagOverrides = overrideBehaviour is not null | ||
? FlagOverrides.LocalFile(Path.Combine("data", "test_override_flagdependency_v6.json"), autoReload: false, overrideBehaviour.Value) | ||
: null, | ||
PollingMode = PollingModes.ManualPoll, | ||
}; | ||
cdnLocation.ConfigureBaseUrl(options); | ||
|
||
using var client = new ConfigCatClient(cdnLocation.SdkKey, options); | ||
await client.ForceRefreshAsync(); | ||
var actualValue = await client.GetValueAsync(key, (object?)null, new User(userId) { Email = email }); | ||
|
||
Assert.AreEqual(expectedValue, actualValue); | ||
} | ||
|
||
[DataTestMethod] | ||
[DataRow("developerAndBetaUserSegment", "1", "[email protected]", null, false)] | ||
[DataRow("developerAndBetaUserSegment", "1", "[email protected]", OverrideBehaviour.RemoteOverLocal, false)] | ||
[DataRow("developerAndBetaUserSegment", "1", "[email protected]", OverrideBehaviour.LocalOverRemote, true)] | ||
[DataRow("developerAndBetaUserSegment", "1", "[email protected]", OverrideBehaviour.LocalOnly, true)] | ||
[DataRow("notDeveloperAndNotBetaUserSegment", "2", "[email protected]", null, true)] | ||
[DataRow("notDeveloperAndNotBetaUserSegment", "2", "[email protected]", OverrideBehaviour.RemoteOverLocal, true)] | ||
[DataRow("notDeveloperAndNotBetaUserSegment", "2", "[email protected]", OverrideBehaviour.LocalOverRemote, true)] | ||
[DataRow("notDeveloperAndNotBetaUserSegment", "2", "[email protected]", OverrideBehaviour.LocalOnly, null)] | ||
public async Task ConfigSaltAndSegmentsOverrideTest(string key, string userId, string email, OverrideBehaviour? overrideBehaviour, object expectedValue) | ||
{ | ||
var cdnLocation = (ConfigLocation.Cdn)new SegmentMatrixTestsDescriptor().ConfigLocation; | ||
|
||
var options = new ConfigCatClientOptions | ||
{ | ||
// The flag override uses a different config json salt than the downloaded one and overrides the following segments: | ||
// * Beta Users: User.Email IS ONE OF ['[email protected]'] | ||
// * Developers: User.Email IS ONE OF ['[email protected]'] | ||
FlagOverrides = overrideBehaviour is not null | ||
? FlagOverrides.LocalFile(Path.Combine("data", "test_override_segments_v6.json"), autoReload: false, overrideBehaviour.Value) | ||
: null, | ||
PollingMode = PollingModes.ManualPoll, | ||
}; | ||
cdnLocation.ConfigureBaseUrl(options); | ||
|
||
using var client = new ConfigCatClient(cdnLocation.SdkKey, options); | ||
await client.ForceRefreshAsync(); | ||
var actualValue = await client.GetValueAsync(key, (object?)null, new User(userId) { Email = email }); | ||
|
||
Assert.AreEqual(expectedValue, actualValue); | ||
} | ||
} |
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
This file was deleted.
Oops, something went wrong.
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,38 @@ | ||
using Moq; | ||
using System.Collections.Generic; | ||
using System; | ||
|
||
namespace ConfigCat.Client; | ||
|
||
internal struct LogEvent | ||
{ | ||
public LogEvent(LogLevel level, LogEventId eventId, ref FormattableLogMessage message, Exception? exception) | ||
{ | ||
(this.Level, this.EventId, this.Message, this.Exception) = (level, eventId, message, exception); | ||
} | ||
|
||
public readonly LogLevel Level; | ||
public readonly LogEventId EventId; | ||
public FormattableLogMessage Message; | ||
public readonly Exception? Exception; | ||
} | ||
|
||
internal static class LoggingHelper | ||
{ | ||
public static LoggerWrapper AsWrapper(this IConfigCatLogger logger, Hooks? hooks = null) | ||
{ | ||
return new LoggerWrapper(logger, hooks); | ||
} | ||
|
||
public static LoggerWrapper CreateCapturingLogger(List<LogEvent> logEvents, LogLevel logLevel = LogLevel.Info) | ||
{ | ||
var loggerMock = new Mock<IConfigCatLogger>(); | ||
|
||
loggerMock.SetupGet(logger => logger.LogLevel).Returns(logLevel); | ||
|
||
loggerMock.Setup(logger => logger.Log(It.IsAny<LogLevel>(), It.IsAny<LogEventId>(), ref It.Ref<FormattableLogMessage>.IsAny, It.IsAny<Exception>())) | ||
.Callback(delegate (LogLevel level, LogEventId eventId, ref FormattableLogMessage msg, Exception ex) { logEvents.Add(new LogEvent(level, eventId, ref msg, ex)); }); | ||
|
||
return loggerMock.Object.AsWrapper(); | ||
} | ||
} |
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
Oops, something went wrong.