From 6f91bd491edd654e156b05ad085be5d1a4e731a3 Mon Sep 17 00:00:00 2001 From: Adam Simon Date: Mon, 31 Jul 2023 22:17:05 +0200 Subject: [PATCH] Add tests for evaluation logging --- .../EvaluationLogTests.cs | 301 ++++++++++++++++++ .../data/evaluationlog/1_targeting_rule.json | 3 +- .../1_rule_matching_targeted_attribute.txt | 2 +- .../1_rule_no_targeted_attribute.txt | 6 +- .../1_targeting_rule/1_rule_no_user.txt | 2 +- ...1_rule_not_matching_targeted_attribute.txt | 2 +- .../data/evaluationlog/2_targeting_rules.json | 3 +- .../2_rules_matching_targeted_attribute.txt | 8 +- .../2_rules_no_targeted_attribute.txt | 10 +- .../2_targeting_rules/2_rules_no_user.txt | 7 +- ..._rules_not_matching_targeted_attribute.txt | 8 +- .../circular_dependency_override.json | 13 +- .../data/evaluationlog/and_rules.json | 1 + .../and_rules/and_rules_no_user.txt | 4 +- .../and_rules/and_rules_user.txt | 8 +- .../evaluationlog/circular_dependency.json | 4 +- .../circular_dependency.txt | 34 +- .../options_after_targeting_rule.json | 1 + ...eting_rule_matching_targeted_attribute.txt | 2 +- ...r_targeting_rule_no_targeted_attribute.txt | 12 +- .../options_after_targeting_rule_no_user.txt | 5 +- ...g_rule_not_matching_targeted_attribute.txt | 8 +- .../options_based_on_custom_attr.json | 1 + .../matching_options_custom_attribute.txt | 4 +- .../no_options_custom_attribute.txt | 4 +- .../options_custom_attribute_no_user.txt | 2 +- .../options_based_on_user_id.json | 1 + .../options_user_attribute_no_user.txt | 5 +- .../options_user_attribute_user.txt | 9 +- .../options_within_targeting_rule.json | 3 +- ...argeted_attribute_no_options_attribute.txt | 3 +- ...g_targeted_attribute_options_attribute.txt | 4 +- ...n_targeting_rule_no_targeted_attribute.txt | 6 +- .../options_within_targeting_rule_no_user.txt | 2 +- ...g_rule_not_matching_targeted_attribute.txt | 2 +- .../data/evaluationlog/prerequisite_flag.json | 3 +- .../prerequisite_flag/prerequisite_flag.txt | 26 +- .../data/evaluationlog/segment.json | 2 +- .../segment/segment_matching.txt | 6 +- .../segment/segment_no_matching.txt | 6 +- .../evaluationlog/segment/segment_no_user.txt | 2 +- .../data/evaluationlog/simple_value.json | 3 +- src/ConfigCatClient/ConfigCatClient.cs | 7 +- 43 files changed, 437 insertions(+), 108 deletions(-) create mode 100644 src/ConfigCat.Client.Tests/EvaluationLogTests.cs rename src/ConfigCat.Client.Tests/data/evaluationlog/{circular_dependency => _overrides}/circular_dependency_override.json (74%) diff --git a/src/ConfigCat.Client.Tests/EvaluationLogTests.cs b/src/ConfigCat.Client.Tests/EvaluationLogTests.cs new file mode 100644 index 00000000..93e5b274 --- /dev/null +++ b/src/ConfigCat.Client.Tests/EvaluationLogTests.cs @@ -0,0 +1,301 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using ConfigCat.Client.Configuration; +using ConfigCat.Client.Evaluation; +using ConfigCat.Client.Override; +using ConfigCat.Client.Utils; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; + +#if NET45 +using Newtonsoft.Json; +using JsonObject = Newtonsoft.Json.Linq.JObject; +using JsonValue = Newtonsoft.Json.Linq.JValue; +#else +using System.Text.Json.Serialization; +using JsonObject = System.Text.Json.JsonElement; +using JsonValue = System.Text.Json.JsonElement; +#endif + +namespace ConfigCat.Client.Tests; + +[TestClass] +public class EvaluationLogTests +{ + private static IEnumerable GetSimpleValueTests() => GetTests("simple_value"); + + [DataTestMethod] + [DynamicData(nameof(GetSimpleValueTests), DynamicDataSourceType.Method)] + public void SimpleValueTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetOneTargetingRuleTests() => GetTests("1_targeting_rule"); + + [DataTestMethod] + [DynamicData(nameof(GetOneTargetingRuleTests), DynamicDataSourceType.Method)] + public void OneTargetingRuleTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetTwoTargetingRulesTests() => GetTests("2_targeting_rules"); + + [DataTestMethod] + [DynamicData(nameof(GetTwoTargetingRulesTests), DynamicDataSourceType.Method)] + public void TwoTargetingRulesTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetPercentageOptionsBasedOnUserIdAttributeTests() => GetTests("options_based_on_user_id"); + + [DataTestMethod] + [DynamicData(nameof(GetPercentageOptionsBasedOnUserIdAttributeTests), DynamicDataSourceType.Method)] + public void PercentageOptionsBasedOnUserIdAttributeTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetPercentageOptionsBasedOnCustomAttributeTests() => GetTests("options_based_on_custom_attr"); + + [DataTestMethod] + [DynamicData(nameof(GetPercentageOptionsBasedOnCustomAttributeTests), DynamicDataSourceType.Method)] + public void PercentageOptionsBasedOnCustomAttributeTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetPercentageOptionsAfterTargetingRuleTests() => GetTests("options_after_targeting_rule"); + + [DataTestMethod] + [DynamicData(nameof(GetPercentageOptionsAfterTargetingRuleTests), DynamicDataSourceType.Method)] + public void PercentageOptionsAfterTargetingRuleTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetPercentageOptionsWithinTargetingRuleTests() => GetTests("options_within_targeting_rule"); + + [DataTestMethod] + [DynamicData(nameof(GetPercentageOptionsWithinTargetingRuleTests), DynamicDataSourceType.Method)] + public void PercentageOptionsWithinTargetingRuleTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetAndRulesTests() => GetTests("and_rules"); + + [DataTestMethod] + [DynamicData(nameof(GetAndRulesTests), DynamicDataSourceType.Method)] + public void AndRulesTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetSegmentConditionsTests() => GetTests("segment"); + + [DataTestMethod] + [DynamicData(nameof(GetSegmentConditionsTests), DynamicDataSourceType.Method)] + public void SegmentConditionsTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetPrerequisiteFlagConditionsTests() => GetTests("prerequisite_flag"); + + [DataTestMethod] + [DynamicData(nameof(GetPrerequisiteFlagConditionsTests), DynamicDataSourceType.Method)] + public void PrerequisiteFlagConditionsTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetPrerequisiteFlagConditionsWithCircularDependencyTests() => GetTests("circular_dependency"); + + [DataTestMethod] + [DynamicData(nameof(GetPrerequisiteFlagConditionsWithCircularDependencyTests), DynamicDataSourceType.Method)] + public void PrerequisiteFlagConditionsWithCircularDependencyTests(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, + string key, string? defaultValue, string userObject, string? expectedReturnValue, string expectedLogFileName) + { + RunTest(testSetName, sdkKey, baseUrlOrOverrideFileName, key, defaultValue, userObject, expectedReturnValue, expectedLogFileName); + } + + private static IEnumerable GetTests(string testSetName) + { + var filePath = Path.Combine("data", "evaluationlog", testSetName + ".json"); + var fileContent = File.ReadAllText(filePath); + var testSet = SerializationExtensions.Deserialize(fileContent); + + foreach (var testCase in testSet!.tests ?? ArrayUtils.EmptyArray()) + { + yield return new object?[] + { + testSetName, + testSet.sdkKey, + testSet.sdkKey is { Length: > 0 } ? testSet.baseUrl : testSet.jsonOverride, + testCase.key, + testCase.defaultValue.Serialize(), + testCase.user?.Serialize(), + testCase.returnValue.Serialize(), + testCase.expectedLog + }; + } + } + + private static string GetReferencedTestFilePath(string subDirName, string fileName) => Path.Combine("data", "evaluationlog", subDirName, fileName); + + private static void RunTest(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName, string key, string? defaultValue, string? userObject, string? expectedReturnValue, string expectedLogFileName) + { + var defaultValueParsed = defaultValue?.Deserialize()!.ToSettingValue(out var settingType).GetValue(); + var expectedReturnValueParsed = expectedReturnValue?.Deserialize()!.ToSettingValue(out _).GetValue(); + + var userObjectParsed = userObject?.Deserialize?>(); + User? user; + if (userObjectParsed is not null) + { + user = new User(userObjectParsed[nameof(User.Identifier)]); + + if (userObjectParsed.TryGetValue(nameof(User.Email), out var email)) + { + user.Email = email; + } + + if (userObjectParsed.TryGetValue(nameof(User.Country), out var country)) + { + user.Country = country; + } + + foreach (var kvp in userObjectParsed) + { + if (kvp.Key is not (nameof(User.Identifier) or nameof(User.Email) or nameof(User.Country))) + { + user.Custom[kvp.Key] = kvp.Value; + } + } + } + else + { + user = null; + } + + var logEvents = new List<(LogLevel Level, LogEventId EventId, FormattableLogMessage Message, Exception? Exception)>(); + + var loggerMock = new Mock(); + loggerMock.SetupGet(logger => logger.LogLevel).Returns(LogLevel.Info); + loggerMock.Setup(logger => logger.Log(It.IsAny(), It.IsAny(), ref It.Ref.IsAny, It.IsAny())) + .Callback(delegate (LogLevel level, LogEventId eventId, ref FormattableLogMessage msg, Exception ex) { logEvents.Add((level, eventId, msg, ex)); }); + var logger = loggerMock.Object.AsWrapper(); + + var settings = GetSettings(testSetName, sdkKey, baseUrlOrOverrideFileName); + + var evaluator = new RolloutEvaluator(logger); + var evaluationDetails = evaluator.Evaluate(settings, key, defaultValueParsed, user, remoteConfig: null, logger); + var actualReturnValue = evaluationDetails.Value; + + Assert.AreEqual(expectedReturnValueParsed, actualReturnValue); + + var expectedLogFilePath = GetReferencedTestFilePath(testSetName, expectedLogFileName); + var expectedLogText = string.Join(Environment.NewLine, File.ReadAllLines(expectedLogFilePath)); + + var actualLogText = string.Join(Environment.NewLine, logEvents + .Select(evt => FormatLogEvent(evt.Level, evt.EventId, ref evt.Message, evt.Exception))); + + Assert.AreEqual(expectedLogText, actualLogText); + } + + private static string FormatLogEvent(LogLevel level, LogEventId eventId, ref FormattableLogMessage message, Exception? exception) + { + var levelString = level switch + { + LogLevel.Debug => "DEBUG", + LogLevel.Info => "INFO", + LogLevel.Warning => "WARNING", + LogLevel.Error => "ERROR", + _ => level.ToString().ToUpperInvariant().PadRight(5) + }; + + var eventIdString = eventId.Id.ToString(CultureInfo.InvariantCulture); + + var exceptionString = exception is null ? string.Empty : Environment.NewLine + exception; + + return $"{levelString} [{eventIdString}] {message.InvariantFormattedMessage}{exceptionString}"; + } + + private static readonly ConcurrentDictionary?>> SettingsCache = new(); + + private static Dictionary? GetSettings(string testSetName, string? sdkKey, string? baseUrlOrOverrideFileName) + { + var key = sdkKey switch + { + not { Length: > 0 } => "flag-override:" + testSetName + "/" + baseUrlOrOverrideFileName, + { } when baseUrlOrOverrideFileName is { Length: > 0 } => sdkKey + "@" + baseUrlOrOverrideFileName, + _ => sdkKey + }; + + return SettingsCache.GetOrAdd(key, _ => new Lazy?>(() => + { + var logger = new ConsoleLogger(); + if (sdkKey is { Length: > 0 }) + { + var options = new ConfigCatClientOptions() { PollingMode = PollingModes.ManualPoll, Logger = logger }; + if (baseUrlOrOverrideFileName is { Length: > 0 }) + { + options.BaseUrl = new Uri(baseUrlOrOverrideFileName); + } + + using var configFetcher = new HttpConfigFetcher(options.CreateUri(sdkKey), ConfigCatClient.GetProductVersion(options.PollingMode), + options.Logger!.AsWrapper(), options.HttpClientHandler, options.IsCustomBaseUrl, options.HttpTimeout); + + var fetchResult = configFetcher.Fetch(ProjectConfig.Empty); + return fetchResult.Config.Config?.Settings; + } + else + { + var overrideFilePath = GetReferencedTestFilePath("_overrides", baseUrlOrOverrideFileName!); + var dataSource = new LocalFileDataSource(overrideFilePath, autoReload: false, logger.AsWrapper()); + return dataSource.GetOverrides(); + } + }, isThreadSafe: true)).Value; + } + + [ClassInitialize] + public static void ClassInitialize(TestContext _) => SettingsCache.Clear(); + + [ClassCleanup] + public static void ClassCleanup() => SettingsCache.Clear(); + +#pragma warning disable IDE1006 // Naming Styles + public class TestSet + { + public string? sdkKey { get; set; } + public string? baseUrl { get; set; } + public string? jsonOverride { get; set; } + public TestCase[]? tests { get; set; } + } + + public class TestCase + { + public string key { get; set; } = null!; + public JsonValue defaultValue { get; set; } = default!; + public JsonObject? user { get; set; } = default!; + public JsonValue returnValue { get; set; } = default!; + public string expectedLog { get; set; } = null!; + } +#pragma warning restore IDE1006 // Naming Styles +} diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule.json b/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule.json index f2e07b2c..596bd2b4 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule.json @@ -1,4 +1,5 @@ { + "configUrl": "https://app.configcat.com/08d5a03c-feb7-af1e-a1fa-40b3329f8bed/08d62463-86ec-8fde-f5b5-1c5c426fc830/244cf8b0-f604-11e8-b543-f23c917f9d8d", "sdkKey": "PKDVCLf-Hq-h-kCzMp-L7Q/psuH7BGHoUmdONrzzUOY7A", "tests": [ { @@ -37,4 +38,4 @@ "expectedLog": "1_rule_matching_targeted_attribute.txt" } ] -} \ No newline at end of file +} diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_matching_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_matching_targeted_attribute.txt index 1d32d489..f05c6f61 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_matching_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_matching_targeted_attribute.txt @@ -1,4 +1,4 @@ -INFO [5000] Evaluating 'stringContainsDogDefaultCat' for User '{"Identifier": "12345", "Email": "joe@configcat.com", "Country": null, "Custom": null}' +INFO [5000] Evaluating 'stringContainsDogDefaultCat' for User '{"Identifier":"12345","Email":"joe@configcat.com"}' Evaluating targeting rules and applying the first match if any: - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN 'Dog' => MATCH, applying rule Returning 'Dog'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_no_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_no_targeted_attribute.txt index 57ea6e86..80702e92 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_no_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_no_targeted_attribute.txt @@ -1,4 +1,6 @@ -INFO [5000] Evaluating 'stringContainsDogDefaultCat' for User '{"Identifier": "12345", "Email": null, "Country": null, "Custom": null}' +WARNING [3003] Cannot evaluate condition (User.Email CONTAINS ANY OF ['@configcat.com']) for setting 'stringContainsDogDefaultCat' (the User.Email attribute is missing). You should set the User.Email attribute in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +INFO [5000] Evaluating 'stringContainsDogDefaultCat' for User '{"Identifier":"12345"}' Evaluating targeting rules and applying the first match if any: - - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN 'Dog' => no match + - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN 'Dog' => cannot evaluate, the User.Email attribute is missing + The current targeting rule is ignored and the evaluation continues with the next rule. Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_no_user.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_no_user.txt index 3b01ec89..2f1f99bb 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_no_user.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_no_user.txt @@ -1,4 +1,4 @@ -WARNING [3001] Cannot evaluate targeting rules and % options for setting 'stringContainsDogDefaultCat' (User Object is missing). You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +WARNING [3001] Cannot evaluate targeting rules and % options for setting 'stringContainsDogDefaultCat' (User Object is missing). You should pass a User Object to the evaluation methods like `GetValue()`/`GetValueAsync()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ INFO [5000] Evaluating 'stringContainsDogDefaultCat' Evaluating targeting rules and applying the first match if any: - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN 'Dog' => cannot evaluate, User Object is missing diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_not_matching_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_not_matching_targeted_attribute.txt index de7ee2db..49d12525 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_not_matching_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/1_targeting_rule/1_rule_not_matching_targeted_attribute.txt @@ -1,4 +1,4 @@ -INFO [5000] Evaluating 'stringContainsDogDefaultCat' for User '{"Identifier": "12345", "Email": "joe@example.com", "Country": null, "Custom": null}' +INFO [5000] Evaluating 'stringContainsDogDefaultCat' for User '{"Identifier":"12345","Email":"joe@example.com"}' Evaluating targeting rules and applying the first match if any: - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN 'Dog' => no match Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules.json b/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules.json index 5da2b635..5cf8a3c8 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules.json @@ -1,4 +1,5 @@ { + "configUrl": "https://app.configcat.com/08d5a03c-feb7-af1e-a1fa-40b3329f8bed/08d62463-86ec-8fde-f5b5-1c5c426fc830/244cf8b0-f604-11e8-b543-f23c917f9d8d", "sdkKey": "PKDVCLf-Hq-h-kCzMp-L7Q/psuH7BGHoUmdONrzzUOY7A", "tests": [ { @@ -37,4 +38,4 @@ "expectedLog": "2_rules_matching_targeted_attribute.txt" } ] -} \ No newline at end of file +} diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_matching_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_matching_targeted_attribute.txt index c9c05094..eeeb64e2 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_matching_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_matching_targeted_attribute.txt @@ -1,5 +1,7 @@ -INFO [5000] Evaluating 'stringIsInDogDefaultCat' for User '{"Identifier": "12345", "Email": null, "Country": null, "Custom": {"Custom1": "admin"}}' +WARNING [3003] Cannot evaluate condition (User.Email IS ONE OF (hashed) ['265522bb68...', '72ff4554fa...']) for setting 'stringIsInDogDefaultCat' (the User.Email attribute is missing). You should set the User.Email attribute in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +INFO [5000] Evaluating 'stringIsInDogDefaultCat' for User '{"Identifier":"12345","Custom1":"admin"}' Evaluating targeting rules and applying the first match if any: - - IF User.Email IS ONE OF (hashed) ['a79a58142e...', '8af1824d6c...'] THEN 'Dog' => no match - - IF User.Custom1 IS ONE OF (hashed) ['e01dfbe824...'] THEN 'Dog' => MATCH, applying rule + - IF User.Email IS ONE OF (hashed) ['265522bb68...', '72ff4554fa...'] THEN 'Dog' => cannot evaluate, the User.Email attribute is missing + The current targeting rule is ignored and the evaluation continues with the next rule. + - IF User.Custom1 IS ONE OF (hashed) ['3eec7c82dd...'] THEN 'Dog' => MATCH, applying rule Returning 'Dog'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_no_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_no_targeted_attribute.txt index 7504b43d..cbb1f0d2 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_no_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_no_targeted_attribute.txt @@ -1,5 +1,9 @@ -INFO [5000] Evaluating 'stringIsInDogDefaultCat' for User '{"Identifier": "12345", "Email": null, "Country": null, "Custom": null}' +WARNING [3003] Cannot evaluate condition (User.Email IS ONE OF (hashed) ['265522bb68...', '72ff4554fa...']) for setting 'stringIsInDogDefaultCat' (the User.Email attribute is missing). You should set the User.Email attribute in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +WARNING [3003] Cannot evaluate condition (User.Custom1 IS ONE OF (hashed) ['3eec7c82dd...']) for setting 'stringIsInDogDefaultCat' (the User.Custom1 attribute is missing). You should set the User.Custom1 attribute in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +INFO [5000] Evaluating 'stringIsInDogDefaultCat' for User '{"Identifier":"12345"}' Evaluating targeting rules and applying the first match if any: - - IF User.Email IS ONE OF (hashed) ['a79a58142e...', '8af1824d6c...'] THEN 'Dog' => no match - - IF User.Custom1 IS ONE OF (hashed) ['e01dfbe824...'] THEN 'Dog' => no match + - IF User.Email IS ONE OF (hashed) ['265522bb68...', '72ff4554fa...'] THEN 'Dog' => cannot evaluate, the User.Email attribute is missing + The current targeting rule is ignored and the evaluation continues with the next rule. + - IF User.Custom1 IS ONE OF (hashed) ['3eec7c82dd...'] THEN 'Dog' => cannot evaluate, the User.Custom1 attribute is missing + The current targeting rule is ignored and the evaluation continues with the next rule. Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_no_user.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_no_user.txt index d00050e9..f9ab0aa7 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_no_user.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_no_user.txt @@ -1,9 +1,8 @@ -WARNING [3001] Cannot evaluate targeting rules and % options for setting 'stringIsInDogDefaultCat' (User Object is missing). You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ -WARNING [3001] Cannot evaluate targeting rules and % options for setting 'stringIsInDogDefaultCat' (User Object is missing). You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +WARNING [3001] Cannot evaluate targeting rules and % options for setting 'stringIsInDogDefaultCat' (User Object is missing). You should pass a User Object to the evaluation methods like `GetValue()`/`GetValueAsync()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ INFO [5000] Evaluating 'stringIsInDogDefaultCat' Evaluating targeting rules and applying the first match if any: - - IF User.Email IS ONE OF (hashed) ['a79a58142e...', '8af1824d6c...'] THEN 'Dog' => cannot evaluate, User Object is missing + - IF User.Email IS ONE OF (hashed) ['265522bb68...', '72ff4554fa...'] THEN 'Dog' => cannot evaluate, User Object is missing The current targeting rule is ignored and the evaluation continues with the next rule. - - IF User.Custom1 IS ONE OF (hashed) ['e01dfbe824...'] THEN 'Dog' => cannot evaluate, User Object is missing + - IF User.Custom1 IS ONE OF (hashed) ['3eec7c82dd...'] THEN 'Dog' => cannot evaluate, User Object is missing The current targeting rule is ignored and the evaluation continues with the next rule. Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_not_matching_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_not_matching_targeted_attribute.txt index 8c0850be..2865e253 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_not_matching_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/2_targeting_rules/2_rules_not_matching_targeted_attribute.txt @@ -1,5 +1,7 @@ -INFO [5000] Evaluating 'stringIsInDogDefaultCat' for User '{"Identifier": "12345", "Email": null, "Country": null, "Custom": {"Custom1": "user"}}' +WARNING [3003] Cannot evaluate condition (User.Email IS ONE OF (hashed) ['265522bb68...', '72ff4554fa...']) for setting 'stringIsInDogDefaultCat' (the User.Email attribute is missing). You should set the User.Email attribute in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +INFO [5000] Evaluating 'stringIsInDogDefaultCat' for User '{"Identifier":"12345","Custom1":"user"}' Evaluating targeting rules and applying the first match if any: - - IF User.Email IS ONE OF (hashed) ['a79a58142e...', '8af1824d6c...'] THEN 'Dog' => no match - - IF User.Custom1 IS ONE OF (hashed) ['e01dfbe824...'] THEN 'Dog' => no match + - IF User.Email IS ONE OF (hashed) ['265522bb68...', '72ff4554fa...'] THEN 'Dog' => cannot evaluate, the User.Email attribute is missing + The current targeting rule is ignored and the evaluation continues with the next rule. + - IF User.Custom1 IS ONE OF (hashed) ['3eec7c82dd...'] THEN 'Dog' => no match Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency/circular_dependency_override.json b/src/ConfigCat.Client.Tests/data/evaluationlog/_overrides/circular_dependency_override.json similarity index 74% rename from src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency/circular_dependency_override.json rename to src/ConfigCat.Client.Tests/data/evaluationlog/_overrides/circular_dependency_override.json index 75ad9036..39c53c08 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency/circular_dependency_override.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/_overrides/circular_dependency_override.json @@ -4,18 +4,25 @@ "r": 0 }, "f": { - "key1": { "v": { "s": "value1" }, + "key1": { + "t": 1, + "v": { "s": "value1" }, "r": [ {"c": [{"d": {"f": "key2", "c": 0, "v": {"s": "fourth"}}}], "s": {"v": {"s": "first"}}}, {"c": [{"d": {"f": "key3", "c": 0, "v": {"s": "value3"}}}], "s": {"v": {"s": "second"}}} ] }, - "key2": { "v": { "s": "value2" }, + "key2": { + "t": 1, + "v": { "s": "value2" }, "r": [ {"c": [{"d": {"f": "key1", "c": 0, "v": {"s": "value1"}}}], "s": {"v": {"s": "third"}}}, {"c": [{"d": {"f": "key3", "c": 0, "v": {"s": "value3"}}}], "s": {"v": {"s": "fourth"}}} ] }, - "key3": { "v": { "s": "value3" }} + "key3": { + "t": 1, + "v": { "s": "value3" } + } } } diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules.json b/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules.json index d30c4570..a3a6491a 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules.json @@ -1,4 +1,5 @@ { + "configUrl": "https://test-app.configcat.com/v2/08d89dea-13b2-406b-8ecf-ee94414208a2/08db465d-5756-49ff-8e53-fb90fd760632/08db4c16-c78b-473c-8b68-ca6723c98bfa/08db465d-a64e-4881-8ed0-62b6c9e68e33", "sdkKey": "configcat-sdk-1/XUbbCFZX_0mOU_uQ_XYGMg/FfwncdJg1kq0lBqxhYC_7g", "baseUrl": "https://test-cdn-eu.configcat.com", "tests": [ diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules/and_rules_no_user.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules/and_rules_no_user.txt index 8072e12e..27541e00 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules/and_rules_no_user.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules/and_rules_no_user.txt @@ -1,7 +1,7 @@ -WARNING [3001] Cannot evaluate targeting rules and % options for setting 'emailAnd' (User Object is missing). You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +WARNING [3001] Cannot evaluate targeting rules and % options for setting 'emailAnd' (User Object is missing). You should pass a User Object to the evaluation methods like `GetValue()`/`GetValueAsync()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ INFO [5000] Evaluating 'emailAnd' Evaluating targeting rules and applying the first match if any: - - IF User.Email STARTS WITH ANY OF (hashed) ['4_985cf0de...'] => False, skipping the remaining AND conditions + - IF User.Email STARTS WITH ANY OF (hashed) ['4_489600ff...'] => false, skipping the remaining AND conditions THEN 'Dog' => cannot evaluate, User Object is missing The current targeting rule is ignored and the evaluation continues with the next rule. Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules/and_rules_user.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules/and_rules_user.txt index 623d2f25..5d92a8ef 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules/and_rules_user.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/and_rules/and_rules_user.txt @@ -1,7 +1,7 @@ -INFO [5000] Evaluating 'emailAnd' for User '{"Identifier": "12345", "Email": "jane@configcat.com", "Country": null, "Custom": null}' +INFO [5000] Evaluating 'emailAnd' for User '{"Identifier":"12345","Email":"jane@configcat.com"}' Evaluating targeting rules and applying the first match if any: - - IF User.Email STARTS WITH ANY OF (hashed) ['4_985cf0de...'] => True - AND User.Email CONTAINS ANY OF ['@'] => True - AND User.Email ENDS WITH (hashed) ['20_37bff8e...'] => False, skipping the remaining AND conditions + - IF User.Email STARTS WITH ANY OF (hashed) ['4_489600ff...'] => true + AND User.Email CONTAINS ANY OF ['@'] => true + AND User.Email ENDS WITH ANY OF (hashed) ['20_be728e1...'] => false, skipping the remaining AND conditions THEN 'Dog' => no match Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency.json b/src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency.json index fd6c5186..cb50d22f 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency.json @@ -1,7 +1,5 @@ { "jsonOverride": "circular_dependency_override.json", - "sdkKey": "", - "baseUrl": "", "tests": [ { "key": "key1", @@ -13,4 +11,4 @@ "expectedLog": "circular_dependency.txt" } ] -} \ No newline at end of file +} diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency/circular_dependency.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency/circular_dependency.txt index 2d96b4e3..3dcbcb0f 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency/circular_dependency.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/circular_dependency/circular_dependency.txt @@ -1,23 +1,21 @@ -WARNING [3005] Cannot evaluate targeting rules for 'key1' (circular dependency detected between the following depending flags: 'key1' -> 'key2' -> 'key1'). Please check your feature flag definition and eliminate the circular dependency. -INFO [5000] Evaluating 'key1' for User '{"Identifier": "1234", "Email": null, "Country": null, "Custom": null}' +WARNING [3005] Cannot evaluate condition (Flag 'key1' EQUALS 'value1') for setting 'key2' (circular dependency detected between the following depending flags: 'key1' -> 'key2' -> 'key1'). Please check your feature flag definition and eliminate the circular dependency. +INFO [5000] Evaluating 'key1' for User '{"Identifier":"1234"}' Evaluating targeting rules and applying the first match if any: - - IF flag 'key2' EQUALS 'fourth' + - IF Flag 'key2' EQUALS 'fourth' ( Evaluating prerequisite flag 'key2': Evaluating targeting rules and applying the first match if any: - - IF flag 'key1' EQUALS 'value1' + - IF Flag 'key1' EQUALS 'value1' THEN 'third' => cannot evaluate, circular dependency detected + The current targeting rule is ignored and the evaluation continues with the next rule. + - IF Flag 'key3' EQUALS 'value3' ( - Evaluating prerequisite flag 'key1':THEN 'third' => Cannot evaluate targeting rules for 'key1' (circular dependency detected between the following depending flags: 'key1' -> 'key2' -> 'key1'). Please check your feature flag definition and eliminate the circular dependency. - The current targeting rule is ignored and the evaluation continues with the next rule. - - IF flag 'key3' EQUALS 'value3' - ( - Evaluating prerequisite flag 'key3': - Prerequisite flag evaluation result: 'value3' - Condition: (Flag 'key3' EQUALS 'value3') evaluates to True. - ) - THEN 'fourth' => MATCH, applying rule - Prerequisite flag evaluation result: 'fourth' - Condition: (Flag 'key2' EQUALS 'fourth') evaluates to True. - ) - THEN 'first' => MATCH, applying rule - Returning 'first'. + Evaluating prerequisite flag 'key3': + Prerequisite flag evaluation result: 'value3'. + Condition (Flag 'key3' EQUALS 'value3') evaluates to true. + ) + THEN 'fourth' => MATCH, applying rule + Prerequisite flag evaluation result: 'fourth'. + Condition (Flag 'key2' EQUALS 'fourth') evaluates to true. + ) + THEN 'first' => MATCH, applying rule + Returning 'first'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule.json b/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule.json index e75d474b..803840e2 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule.json @@ -1,4 +1,5 @@ { + "configUrl": "https://app.configcat.com/08d5a03c-feb7-af1e-a1fa-40b3329f8bed/08d62463-86ec-8fde-f5b5-1c5c426fc830/244cf8b0-f604-11e8-b543-f23c917f9d8d", "sdkKey": "PKDVCLf-Hq-h-kCzMp-L7Q/psuH7BGHoUmdONrzzUOY7A", "tests": [ { diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_matching_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_matching_targeted_attribute.txt index 164f0ce3..6815fa39 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_matching_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_matching_targeted_attribute.txt @@ -1,4 +1,4 @@ -INFO [5000] Evaluating 'integer25One25Two25Three25FourAdvancedRules' for User '{"Identifier": "12345", "Email": "joe@configcat.com", "Country": null, "Custom": null}' +INFO [5000] Evaluating 'integer25One25Two25Three25FourAdvancedRules' for User '{"Identifier":"12345","Email":"joe@configcat.com"}' Evaluating targeting rules and applying the first match if any: - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN '5' => MATCH, applying rule Returning '5'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_no_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_no_targeted_attribute.txt index 3398e7d6..8e6facb8 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_no_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_no_targeted_attribute.txt @@ -1,7 +1,9 @@ -INFO [5000] Evaluating 'integer25One25Two25Three25FourAdvancedRules' for User '{"Identifier": "12345", "Email": null, "Country": null, "Custom": null}' +WARNING [3003] Cannot evaluate condition (User.Email CONTAINS ANY OF ['@configcat.com']) for setting 'integer25One25Two25Three25FourAdvancedRules' (the User.Email attribute is missing). You should set the User.Email attribute in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +INFO [5000] Evaluating 'integer25One25Two25Three25FourAdvancedRules' for User '{"Identifier":"12345"}' Evaluating targeting rules and applying the first match if any: - - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN '5' => no match - Evaluating % options based on the User.Identifier attribute: - - Computing hash in the [0..99] range from User.Identifier => 25 (this value is sticky and consistent across all SDKs) - - Hash value 25 selects % option 2 (50%), '2' + - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN '5' => cannot evaluate, the User.Email attribute is missing + The current targeting rule is ignored and the evaluation continues with the next rule. + Evaluating % options based on the User.Identifier attribute: + - Computing hash in the [0..99] range from User.Identifier => 25 (this value is sticky and consistent across all SDKs) + - Hash value 25 selects % option 2 (25%), '2'. Returning '2'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_no_user.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_no_user.txt index e5560d0b..b7384194 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_no_user.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_no_user.txt @@ -1,8 +1,7 @@ -WARNING [3001] Cannot evaluate targeting rules and % options for setting 'integer25One25Two25Three25FourAdvancedRules' (User Object is missing). You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ -WARNING [3001] Cannot evaluate % options for setting 'integer25One25Two25Three25FourAdvancedRules' (User Object is missing). You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +WARNING [3001] Cannot evaluate targeting rules and % options for setting 'integer25One25Two25Three25FourAdvancedRules' (User Object is missing). You should pass a User Object to the evaluation methods like `GetValue()`/`GetValueAsync()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ INFO [5000] Evaluating 'integer25One25Two25Three25FourAdvancedRules' Evaluating targeting rules and applying the first match if any: - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN '5' => cannot evaluate, User Object is missing The current targeting rule is ignored and the evaluation continues with the next rule. - Skipping % options because the User Object is missing. + Skipping % options because the User Object is missing. Returning '-1'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_not_matching_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_not_matching_targeted_attribute.txt index 5927dd5a..c412e5a5 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_not_matching_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_after_targeting_rule/options_after_targeting_rule_not_matching_targeted_attribute.txt @@ -1,7 +1,7 @@ -INFO [5000] Evaluating 'integer25One25Two25Three25FourAdvancedRules' for User '{"Identifier": "12345", "Email": "joe@example.com", "Country": null, "Custom": null}' +INFO [5000] Evaluating 'integer25One25Two25Three25FourAdvancedRules' for User '{"Identifier":"12345","Email":"joe@example.com"}' Evaluating targeting rules and applying the first match if any: - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN '5' => no match - Evaluating % options based on the User.Identifier attribute: - - Computing hash in the [0..99] range from User.Identifier => 25 (this value is sticky and consistent across all SDKs) - - Hash value 25 selects % option 2 (50%), '2' + Evaluating % options based on the User.Identifier attribute: + - Computing hash in the [0..99] range from User.Identifier => 25 (this value is sticky and consistent across all SDKs) + - Hash value 25 selects % option 2 (25%), '2'. Returning '2'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr.json b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr.json index 87cb7744..efa16493 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr.json @@ -1,4 +1,5 @@ { + "configUrl": "https://test-app.configcat.com/v2/08d89dea-13b2-406b-8ecf-ee94414208a2/08db465d-5756-49ff-8e53-fb90fd760632/08db6eb8-cdfa-4adc-880b-34f75432cc36/08db465d-a64e-4881-8ed0-62b6c9e68e33", "sdkKey": "configcat-sdk-1/XUbbCFZX_0mOU_uQ_XYGMg/x0tcrFMkl02A65D8GD20Eg", "baseUrl": "https://test-cdn-eu.configcat.com", "tests": [ diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/matching_options_custom_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/matching_options_custom_attribute.txt index d3c83123..2621086b 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/matching_options_custom_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/matching_options_custom_attribute.txt @@ -1,5 +1,5 @@ -INFO [5000] Evaluating 'string75Cat0Dog25Falcon0HorseCustomAttr' for User '{"Identifier": "12345", "Email": null, "Country": "US", "Custom": null}' +INFO [5000] Evaluating 'string75Cat0Dog25Falcon0HorseCustomAttr' for User '{"Identifier":"12345","Country":"US"}' Evaluating % options based on the User.Country attribute: - Computing hash in the [0..99] range from User.Country => 70 (this value is sticky and consistent across all SDKs) - - Hash value 70 selects % option 1 (75%), 'Cat' + - Hash value 70 selects % option 1 (75%), 'Cat'. Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/no_options_custom_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/no_options_custom_attribute.txt index e152f5df..c92c5bcb 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/no_options_custom_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/no_options_custom_attribute.txt @@ -1,4 +1,4 @@ -INFO [5000] Evaluating 'string75Cat0Dog25Falcon0HorseCustomAttr' for User '{"Identifier": "12345", "Email": null, "Country": null, "Custom": null}' +WARNING [3003] Cannot evaluate % options for setting 'string75Cat0Dog25Falcon0HorseCustomAttr' (the User.Country attribute is missing). You should set the User.Country attribute in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +INFO [5000] Evaluating 'string75Cat0Dog25Falcon0HorseCustomAttr' for User '{"Identifier":"12345"}' Skipping % options because the User.Country attribute is missing. - The current targeting rule is ignored and the evaluation continues with the next rule. Returning 'Chicken'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/options_custom_attribute_no_user.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/options_custom_attribute_no_user.txt index 4d0b24ec..50b92afc 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/options_custom_attribute_no_user.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_custom_attr/options_custom_attribute_no_user.txt @@ -1,4 +1,4 @@ -WARNING [3001] Cannot evaluate % options for setting 'string75Cat0Dog25Falcon0HorseCustomAttr' (User Object is missing). You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +WARNING [3001] Cannot evaluate targeting rules and % options for setting 'string75Cat0Dog25Falcon0HorseCustomAttr' (User Object is missing). You should pass a User Object to the evaluation methods like `GetValue()`/`GetValueAsync()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ INFO [5000] Evaluating 'string75Cat0Dog25Falcon0HorseCustomAttr' Skipping % options because the User Object is missing. Returning 'Chicken'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id.json b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id.json index 66ce6fa3..442f575c 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id.json @@ -1,4 +1,5 @@ { + "configUrl": "https://app.configcat.com/08d5a03c-feb7-af1e-a1fa-40b3329f8bed/08d62463-86ec-8fde-f5b5-1c5c426fc830/244cf8b0-f604-11e8-b543-f23c917f9d8d", "sdkKey": "PKDVCLf-Hq-h-kCzMp-L7Q/psuH7BGHoUmdONrzzUOY7A", "tests": [ { diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id/options_user_attribute_no_user.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id/options_user_attribute_no_user.txt index 860a7641..2b1849ba 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id/options_user_attribute_no_user.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id/options_user_attribute_no_user.txt @@ -1,5 +1,4 @@ -WARNING [3001] Cannot evaluate % options for setting 'string75Cat0Dog25Falcon0Horse' (User Object is missing). You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +WARNING [3001] Cannot evaluate targeting rules and % options for setting 'string75Cat0Dog25Falcon0Horse' (User Object is missing). You should pass a User Object to the evaluation methods like `GetValue()`/`GetValueAsync()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ INFO [5000] Evaluating 'string75Cat0Dog25Falcon0Horse' - Evaluating targeting rules and applying the first match if any: - Skipping % options because the User Object is missing. + Skipping % options because the User Object is missing. Returning 'Chicken'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id/options_user_attribute_user.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id/options_user_attribute_user.txt index 03abefb3..dac8dd6a 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id/options_user_attribute_user.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_based_on_user_id/options_user_attribute_user.txt @@ -1,6 +1,5 @@ -INFO [5000] Evaluating 'string75Cat0Dog25Falcon0Horse' for User '{"Identifier": "12345", "Email": null, "Country": null, "Custom": null}' - Evaluating targeting rules and applying the first match if any: - Evaluating % options based on the User.Identifier attribute: - - Computing hash in the [0..99] range from User.Identifier => 21 (this value is sticky and consistent across all SDKs) - - Hash value 21 selects % option 1 (75%), 'Cat' +INFO [5000] Evaluating 'string75Cat0Dog25Falcon0Horse' for User '{"Identifier":"12345"}' + Evaluating % options based on the User.Identifier attribute: + - Computing hash in the [0..99] range from User.Identifier => 21 (this value is sticky and consistent across all SDKs) + - Hash value 21 selects % option 1 (75%), 'Cat'. Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule.json b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule.json index 1c75a3d3..5a461cec 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule.json @@ -1,5 +1,6 @@ { - "sdkKey": "configcat-sdk-1/pCDbCNTRQEOE2b2xikWfkQ/xUqZMLx8d02UDWE0QMdUgA", + "configUrl": "https://test-app.configcat.com/v2/08d89dea-13b2-406b-8ecf-ee94414208a2/08db465d-5756-49ff-8e53-fb90fd760632/08db6eb8-cdfa-4adc-880b-34f75432cc36/08db465d-a64e-4881-8ed0-62b6c9e68e33", + "sdkKey": "configcat-sdk-1/XUbbCFZX_0mOU_uQ_XYGMg/x0tcrFMkl02A65D8GD20Eg", "baseUrl": "https://test-cdn-eu.configcat.com", "tests": [ { diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_matching_targeted_attribute_no_options_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_matching_targeted_attribute_no_options_attribute.txt index 39f1dfd5..db721f51 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_matching_targeted_attribute_no_options_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_matching_targeted_attribute_no_options_attribute.txt @@ -1,4 +1,5 @@ -INFO [5000] Evaluating 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' for User '{"Identifier": "12345", "Email": "joe@configcat.com", "Country": null, "Custom": null}' +WARNING [3003] Cannot evaluate % options for setting 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' (the User.Country attribute is missing). You should set the User.Country attribute in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +INFO [5000] Evaluating 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' for User '{"Identifier":"12345","Email":"joe@configcat.com"}' Evaluating targeting rules and applying the first match if any: - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN % options => MATCH, applying rule Skipping % options because the User.Country attribute is missing. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_matching_targeted_attribute_options_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_matching_targeted_attribute_options_attribute.txt index 86bba74a..81295215 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_matching_targeted_attribute_options_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_matching_targeted_attribute_options_attribute.txt @@ -1,7 +1,7 @@ -INFO [5000] Evaluating 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' for User '{"Identifier": "12345", "Email": "joe@configcat.com", "Country": "US", "Custom": null}' +INFO [5000] Evaluating 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' for User '{"Identifier":"12345","Email":"joe@configcat.com","Country":"US"}' Evaluating targeting rules and applying the first match if any: - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN % options => MATCH, applying rule Evaluating % options based on the User.Country attribute: - Computing hash in the [0..99] range from User.Country => 63 (this value is sticky and consistent across all SDKs) - - Hash value 63 selects % option 1 (75%), 'Cat' + - Hash value 63 selects % option 1 (75%), 'Cat'. Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_no_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_no_targeted_attribute.txt index 8f533c38..74f812f4 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_no_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_no_targeted_attribute.txt @@ -1,4 +1,6 @@ -INFO [5000] Evaluating 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' for User '{"Identifier": "12345", "Email": null, "Country": null, "Custom": null}' +WARNING [3003] Cannot evaluate condition (User.Email CONTAINS ANY OF ['@configcat.com']) for setting 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' (the User.Email attribute is missing). You should set the User.Email attribute in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +INFO [5000] Evaluating 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' for User '{"Identifier":"12345"}' Evaluating targeting rules and applying the first match if any: - - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN % options => no match + - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN % options => cannot evaluate, the User.Email attribute is missing + The current targeting rule is ignored and the evaluation continues with the next rule. Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_no_user.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_no_user.txt index 6224e5ae..e886be82 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_no_user.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_no_user.txt @@ -1,4 +1,4 @@ -WARNING [3001] Cannot evaluate targeting rules and % options for setting 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' (User Object is missing). You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +WARNING [3001] Cannot evaluate targeting rules and % options for setting 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' (User Object is missing). You should pass a User Object to the evaluation methods like `GetValue()`/`GetValueAsync()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ INFO [5000] Evaluating 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' Evaluating targeting rules and applying the first match if any: - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN % options => cannot evaluate, User Object is missing diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_not_matching_targeted_attribute.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_not_matching_targeted_attribute.txt index de4823c6..dd6032e5 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_not_matching_targeted_attribute.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/options_within_targeting_rule/options_within_targeting_rule_not_matching_targeted_attribute.txt @@ -1,4 +1,4 @@ -INFO [5000] Evaluating 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' for User '{"Identifier": "12345", "Email": "joe@example.com", "Country": null, "Custom": null}' +INFO [5000] Evaluating 'stringContainsString75Cat0Dog25Falcon0HorseDefaultCat' for User '{"Identifier":"12345","Email":"joe@example.com"}' Evaluating targeting rules and applying the first match if any: - IF User.Email CONTAINS ANY OF ['@configcat.com'] THEN % options => no match Returning 'Cat'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/prerequisite_flag.json b/src/ConfigCat.Client.Tests/data/evaluationlog/prerequisite_flag.json index b304a129..b69c5333 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/prerequisite_flag.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/prerequisite_flag.json @@ -1,4 +1,5 @@ { + "configUrl": "https://test-app.configcat.com/v2/08d89dea-13b2-406b-8ecf-ee94414208a2/08db465d-5756-49ff-8e53-fb90fd760632/08db4c16-c78b-473c-8b68-ca6723c98bfa/08db465d-a64e-4881-8ed0-62b6c9e68e33", "sdkKey": "configcat-sdk-1/XUbbCFZX_0mOU_uQ_XYGMg/FfwncdJg1kq0lBqxhYC_7g", "baseUrl": "https://test-cdn-eu.configcat.com", "tests": [ @@ -14,4 +15,4 @@ "expectedLog": "prerequisite_flag.txt" } ] -} \ No newline at end of file +} diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/prerequisite_flag/prerequisite_flag.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/prerequisite_flag/prerequisite_flag.txt index fc281f6c..948940c9 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/prerequisite_flag/prerequisite_flag.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/prerequisite_flag/prerequisite_flag.txt @@ -1,32 +1,32 @@ -INFO [5000] Evaluating 'dependentFeature' for User '{"Identifier": "12345", "Email": "kate@configcat.com", "Country": "USA", "Custom": null}' +INFO [5000] Evaluating 'dependentFeature' for User '{"Identifier":"12345","Email":"kate@configcat.com","Country":"USA"}' Evaluating targeting rules and applying the first match if any: - - IF flag 'mainFeature' EQUALS 'target' + - IF Flag 'mainFeature' EQUALS 'target' ( Evaluating prerequisite flag 'mainFeature': Evaluating targeting rules and applying the first match if any: - - IF User.Email ENDS WITH (hashed) ['21_afedf39...'] => False, skipping the remaining AND conditions + - IF User.Email ENDS WITH ANY OF (hashed) ['21_57e6ffe...'] => false, skipping the remaining AND conditions THEN 'private' => no match - - IF User.Country IS ONE OF (hashed) ['f17aae9d1a...'] => True + - IF User.Country IS ONE OF (hashed) ['172faabf6a...'] => true AND User IS NOT IN SEGMENT 'Beta Users' ( Evaluating segment 'Beta Users': - - IF User.Email IS ONE OF (hashed) ['3b10c030fb...', '63aadd8165...'] => False, skipping the remaining AND conditions + - IF User.Email IS ONE OF (hashed) ['53b705ed36...', '9a043335df...'] => false, skipping the remaining AND conditions Segment evaluation result: User IS NOT IN SEGMENT. - Condition (User IS NOT IN SEGMENT 'Beta Users') evaluates to True. - ) => True + Condition (User IS NOT IN SEGMENT 'Beta Users') evaluates to true. + ) => true AND User IS NOT IN SEGMENT 'Developers' ( Evaluating segment 'Developers': - - IF User.Email IS ONE OF (hashed) ['b3892c655a...', '026df07501...'] => False, skipping the remaining AND conditions + - IF User.Email IS ONE OF (hashed) ['242f9fc710...', 'b2f917f062...'] => false, skipping the remaining AND conditions Segment evaluation result: User IS NOT IN SEGMENT. - Condition (User IS NOT IN SEGMENT 'Developers') evaluates to True. - ) => True + Condition (User IS NOT IN SEGMENT 'Developers') evaluates to true. + ) => true THEN 'target' => MATCH, applying rule - Prerequisite flag evaluation result: 'target' - Condition: (Flag 'mainFeature' EQUALS 'target') evaluates to True. + Prerequisite flag evaluation result: 'target'. + Condition (Flag 'mainFeature' EQUALS 'target') evaluates to true. ) THEN % options => MATCH, applying rule Evaluating % options based on the User.Identifier attribute: - Computing hash in the [0..99] range from User.Identifier => 78 (this value is sticky and consistent across all SDKs) - - Hash value 78 selects % option 4 (100%), 'Horse' + - Hash value 78 selects % option 4 (25%), 'Horse'. Returning 'Horse'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/segment.json b/src/ConfigCat.Client.Tests/data/evaluationlog/segment.json index ef27078f..33bead38 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/segment.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/segment.json @@ -1,4 +1,5 @@ { + "configUrl": "https://app.configcat.com/08d5a03c-feb7-af1e-a1fa-40b3329f8bed/08d9f207-6883-43e5-868c-cbf677af3fe6/244cf8b0-f604-11e8-b543-f23c917f9d8d", "sdkKey": "PKDVCLf-Hq-h-kCzMp-L7Q/LcYz135LE0qbcacz2mgXnA", "tests": [ { @@ -27,6 +28,5 @@ "returnValue": false, "expectedLog": "segment_no_matching.txt" } - ] } diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_matching.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_matching.txt index 213d174f..03137a7f 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_matching.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_matching.txt @@ -1,11 +1,11 @@ -INFO [5000] Evaluating 'featureWithSegmentTargeting' for User '{"Identifier": "12345", "Email": "jane@example.com", "Country": null, "Custom": null}' +INFO [5000] Evaluating 'featureWithSegmentTargeting' for User '{"Identifier":"12345","Email":"jane@example.com"}' Evaluating targeting rules and applying the first match if any: - IF User IS IN SEGMENT 'Beta users' ( Evaluating segment 'Beta users': - - IF User.Email IS ONE OF (hashed) ['26fc71b9ce...', 'daaa967a93...'] => True + - IF User.Email IS ONE OF (hashed) ['26fc71b9ce...', 'daaa967a93...'] => true Segment evaluation result: User IS IN SEGMENT. - Condition (User IS IN SEGMENT 'Beta users') evaluates to True. + Condition (User IS IN SEGMENT 'Beta users') evaluates to true. ) THEN 'True' => MATCH, applying rule Returning 'True'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_no_matching.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_no_matching.txt index 075913f5..f044ba04 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_no_matching.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_no_matching.txt @@ -1,11 +1,11 @@ -INFO [5000] Evaluating 'featureWithNegatedSegmentTargeting' for User '{"Identifier": "12345", "Email": "jane@example.com", "Country": null, "Custom": null}' +INFO [5000] Evaluating 'featureWithNegatedSegmentTargeting' for User '{"Identifier":"12345","Email":"jane@example.com"}' Evaluating targeting rules and applying the first match if any: - IF User IS NOT IN SEGMENT 'Beta users' ( Evaluating segment 'Beta users': - - IF User.Email IS ONE OF (hashed) ['26fc71b9ce...', 'daaa967a93...'] => True + - IF User.Email IS ONE OF (hashed) ['26fc71b9ce...', 'daaa967a93...'] => true Segment evaluation result: User IS IN SEGMENT. - Condition (User IS NOT IN SEGMENT 'Beta users') evaluates to False. + Condition (User IS NOT IN SEGMENT 'Beta users') evaluates to false. ) THEN 'True' => no match Returning 'False'. diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_no_user.txt b/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_no_user.txt index 087f85e2..d61e3f9e 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_no_user.txt +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/segment/segment_no_user.txt @@ -1,4 +1,4 @@ -WARNING [3001] Cannot evaluate targeting rules and % options for setting 'featureWithSegmentTargeting' (User Object is missing). You should pass a User Object to the evaluation methods like `get_value()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ +WARNING [3001] Cannot evaluate targeting rules and % options for setting 'featureWithSegmentTargeting' (User Object is missing). You should pass a User Object to the evaluation methods like `GetValue()`/`GetValueAsync()` in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/ INFO [5000] Evaluating 'featureWithSegmentTargeting' Evaluating targeting rules and applying the first match if any: - IF User IS IN SEGMENT 'Beta users' THEN 'True' => cannot evaluate, User Object is missing diff --git a/src/ConfigCat.Client.Tests/data/evaluationlog/simple_value.json b/src/ConfigCat.Client.Tests/data/evaluationlog/simple_value.json index 8e03f2cc..070d6f59 100644 --- a/src/ConfigCat.Client.Tests/data/evaluationlog/simple_value.json +++ b/src/ConfigCat.Client.Tests/data/evaluationlog/simple_value.json @@ -1,4 +1,5 @@ { + "configUrl": "https://app.configcat.com/08d5a03c-feb7-af1e-a1fa-40b3329f8bed/08d62463-86ec-8fde-f5b5-1c5c426fc830/244cf8b0-f604-11e8-b543-f23c917f9d8d", "sdkKey": "PKDVCLf-Hq-h-kCzMp-L7Q/psuH7BGHoUmdONrzzUOY7A", "tests": [ { @@ -33,4 +34,4 @@ "expectedLog": "double_setting.txt" } ] -} \ No newline at end of file +} diff --git a/src/ConfigCatClient/ConfigCatClient.cs b/src/ConfigCatClient/ConfigCatClient.cs index 54146364..d5703101 100644 --- a/src/ConfigCatClient/ConfigCatClient.cs +++ b/src/ConfigCatClient/ConfigCatClient.cs @@ -54,6 +54,11 @@ private static bool IsValidSdkKey(string sdkKey, bool customBaseUrl) }; } + internal static string GetProductVersion(PollingMode pollingMode) + { + return $"{pollingMode.Identifier}-{Version}"; + } + internal static string GetCacheKey(string sdkKey) { var key = $"{sdkKey}_{ConfigCatClientOptions.ConfigFileName}_{ProjectConfig.SerializationFormatVersion}"; @@ -97,7 +102,7 @@ internal ConfigCatClient(string sdkKey, ConfigCatClientOptions options) this.configService = this.overrideBehaviour != OverrideBehaviour.LocalOnly ? DetermineConfigService(pollingMode, new HttpConfigFetcher(options.CreateUri(sdkKey), - $"{pollingMode.Identifier}-{Version}", + GetProductVersion(pollingMode), this.logger, options.HttpClientHandler, options.IsCustomBaseUrl,