Esempio n. 1
0
        public void TestGetVariationForFeatureExperimentGivenNonMutexGroupAndUserIsBucketed()
        {
            var experiment       = ProjectConfig.GetExperimentFromKey("test_experiment_multivariate");
            var variation        = ProjectConfig.GetVariationFromId("test_experiment_multivariate", "122231");
            var expectedDecision = new FeatureDecision(experiment, variation, FeatureDecision.DECISION_SOURCE_EXPERIMENT);
            var userAttributes   = new UserAttributes();

            DecisionServiceMock.Setup(ds => ds.GetVariation(ProjectConfig.GetExperimentFromKey("test_experiment_multivariate"),
                                                            "user1", userAttributes)).Returns(variation);

            var featureFlag = ProjectConfig.GetFeatureFlagFromKey("multi_variate_feature");
            var decision    = DecisionServiceMock.Object.GetVariationForFeatureExperiment(featureFlag, "user1", userAttributes);

            Assert.IsTrue(TestData.CompareObjects(expectedDecision, decision));

            LoggerMock.Verify(l => l.Log(LogLevel.INFO, "The user \"user1\" is bucketed into experiment \"test_experiment_multivariate\" of feature \"multi_variate_feature\"."));
        }
Esempio n. 2
0
        public void ImpressionEventTest()
        {
            var projectConfig = Config;
            var experiment    = Config.GetExperimentFromKey("test_experiment");
            var variation     = Config.GetVariationFromId(experiment.Key, "77210100090");
            var userId        = TestUserId;

            var impressionEvent = UserEventFactory.CreateImpressionEvent(projectConfig, experiment, variation, userId, null, "test_experiment", "experiment");

            Assert.AreEqual(Config.ProjectId, impressionEvent.Context.ProjectId);
            Assert.AreEqual(Config.Revision, impressionEvent.Context.Revision);
            Assert.AreEqual(Config.AccountId, impressionEvent.Context.AccountId);
            Assert.AreEqual(Config.AnonymizeIP, impressionEvent.Context.AnonymizeIP);
            Assert.AreEqual(Config.BotFiltering, impressionEvent.BotFiltering);
            Assert.AreEqual(experiment, impressionEvent.Experiment);
            Assert.AreEqual(variation, impressionEvent.Variation);
            Assert.AreEqual(userId, impressionEvent.UserId);
            Assert.AreEqual(Config.BotFiltering, impressionEvent.BotFiltering);
        }
Esempio n. 3
0
        public void TestBucketRolloutRule()
        {
            var bucketer          = new Bucketer(LoggerMock.Object);
            var rollout           = Config.GetRolloutFromId("166660");
            var rolloutRule       = rollout.Experiments[1];
            var expectedVariation = Config.GetVariationFromId(rolloutRule.Key, "177773");

            Assert.True(TestData.CompareObjects(expectedVariation,
                                                bucketer.Bucket(Config, rolloutRule, "testBucketingId", TestUserId)));
        }
        /// <summary>
        /// Create ImpressionEvent instance from ProjectConfig
        /// </summary>
        /// <param name="projectConfig">The ProjectConfig entity</param>
        /// <param name="activatedExperiment">The Experiment entity</param>
        /// <param name="variationId">The variation Id</param>
        /// <param name="userId">The user Id</param>
        /// <param name="userAttributes">The user's attributes</param>
        /// <returns>ImpressionEvent instance</returns>
        public static ImpressionEvent CreateImpressionEvent(ProjectConfig projectConfig,
                                                            Experiment activatedExperiment,
                                                            string variationId,
                                                            string userId,
                                                            UserAttributes userAttributes)
        {
            Variation variation = projectConfig.GetVariationFromId(activatedExperiment?.Key, variationId);

            return(CreateImpressionEvent(projectConfig, activatedExperiment, variation, userId, userAttributes));
        }
