From e7e803ed553b82f7d32bec4f9c95cd573dacaadb Mon Sep 17 00:00:00 2001 From: Sohail Hussain Date: Tue, 14 Apr 2020 13:16:24 -0700 Subject: [PATCH 1/2] feature variable type enum removed --- .../EntityTests/FeatureVariableTest.cs | 19 +++++--- OptimizelySDK.Tests/OptimizelyTest.cs | 44 ++++++++++++------- OptimizelySDK.Tests/TestData.json | 24 +++++++++- OptimizelySDK/Entity/FeatureVariable.cs | 26 +++++------ OptimizelySDK/Optimizely.cs | 20 ++++----- 5 files changed, 86 insertions(+), 47 deletions(-) diff --git a/OptimizelySDK.Tests/EntityTests/FeatureVariableTest.cs b/OptimizelySDK.Tests/EntityTests/FeatureVariableTest.cs index c4956dfb..e4324652 100644 --- a/OptimizelySDK.Tests/EntityTests/FeatureVariableTest.cs +++ b/OptimizelySDK.Tests/EntityTests/FeatureVariableTest.cs @@ -1,5 +1,5 @@ /* - * Copyright 2019, Optimizely + * Copyright 2019-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,10 +26,19 @@ public class FeatureVariableTest [Test] public void TestFeatureVariableTypeName() { - Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.VariableType.BOOLEAN), "GetFeatureVariableBoolean"); - Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.VariableType.DOUBLE), "GetFeatureVariableDouble"); - Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.VariableType.INTEGER), "GetFeatureVariableInteger"); - Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.VariableType.STRING), "GetFeatureVariableString"); + Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.BOOLEAN_TYPE), "GetFeatureVariableBoolean"); + Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.DOUBLE_TYPE), "GetFeatureVariableDouble"); + Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.INTEGER_TYPE), "GetFeatureVariableInteger"); + Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.STRING_TYPE), "GetFeatureVariableString"); + } + + [Test] + public void TestConstantValues() + { + Assert.AreEqual(FeatureVariable.BOOLEAN_TYPE, "boolean"); + Assert.AreEqual(FeatureVariable.DOUBLE_TYPE, "double"); + Assert.AreEqual(FeatureVariable.INTEGER_TYPE, "integer"); + Assert.AreEqual(FeatureVariable.STRING_TYPE, "string"); } } } diff --git a/OptimizelySDK.Tests/OptimizelyTest.cs b/OptimizelySDK.Tests/OptimizelyTest.cs index 798df053..84c77604 100644 --- a/OptimizelySDK.Tests/OptimizelyTest.cs +++ b/OptimizelySDK.Tests/OptimizelyTest.cs @@ -1158,7 +1158,7 @@ public void TestGetFeatureVariableBooleanReturnsCorrectValue() var variableKeyFalse = "varFalse"; var variableKeyNonBoolean = "varNonBoolean"; var variableKeyNull = "varNull"; - var featureVariableType = FeatureVariable.VariableType.BOOLEAN; + var featureVariableType = "boolean"; OptimizelyMock.Setup(om => om.GetFeatureVariableValueForType(It.IsAny(), variableKeyTrue, It.IsAny(), It.IsAny(), featureVariableType)).Returns(true); @@ -1253,7 +1253,7 @@ public void TestGetFeatureVariableDoubleReturnsCorrectValue() var variableKeyInt = "varInt"; var variableKeyNonDouble = "varNonDouble"; var variableKeyNull = "varNull"; - var featureVariableType = FeatureVariable.VariableType.DOUBLE; + var featureVariableType = "double"; OptimizelyMock.Setup(om => om.GetFeatureVariableValueForType(It.IsAny(), variableKeyDouble, It.IsAny(), It.IsAny(), featureVariableType)).Returns(100.54); @@ -1279,7 +1279,7 @@ public void TestGetFeatureVariableIntegerReturnsCorrectValue() var variableKeyInt = "varInt"; var variableNonInt = "varNonInt"; var variableKeyNull = "varNull"; - var featureVariableType = FeatureVariable.VariableType.INTEGER; + var featureVariableType = "integer"; OptimizelyMock.Setup(om => om.GetFeatureVariableValueForType(It.IsAny(), variableKeyInt, It.IsAny(), It.IsAny(), featureVariableType)).Returns(100); @@ -1301,7 +1301,7 @@ public void TestGetFeatureVariableStringReturnsCorrectValue() var variableKeyString = "varString1"; var variableKeyIntString = "varString2"; var variableKeyNull = "varNull"; - var featureVariableType = FeatureVariable.VariableType.STRING; + var featureVariableType = "string"; OptimizelyMock.Setup(om => om.GetFeatureVariableValueForType(It.IsAny(), variableKeyString, It.IsAny(), It.IsAny(), featureVariableType)).Returns("Test String"); @@ -1558,7 +1558,7 @@ public void TestGetFeatureVariableValueForTypeGivenNullOrEmptyArguments() { var featureKey = "featureKey"; var variableKey = "variableKey"; - var variableType = FeatureVariable.VariableType.BOOLEAN; + var variableType = "boolean"; // Passing null and empty feature key. Assert.IsNull(Optimizely.GetFeatureVariableValueForType(null, variableKey, TestUserId, null, variableType)); @@ -1583,7 +1583,7 @@ public void TestGetFeatureVariableValueForTypeGivenFeatureKeyOrVariableKeyNotFou { var featureKey = "this_feature_should_never_be_found_in_the_datafile_unless_the_datafile_creator_got_insane"; var variableKey = "this_variable_should_never_be_found_in_the_datafile_unless_the_datafile_creator_got_insane"; - var variableType = FeatureVariable.VariableType.BOOLEAN; + var variableType = "boolean"; Assert.IsNull(Optimizely.GetFeatureVariableValueForType(featureKey, variableKey, TestUserId, null, variableType)); Assert.IsNull(Optimizely.GetFeatureVariableValueForType("double_single_variable_feature", variableKey, TestUserId, null, variableType)); @@ -1597,10 +1597,10 @@ public void TestGetFeatureVariableValueForTypeGivenFeatureKeyOrVariableKeyNotFou [Test] public void TestGetFeatureVariableValueForTypeGivenInvalidVariableType() { - var variableTypeBool = FeatureVariable.VariableType.BOOLEAN; - var variableTypeInt = FeatureVariable.VariableType.INTEGER; - var variableTypeDouble = FeatureVariable.VariableType.DOUBLE; - var variableTypeString = FeatureVariable.VariableType.STRING; + var variableTypeBool = "boolean"; + var variableTypeInt = "integer"; + var variableTypeDouble = "double"; + var variableTypeString = "string"; Assert.IsNull(Optimizely.GetFeatureVariableValueForType("double_single_variable_feature", "double_variable", TestUserId, null, variableTypeBool)); Assert.IsNull(Optimizely.GetFeatureVariableValueForType("boolean_single_variable_feature", "boolean_variable", TestUserId, null, variableTypeDouble)); @@ -1608,13 +1608,23 @@ public void TestGetFeatureVariableValueForTypeGivenInvalidVariableType() Assert.IsNull(Optimizely.GetFeatureVariableValueForType("string_single_variable_feature", "string_variable", TestUserId, null, variableTypeInt)); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, - $@"Variable is of type ""DOUBLE"", but you requested it as type ""{variableTypeBool}"".")); + $@"Variable is of type ""double"", but you requested it as type ""{variableTypeBool}"".")); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, - $@"Variable is of type ""BOOLEAN"", but you requested it as type ""{variableTypeDouble}"".")); + $@"Variable is of type ""boolean"", but you requested it as type ""{variableTypeDouble}"".")); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, - $@"Variable is of type ""INTEGER"", but you requested it as type ""{variableTypeString}"".")); + $@"Variable is of type ""integer"", but you requested it as type ""{variableTypeString}"".")); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, - $@"Variable is of type ""STRING"", but you requested it as type ""{variableTypeInt}"".")); + $@"Variable is of type ""string"", but you requested it as type ""{variableTypeInt}"".")); + } + + [Test] + public void TestUnsupportedVariableType() + { + var featureVariableStringRandomType = Optimizely.GetFeatureVariableString("", "any_key", TestUserId); + Assert.IsNull(featureVariableStringRandomType); + + var featureVariableStringJsonType = Optimizely.GetFeatureVariableString("unsupported_variabletype", "string_json_key", TestUserId); + Assert.AreEqual(featureVariableStringJsonType, "{\"myvalue\": \"jsonValue\"}"); } // Should return default value and log message when feature is not enabled for the user. @@ -1626,7 +1636,7 @@ public void TestGetFeatureVariableValueForTypeGivenFeatureFlagIsNotEnabledForUse var experiment = Config.GetExperimentFromKey("test_experiment_double_feature"); var variation = Config.GetVariationFromKey("test_experiment_double_feature", "variation"); var variableKey = "double_variable"; - var variableType = FeatureVariable.VariableType.DOUBLE; + var variableType = "double"; var expectedValue = 14.99; var decision = new FeatureDecision(experiment, variation, FeatureDecision.DECISION_SOURCE_FEATURE_TEST); @@ -1656,7 +1666,7 @@ public void TestGetFeatureVariableValueForTypeGivenFeatureFlagIsEnabledForUserAn var differentVariation = Config.GetVariationFromKey("test_experiment_integer_feature", "control"); var expectedDecision = new FeatureDecision(experiment, differentVariation, FeatureDecision.DECISION_SOURCE_FEATURE_TEST); var variableKey = "double_variable"; - var variableType = FeatureVariable.VariableType.DOUBLE; + var variableType = "double"; var expectedValue = 14.99; // Mock GetVariationForFeature method to return variation of different feature. @@ -1682,7 +1692,7 @@ public void TestGetFeatureVariableValueForTypeGivenFeatureFlagIsEnabledForUserAn var featureKey = "double_single_variable_feature"; var featureFlag = Config.GetFeatureFlagFromKey("double_single_variable_feature"); var variableKey = "double_variable"; - var variableType = FeatureVariable.VariableType.DOUBLE; + var variableType = "double"; var expectedValue = 42.42; var experiment = Config.GetExperimentFromKey("test_experiment_double_feature"); var variation = Config.GetVariationFromKey("test_experiment_double_feature", "control"); diff --git a/OptimizelySDK.Tests/TestData.json b/OptimizelySDK.Tests/TestData.json index 3b36c288..0e44dc56 100644 --- a/OptimizelySDK.Tests/TestData.json +++ b/OptimizelySDK.Tests/TestData.json @@ -561,7 +561,7 @@ "key": "integer_variable", "type": "integer", "defaultValue": "7" - } + } ] }, { @@ -639,6 +639,28 @@ "rolloutId": "166662", "experimentIds": [], "variables": [] + }, + { + "id": "155566", + "key": "unsupported_variabletype", + "rolloutId": "166662", + "experimentIds": [], + "variables": [ + { + "id": "255554", + "key": "any_key", + "type": "random", + "defaultValue": "{}" + }, + { + "id": "255555", + "key": "string_json_key", + "type": "string", + "defaultValue": "{\"myvalue\": \"jsonValue\"}", + "subType": "json" + } + ] + } ], "rollouts": [ diff --git a/OptimizelySDK/Entity/FeatureVariable.cs b/OptimizelySDK/Entity/FeatureVariable.cs index 1d2d10fa..c0634b9e 100644 --- a/OptimizelySDK/Entity/FeatureVariable.cs +++ b/OptimizelySDK/Entity/FeatureVariable.cs @@ -1,5 +1,5 @@ /* - * Copyright 2017, 2019, Optimizely + * Copyright 2017, 2019-2020, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,22 +18,20 @@ namespace OptimizelySDK.Entity { public class FeatureVariable : IdKeyEntity { + public const string STRING_TYPE = "string"; + public const string INTEGER_TYPE = "integer"; + public const string DOUBLE_TYPE = "double"; + public const string BOOLEAN_TYPE = "boolean"; + public enum VariableStatus { ACTIVE, ARCHIVED } - public enum VariableType - { - BOOLEAN, - INTEGER, - DOUBLE, - STRING - } public string DefaultValue { get; set; } - public VariableType Type { get; set; } + public string Type { get; set; } public VariableStatus Status { get; set; } /// @@ -41,16 +39,16 @@ public enum VariableType /// /// The feature variable type name. /// Variable type. - public static string GetFeatureVariableTypeName(VariableType variableType) + public static string GetFeatureVariableTypeName(string variableType) { switch (variableType) { - case FeatureVariable.VariableType.BOOLEAN: + case BOOLEAN_TYPE: return "GetFeatureVariableBoolean"; - case FeatureVariable.VariableType.DOUBLE: + case DOUBLE_TYPE: return "GetFeatureVariableDouble"; - case FeatureVariable.VariableType.INTEGER: + case INTEGER_TYPE: return "GetFeatureVariableInteger"; - case FeatureVariable.VariableType.STRING: + case STRING_TYPE: return "GetFeatureVariableString"; default: return null; diff --git a/OptimizelySDK/Optimizely.cs b/OptimizelySDK/Optimizely.cs index 4bd0575e..d227597d 100644 --- a/OptimizelySDK/Optimizely.cs +++ b/OptimizelySDK/Optimizely.cs @@ -515,7 +515,7 @@ public virtual bool IsFeatureEnabled(string featureKey, string userId, UserAttri /// Variable type /// string | null Feature variable value public virtual T GetFeatureVariableValueForType(string featureKey, string variableKey, string userId, - UserAttributes userAttributes, FeatureVariable.VariableType variableType) + UserAttributes userAttributes, string variableType) { var config = ProjectConfigManager?.GetConfig(); @@ -620,7 +620,7 @@ public virtual T GetFeatureVariableValueForType(string featureKey, string var /// bool | Feature variable value or null public bool? GetFeatureVariableBoolean(string featureKey, string variableKey, string userId, UserAttributes userAttributes = null) { - return GetFeatureVariableValueForType(featureKey, variableKey, userId, userAttributes, FeatureVariable.VariableType.BOOLEAN); + return GetFeatureVariableValueForType(featureKey, variableKey, userId, userAttributes, FeatureVariable.BOOLEAN_TYPE); } /// @@ -633,7 +633,7 @@ public virtual T GetFeatureVariableValueForType(string featureKey, string var /// double | Feature variable value or null public double? GetFeatureVariableDouble(string featureKey, string variableKey, string userId, UserAttributes userAttributes = null) { - return GetFeatureVariableValueForType(featureKey, variableKey, userId, userAttributes, FeatureVariable.VariableType.DOUBLE); + return GetFeatureVariableValueForType(featureKey, variableKey, userId, userAttributes, FeatureVariable.DOUBLE_TYPE); } /// @@ -646,7 +646,7 @@ public virtual T GetFeatureVariableValueForType(string featureKey, string var /// int | Feature variable value or null public int? GetFeatureVariableInteger(string featureKey, string variableKey, string userId, UserAttributes userAttributes = null) { - return GetFeatureVariableValueForType(featureKey, variableKey, userId, userAttributes, FeatureVariable.VariableType.INTEGER); + return GetFeatureVariableValueForType(featureKey, variableKey, userId, userAttributes, FeatureVariable.INTEGER_TYPE); } /// @@ -659,7 +659,7 @@ public virtual T GetFeatureVariableValueForType(string featureKey, string var /// string | Feature variable value or null public string GetFeatureVariableString(string featureKey, string variableKey, string userId, UserAttributes userAttributes = null) { - return GetFeatureVariableValueForType(featureKey, variableKey, userId, userAttributes, FeatureVariable.VariableType.STRING); + return GetFeatureVariableValueForType(featureKey, variableKey, userId, userAttributes, FeatureVariable.STRING_TYPE); } /// @@ -786,24 +786,24 @@ private bool ValidateStringInputs(Dictionary inputs) return isValid; } - private object GetTypeCastedVariableValue(string value, FeatureVariable.VariableType type) + private object GetTypeCastedVariableValue(string value, string type) { object result = null; switch (type) { - case FeatureVariable.VariableType.BOOLEAN: + case FeatureVariable.BOOLEAN_TYPE: bool.TryParse(value, out bool booleanValue); result = booleanValue; break; - case FeatureVariable.VariableType.DOUBLE: + case FeatureVariable.DOUBLE_TYPE: double.TryParse(value, System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, out double doubleValue); result = doubleValue; break; - case FeatureVariable.VariableType.INTEGER: + case FeatureVariable.INTEGER_TYPE: int.TryParse(value, out int intValue); result = intValue; break; - case FeatureVariable.VariableType.STRING: + case FeatureVariable.STRING_TYPE: result = value; break; } From bb69784ba22833022a3d66e1a42cfe795d0fc399 Mon Sep 17 00:00:00 2001 From: Sohail Hussain Date: Tue, 14 Apr 2020 13:39:09 -0700 Subject: [PATCH 2/2] one feature added. --- OptimizelySDK.Tests/ProjectConfigTest.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OptimizelySDK.Tests/ProjectConfigTest.cs b/OptimizelySDK.Tests/ProjectConfigTest.cs index 3b3c98bc..0c9a2ab2 100644 --- a/OptimizelySDK.Tests/ProjectConfigTest.cs +++ b/OptimizelySDK.Tests/ProjectConfigTest.cs @@ -399,7 +399,8 @@ public void TestInit() { "multi_variate_feature", Config.GetFeatureFlagFromKey("multi_variate_feature") }, { "mutex_group_feature", Config.GetFeatureFlagFromKey("mutex_group_feature") }, { "empty_feature", Config.GetFeatureFlagFromKey("empty_feature") }, - { "no_rollout_experiment_feature", Config.GetFeatureFlagFromKey("no_rollout_experiment_feature") } + { "no_rollout_experiment_feature", Config.GetFeatureFlagFromKey("no_rollout_experiment_feature") }, + { "unsupported_variabletype", Config.GetFeatureFlagFromKey("unsupported_variabletype") } }; Assert.IsTrue(TestData.CompareObjects(expectedFeatureKeyMap, Config.FeatureKeyMap));