Esempio n. 5
0
        /// <summary>
        /// Determine variation the user should be put in.
        /// </summary>
        /// <param name="config">ProjectConfig Configuration for the project</param>
        /// <param name="experiment">Experiment Experiment in which user is to be bucketed</param>
        /// <param name="bucketingId">A customer-assigned value used to create the key for the murmur hash.</param>
        /// <param name="userId">User identifier</param>
        /// <returns>Variation which will be shown to the user</returns>
        public virtual Variation Bucket(ProjectConfig config, Experiment experiment, string bucketingId, string userId)
        {
            string    message;
            Variation variation;

            if (string.IsNullOrEmpty(experiment.Key))
            {
                return(new Variation());
            }

            // Determine if experiment is in a mutually exclusive group.
            if (experiment.IsInMutexGroup)
            {
                Group group = config.GetGroup(experiment.GroupId);
                if (string.IsNullOrEmpty(group.Id))
                {
                    return(new Variation());
                }

                string userExperimentId = FindBucket(bucketingId, userId, group.Id, group.TrafficAllocation);
                if (string.IsNullOrEmpty(userExperimentId))
                {
                    message = string.Format("User [{0}] is in no experiment.", userId);
                    Logger.Log(LogLevel.INFO, message);
                    return(new Variation());
                }

                if (userExperimentId != experiment.Id)
                {
                    message = string.Format("User [{0}] is not in experiment [{1}] of group [{2}].",
                                            userId, experiment.Key, experiment.GroupId);
                    Logger.Log(LogLevel.INFO, message);
                    return(new Variation());
                }

                message = string.Format("User [{0}] is in experiment [{1}] of group [{2}].",
                                        userId, experiment.Key, experiment.GroupId);
                Logger.Log(LogLevel.INFO, message);
            }

            // Bucket user if not in whitelist and in group (if any).
            string variationId = FindBucket(bucketingId, userId, experiment.Id, experiment.TrafficAllocation);

            if (string.IsNullOrEmpty(variationId))
            {
                Logger.Log(LogLevel.INFO, string.Format("User [{0}] is in no variation.", userId));
                return(new Variation());
            }

            // success!
            variation = config.GetVariationFromId(experiment.Key, variationId);
            message   = string.Format("User [{0}] is in variation [{1}] of experiment [{2}].", userId, variation.Key, experiment.Key);
            Logger.Log(LogLevel.INFO, message);
            return(variation);
        }
Esempio n. 6
0
        /// <summary>
        /// Determine variation the user should be put in.
        /// </summary>
        /// <param name="config">ProjectConfig Configuration for the project</param>
        /// <param name="experiment">Experiment Experiment in which user is to be bucketed</param>
        /// <param name="bucketingId">A customer-assigned value used to create the key for the murmur hash.</param>
        /// <param name="userId">User identifier</param>
        /// <returns>Variation which will be shown to the user</returns>
        public virtual Result <Variation> Bucket(ProjectConfig config, Experiment experiment, string bucketingId, string userId)
        {
            string    message;
            Variation variation;

            var reasons = new DecisionReasons();

            if (string.IsNullOrEmpty(experiment.Key))
            {
                return(Result <Variation> .NewResult(new Variation(), reasons));
            }

            // Determine if experiment is in a mutually exclusive group.
            if (experiment.IsInMutexGroup)
            {
                Group group = config.GetGroup(experiment.GroupId);
                if (string.IsNullOrEmpty(group.Id))
                {
                    return(Result <Variation> .NewResult(new Variation(), reasons));
                }

                string userExperimentId = FindBucket(bucketingId, userId, group.Id, group.TrafficAllocation);
                if (string.IsNullOrEmpty(userExperimentId))
                {
                    message = $"User [{userId}] is in no experiment.";
                    Logger.Log(LogLevel.INFO, reasons.AddInfo(message));
                    return(Result <Variation> .NewResult(new Variation(), reasons));
                }

                if (userExperimentId != experiment.Id)
                {
                    message = $"User [{userId}] is not in experiment [{experiment.Key}] of group [{experiment.GroupId}].";
                    Logger.Log(LogLevel.INFO, reasons.AddInfo(message));
                    return(Result <Variation> .NewResult(new Variation(), reasons));
                }

                message = $"User [{userId}] is in experiment [{experiment.Key}] of group [{experiment.GroupId}].";
                Logger.Log(LogLevel.INFO, reasons.AddInfo(message));
            }

            // Bucket user if not in whitelist and in group (if any).
            string variationId = FindBucket(bucketingId, userId, experiment.Id, experiment.TrafficAllocation);

            if (string.IsNullOrEmpty(variationId))
            {
                Logger.Log(LogLevel.INFO, reasons.AddInfo($"User [{userId}] is in no variation."));
                return(Result <Variation> .NewResult(new Variation(), reasons));
            }

            // success!
            variation = config.GetVariationFromId(experiment.Key, variationId);
            message   = $"User [{userId}] is in variation [{variation.Key}] of experiment [{experiment.Key}].";
            Logger.Log(LogLevel.INFO, reasons.AddInfo(message));
            return(Result <Variation> .NewResult(variation, reasons));
        }
Esempio n. 7
0
        /// <summary>
        /// Create ImpressionEvent instance from ProjectConfig
        /// </summary>
        /// <param name="projectConfig">The ProjectConfig entity</param>
        /// <param name="activatedExperiment">The Experiment entity</param>
        /// <param name="variationId">The variation Id</param>
        /// <param name="userId">The user Id</param>
        /// <param name="userAttributes">The user's attributes</param>
        /// <returns>ImpressionEvent instance</returns>
        public static ImpressionEvent CreateImpressionEvent(ProjectConfig projectConfig,
                                                            Experiment activatedExperiment,
                                                            string variationId,
                                                            string userId,
                                                            UserAttributes userAttributes,
                                                            string flagKey,
                                                            string ruleType,
                                                            bool enabled = false)
        {
            Variation variation = projectConfig.GetVariationFromId(activatedExperiment?.Key, variationId);

            return(CreateImpressionEvent(projectConfig, activatedExperiment, variation, userId, userAttributes, flagKey, ruleType, enabled));
        }
Esempio n. 8
0
        /// <summary>
        /// Gets the forced variation for the given user and experiment.
        /// </summary>
        /// <param name="experimentKey">The experiment key</param>
        /// <param name="userId">The user ID</param>
        /// <param name="config">Project Config</param>
        /// <returns>Variation entity which the given user and experiment should be forced into.</returns>
        public Result <Variation> GetForcedVariation(string experimentKey, string userId, ProjectConfig config)
        {
            var reasons = new DecisionReasons();

            if (ForcedVariationMap.ContainsKey(userId) == false)
            {
                Logger.Log(LogLevel.DEBUG, $@"User ""{userId}"" is not in the forced variation map.");
                return(Result <Variation> .NullResult(reasons));
            }

            Dictionary <string, string> experimentToVariationMap = ForcedVariationMap[userId];

            string experimentId = config.GetExperimentFromKey(experimentKey).Id;

            // this case is logged in getExperimentFromKey
            if (string.IsNullOrEmpty(experimentId))
            {
                return(Result <Variation> .NullResult(reasons));
            }

            if (experimentToVariationMap.ContainsKey(experimentId) == false)
            {
                Logger.Log(LogLevel.DEBUG, $@"No experiment ""{experimentKey}"" mapped to user ""{userId}"" in the forced variation map.");
                return(Result <Variation> .NullResult(reasons));
            }

            string variationId = experimentToVariationMap[experimentId];

            if (string.IsNullOrEmpty(variationId))
            {
                Logger.Log(LogLevel.DEBUG, $@"No variation mapped to experiment ""{experimentKey}"" in the forced variation map.");
                return(Result <Variation> .NullResult(reasons));
            }

            string variationKey = config.GetVariationFromId(experimentKey, variationId).Key;

            // this case is logged in getVariationFromKey
            if (string.IsNullOrEmpty(variationKey))
            {
                return(Result <Variation> .NullResult(reasons));
            }
            Logger.Log(LogLevel.DEBUG, reasons.AddInfo($@"Variation ""{variationKey}"" is mapped to experiment ""{experimentKey}"" and user ""{userId}"" in the forced variation map"));

            Variation variation = config.GetVariationFromKey(experimentKey, variationKey);

            return(Result <Variation> .NewResult(variation, reasons));
        }
Esempio n. 9
0
        public void TestBucketRolloutRule()
        {
            var bucketer          = new Bucketer(LoggerMock.Object);
            var rollout           = Config.GetRolloutFromId("166660");
            var rolloutRule       = rollout.Experiments[1];
            var expectedVariation = Config.GetVariationFromId(rolloutRule.Key, "177773");

            var variationResult = bucketer.Bucket(Config, rolloutRule, "testBucketingId", TestUserId);

            Assert.True(TestData.CompareObjects(expectedVariation,
                                                variationResult.ResultObject));
            Assert.AreEqual(variationResult.DecisionReasons.ToReport().Count, 0);
            var variationsResult = bucketer.Bucket(Config, rolloutRule, "testBucketingId", TestUserId);

            Assert.True(TestData.CompareObjects(expectedVariation,
                                                variationsResult.ResultObject));
            Assert.AreEqual(variationsResult.DecisionReasons.ToReport(true).Count, 1);
            Assert.AreEqual(variationsResult.DecisionReasons.ToReport(true)[0], "User [testUserId] is in variation [177773] of experiment [177772].");
        }
Esempio n. 10
0
        public void TestInit()
        {
            // Check Version
            Assert.AreEqual("4", Config.Version);

            // Check Account ID
            Assert.AreEqual("1592310167", Config.AccountId);
            // Check Project ID
            Assert.AreEqual("7720880029", Config.ProjectId);
            // Check Revision
            Assert.AreEqual("15", Config.Revision);

            // Check Group ID Map
            var expectedGroupId = CreateDictionary("7722400015", Config.GetGroup("7722400015"));

            var actual = Config.GroupIdMap;

            Assert.IsTrue(TestData.CompareObjects(expectedGroupId, actual));

            // Check Experiment Key Map
            var experimentKeyMap = new Dictionary <string, object>()
            {
                { "test_experiment", Config.GetExperimentFromKey("test_experiment") },
                { "paused_experiment", Config.GetExperimentFromKey("paused_experiment") },
                { "test_experiment_multivariate", Config.GetExperimentFromKey("test_experiment_multivariate") },
                { "test_experiment_with_feature_rollout", Config.GetExperimentFromKey("test_experiment_with_feature_rollout") },
                { "test_experiment_double_feature", Config.GetExperimentFromKey("test_experiment_double_feature") },
                { "test_experiment_integer_feature", Config.GetExperimentFromKey("test_experiment_integer_feature") },
                { "group_experiment_1", Config.GetExperimentFromKey("group_experiment_1") },
                { "group_experiment_2", Config.GetExperimentFromKey("group_experiment_2") },
                { "etag1", Config.GetExperimentFromKey("etag1") },
                { "etag2", Config.GetExperimentFromKey("etag2") },
                { "etag3", Config.GetExperimentFromKey("etag3") },
                { "etag4", Config.GetExperimentFromKey("etag4") }
            };

            Assert.IsTrue(TestData.CompareObjects(experimentKeyMap, Config.ExperimentKeyMap));

            // Check Experiment ID Map

            var experimentIdMap = new Dictionary <string, object>()
            {
                { "7716830082", Config.GetExperimentFromId("7716830082") },
                { "7716830585", Config.GetExperimentFromId("7716830585") },
                { "122230", Config.GetExperimentFromId("122230") },
                { "122235", Config.GetExperimentFromId("122235") },
                { "122238", Config.GetExperimentFromId("122238") },
                { "122241", Config.GetExperimentFromId("122241") },
                { "7723330021", Config.GetExperimentFromId("7723330021") },
                { "7718750065", Config.GetExperimentFromId("7718750065") },
                { "223", Config.GetExperimentFromId("223") },
                { "118", Config.GetExperimentFromId("118") },
                { "224", Config.GetExperimentFromId("224") },
                { "119", Config.GetExperimentFromId("119") }
            };

            Assert.IsTrue(TestData.CompareObjects(experimentIdMap, Config.ExperimentIdMap));

            // Check Event key Map
            var eventKeyMap = new Dictionary <string, object> {
                { "purchase", Config.GetEvent("purchase") }
            };

            Assert.IsTrue(TestData.CompareObjects(eventKeyMap, Config.EventKeyMap));

            // Check Attribute Key Map
            var attributeKeyMap = new Dictionary <string, object>
            {
                { "device_type", Config.GetAttribute("device_type") },
                { "location", Config.GetAttribute("location") },
                { "browser_type", Config.GetAttribute("browser_type") },
                { "boolean_key", Config.GetAttribute("boolean_key") },
                { "integer_key", Config.GetAttribute("integer_key") },
                { "double_key", Config.GetAttribute("double_key") }
            };

            Assert.IsTrue(TestData.CompareObjects(attributeKeyMap, Config.AttributeKeyMap));

            // Check Audience ID Map
            var audienceIdMap = new Dictionary <string, object>
            {
                { "7718080042", Config.GetAudience("7718080042") },
                { "11154", Config.GetAudience("11154") },
                { "100", Config.GetAudience("100") }
            };

            Assert.IsTrue(TestData.CompareObjects(audienceIdMap, Config.AudienceIdMap));

            // Check Variation Key Map
            var expectedVariationKeyMap = new Dictionary <string, object>
            {
                { "test_experiment", new Dictionary <string, object>
                  {
                      { "control", Config.GetVariationFromKey("test_experiment", "control") },
                      { "variation", Config.GetVariationFromKey("test_experiment", "variation") }
                  } },
                { "paused_experiment", new Dictionary <string, object>
                  {
                      { "control", Config.GetVariationFromKey("paused_experiment", "control") },
                      { "variation", Config.GetVariationFromKey("paused_experiment", "variation") }
                  } },
                { "group_experiment_1", new Dictionary <string, object>
                  {
                      { "group_exp_1_var_1", Config.GetVariationFromKey("group_experiment_1", "group_exp_1_var_1") },
                      { "group_exp_1_var_2", Config.GetVariationFromKey("group_experiment_1", "group_exp_1_var_2") }
                  } },
                { "group_experiment_2", new Dictionary <string, object>
                  {
                      { "group_exp_2_var_1", Config.GetVariationFromKey("group_experiment_2", "group_exp_2_var_1") },
                      { "group_exp_2_var_2", Config.GetVariationFromKey("group_experiment_2", "group_exp_2_var_2") }
                  } },
                { "test_experiment_multivariate", new Dictionary <string, object>
                  {
                      { "Fred", Config.GetVariationFromKey("test_experiment_multivariate", "Fred") },
                      { "Feorge", Config.GetVariationFromKey("test_experiment_multivariate", "Feorge") },
                      { "Gred", Config.GetVariationFromKey("test_experiment_multivariate", "Gred") },
                      { "George", Config.GetVariationFromKey("test_experiment_multivariate", "George") }
                  } },
                { "test_experiment_with_feature_rollout", new Dictionary <string, object>
                  {
                      { "control", Config.GetVariationFromKey("test_experiment_with_feature_rollout", "control") },
                      { "variation", Config.GetVariationFromKey("test_experiment_with_feature_rollout", "variation") }
                  } },
                { "test_experiment_double_feature", new Dictionary <string, object>
                  {
                      { "control", Config.GetVariationFromKey("test_experiment_double_feature", "control") },
                      { "variation", Config.GetVariationFromKey("test_experiment_double_feature", "variation") }
                  } },
                { "test_experiment_integer_feature", new Dictionary <string, object>
                  {
                      { "control", Config.GetVariationFromKey("test_experiment_integer_feature", "control") },
                      { "variation", Config.GetVariationFromKey("test_experiment_integer_feature", "variation") }
                  } },
                { "177770", new Dictionary <string, object>
                  {
                      { "177771", Config.GetVariationFromKey("177770", "177771") }
                  } },
                { "177772", new Dictionary <string, object>
                  {
                      { "177773", Config.GetVariationFromKey("177772", "177773") }
                  } },
                { "177776", new Dictionary <string, object>
                  {
                      { "177778", Config.GetVariationFromKey("177776", "177778") }
                  } },
                { "177774", new Dictionary <string, object>
                  {
                      { "177775", Config.GetVariationFromKey("177774", "177775") }
                  } },
                { "177779", new Dictionary <string, object>
                  {
                      { "177780", Config.GetVariationFromKey("177779", "177780") }
                  } },
                { "177781", new Dictionary <string, object>
                  {
                      { "177782", Config.GetVariationFromKey("177781", "177782") }
                  } },
                { "177783", new Dictionary <string, object>
                  {
                      { "177784", Config.GetVariationFromKey("177783", "177784") }
                  } },
                { "188880", new Dictionary <string, object>
                  {
                      { "188881", Config.GetVariationFromKey("188880", "188881") }
                  } },
                { "etag1", new Dictionary <string, object>
                  {
                      { "vtag1", Config.GetVariationFromKey("etag1", "vtag1") },
                      { "vtag2", Config.GetVariationFromKey("etag1", "vtag2") }
                  } },
                { "etag2", new Dictionary <string, object>
                  {
                      { "vtag3", Config.GetVariationFromKey("etag2", "vtag3") },
                      { "vtag4", Config.GetVariationFromKey("etag2", "vtag4") }
                  } },
                { "etag3", new Dictionary <string, object>
                  {
                      { "vtag5", Config.GetVariationFromKey("etag3", "vtag5") },
                      { "vtag6", Config.GetVariationFromKey("etag3", "vtag6") }
                  } },
                { "etag4", new Dictionary <string, object>
                  {
                      { "vtag7", Config.GetVariationFromKey("etag4", "vtag7") },
                      { "vtag8", Config.GetVariationFromKey("etag4", "vtag8") }
                  } }
            };

            Assert.IsTrue(TestData.CompareObjects(expectedVariationKeyMap, Config.VariationKeyMap));

            // Check Variation ID Map
            var expectedVariationIdMap = new Dictionary <string, object>
            {
                { "test_experiment", new Dictionary <string, object>
                  {
                      { "7722370027", Config.GetVariationFromId("test_experiment", "7722370027") },
                      { "7721010009", Config.GetVariationFromId("test_experiment", "7721010009") }
                  } },
                { "paused_experiment", new Dictionary <string, object>
                  {
                      { "7722370427", Config.GetVariationFromId("paused_experiment", "7722370427") },
                      { "7721010509", Config.GetVariationFromId("paused_experiment", "7721010509") }
                  } },
                { "test_experiment_multivariate", new Dictionary <string, object>
                  {
                      { "122231", Config.GetVariationFromId("test_experiment_multivariate", "122231") },
                      { "122232", Config.GetVariationFromId("test_experiment_multivariate", "122232") },
                      { "122233", Config.GetVariationFromId("test_experiment_multivariate", "122233") },
                      { "122234", Config.GetVariationFromId("test_experiment_multivariate", "122234") }
                  } },
                { "test_experiment_with_feature_rollout", new Dictionary <string, object>
                  {
                      { "122236", Config.GetVariationFromId("test_experiment_with_feature_rollout", "122236") },
                      { "122237", Config.GetVariationFromId("test_experiment_with_feature_rollout", "122237") }
                  } },
                { "test_experiment_double_feature", new Dictionary <string, object>
                  {
                      { "122239", Config.GetVariationFromId("test_experiment_double_feature", "122239") },
                      { "122240", Config.GetVariationFromId("test_experiment_double_feature", "122240") }
                  } },
                { "test_experiment_integer_feature", new Dictionary <string, object>
                  {
                      { "122242", Config.GetVariationFromId("test_experiment_integer_feature", "122242") },
                      { "122243", Config.GetVariationFromId("test_experiment_integer_feature", "122243") }
                  } },
                { "group_experiment_1", new Dictionary <string, object>
                  {
                      { "7722260071", Config.GetVariationFromId("group_experiment_1", "7722260071") },
                      { "7722360022", Config.GetVariationFromId("group_experiment_1", "7722360022") }
                  } },
                { "group_experiment_2", new Dictionary <string, object>
                  {
                      { "7713030086", Config.GetVariationFromId("group_experiment_2", "7713030086") },
                      { "7725250007", Config.GetVariationFromId("group_experiment_2", "7725250007") }
                  } },
                { "177770", new Dictionary <string, object>
                  {
                      { "177771", Config.GetVariationFromId("177770", "177771") }
                  } },
                { "177772", new Dictionary <string, object>
                  {
                      { "177773", Config.GetVariationFromId("177772", "177773") }
                  } },
                { "177776", new Dictionary <string, object>
                  {
                      { "177778", Config.GetVariationFromId("177776", "177778") }
                  } },
                { "177774", new Dictionary <string, object>
                  {
                      { "177775", Config.GetVariationFromId("177774", "177775") }
                  } },
                { "177779", new Dictionary <string, object>
                  {
                      { "177780", Config.GetVariationFromId("177779", "177780") }
                  } },
                { "177781", new Dictionary <string, object>
                  {
                      { "177782", Config.GetVariationFromId("177781", "177782") }
                  } },
                { "177783", new Dictionary <string, object>
                  {
                      { "177784", Config.GetVariationFromId("177783", "177784") }
                  } },
                { "188880", new Dictionary <string, object>
                  {
                      { "188881", Config.GetVariationFromId("188880", "188881") }
                  } },
                { "etag1", new Dictionary <string, object>
                  {
                      { "276", Config.GetVariationFromId("etag1", "276") },
                      { "277", Config.GetVariationFromId("etag1", "277") }
                  } },
                { "etag2", new Dictionary <string, object>
                  {
                      { "278", Config.GetVariationFromId("etag2", "278") },
                      { "279", Config.GetVariationFromId("etag2", "279") }
                  } },
                { "etag3", new Dictionary <string, object>
                  {
                      { "280", Config.GetVariationFromId("etag3", "280") },
                      { "281", Config.GetVariationFromId("etag3", "281") }
                  } },
                { "etag4", new Dictionary <string, object>
                  {
                      { "282", Config.GetVariationFromId("etag4", "282") },
                      { "283", Config.GetVariationFromId("etag4", "283") }
                  } }
            };

            Assert.IsTrue(TestData.CompareObjects(expectedVariationIdMap, Config.VariationIdMap));

            // Check Variation returns correct variable usage
            var featureVariableUsageInstance = new List <FeatureVariableUsage>
            {
                new FeatureVariableUsage {
                    Id = "155560", Value = "F"
                },
                new FeatureVariableUsage {
                    Id = "155561", Value = "red"
                },
            };

            var expectedVariationUsage = new Variation {
                Id = "122231", Key = "Fred", FeatureVariableUsageInstances = featureVariableUsageInstance, FeatureEnabled = true
            };
            var actualVariationUsage = Config.GetVariationFromKey("test_experiment_multivariate", "Fred");

            Assert.IsTrue(TestData.CompareObjects(expectedVariationUsage, actualVariationUsage));

            // Check Feature Key map.
            var expectedFeatureKeyMap = new Dictionary <string, FeatureFlag>
            {
                { "boolean_feature", Config.GetFeatureFlagFromKey("boolean_feature") },
                { "double_single_variable_feature", Config.GetFeatureFlagFromKey("double_single_variable_feature") },
                { "integer_single_variable_feature", Config.GetFeatureFlagFromKey("integer_single_variable_feature") },
                { "boolean_single_variable_feature", Config.GetFeatureFlagFromKey("boolean_single_variable_feature") },
                { "string_single_variable_feature", Config.GetFeatureFlagFromKey("string_single_variable_feature") },
                { "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") }
            };

            Assert.IsTrue(TestData.CompareObjects(expectedFeatureKeyMap, Config.FeatureKeyMap));

            // Check Feature Key map.
            var expectedRolloutIdMap = new Dictionary <string, Rollout>
            {
                { "166660", Config.GetRolloutFromId("166660") },
                { "166661", Config.GetRolloutFromId("166661") }
            };

            Assert.IsTrue(TestData.CompareObjects(expectedRolloutIdMap, Config.RolloutIdMap));
        }