public void Setup() { Config = DatafileProjectConfig.Create(TestData.TypedAudienceDatafile, null, null); LoggerMock = new Mock <ILogger>(); LoggerMock.Setup(l => l.Log(It.IsAny <LogLevel>(), It.IsAny <string>())); Logger = LoggerMock.Object; }
public void Setup() { Logger = new DefaultLogger(); ErrorHandler = new DefaultErrorHandler(); Config = DatafileProjectConfig.Create(TestData.Datafile, Logger, ErrorHandler); }
public void TestIsFeatureExperimentReturnsFalseForExperimentThatDoesNotBelongToAnyFeature() { var typedConfig = DatafileProjectConfig.Create(TestData.TypedAudienceDatafile, null, null); var experiment = typedConfig.GetExperimentFromKey("typed_audience_experiment"); Assert.False(typedConfig.IsFeatureExperiment(experiment.Id)); }
public void TempProjectConfigTest() { ProjectConfig config = DatafileProjectConfig.Create(TestData.Datafile, new Mock <ILogger>().Object, new DefaultErrorHandler()); Assert.IsNotNull(config); Assert.AreEqual("1592310167", config.AccountId); }
public void TestGetAttributeIdWithReservedPrefix() { // Verify that attribute key is returned for reserved attribute key. Assert.AreEqual(Config.GetAttributeId(ControlAttributes.USER_AGENT_ATTRIBUTE), ControlAttributes.USER_AGENT_ATTRIBUTE); // Verify that attribute Id is returned for attribute key with reserved prefix that does not exist in datafile. Assert.AreEqual(Config.GetAttributeId("$opt_reserved_prefix_attribute"), "$opt_reserved_prefix_attribute"); // Create config file copy with additional resered prefix attribute. string reservedPrefixAttrKey = "$opt_user_defined_attribute"; JObject projConfig = JObject.Parse(TestData.Datafile); var attributes = (JArray)projConfig["attributes"]; var reservedAttr = new Entity.Attribute { Id = "7723348204", Key = reservedPrefixAttrKey }; attributes.Add((JObject)JToken.FromObject(reservedAttr)); // Verify that attribute Id is returned and warning is logged for attribute key with reserved prefix that exists in datafile. var reservedAttrConfig = DatafileProjectConfig.Create(JsonConvert.SerializeObject(projConfig), LoggerMock.Object, ErrorHandlerMock.Object); Assert.AreEqual(reservedAttrConfig.GetAttributeId(reservedPrefixAttrKey), reservedAttrConfig.GetAttribute(reservedPrefixAttrKey).Id); LoggerMock.Verify(l => l.Log(LogLevel.WARN, $@"Attribute {reservedPrefixAttrKey} unexpectedly has reserved prefix {DatafileProjectConfig.RESERVED_ATTRIBUTE_PREFIX}; using attribute ID instead of reserved attribute name.")); }
public void TestIsFeatureExperimentReturnsTrueForExperimentThatBelongsToAFeature() { var typedConfig = DatafileProjectConfig.Create(TestData.TypedAudienceDatafile, null, null); var experiment = typedConfig.GetExperimentFromKey("feat2_with_var_test"); Assert.True(typedConfig.IsFeatureExperiment(experiment.Id)); }
public void TestWaitUntilValidDatfileIsNotGiven() { // Send invalid datafile. // Wait for one more poll // Send invalid datafile. // wait for one more poll // then send the right datafile // see it should release blocking. // blocking timeout must be inifinity. var projConfig = DatafileProjectConfig.Create(TestData.Datafile, LoggerMock.Object, null); var data = new List <TestPollingData>() { new TestPollingData { PollingTime = 50, ChangeVersion = false, ConfigDatafile = null }, new TestPollingData { PollingTime = 50, ChangeVersion = false, ConfigDatafile = null }, new TestPollingData { PollingTime = 50, ChangeVersion = false, ConfigDatafile = projConfig } }; var configManager = new TestPollingProjectConfigManager(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(10000), true, LoggerMock.Object, data.ToArray()); configManager.Start(); // after 3rd attempt should get var config = configManager.GetConfig(); //Assert.NotNull(config); Assert.AreEqual(3, configManager.Counter); configManager.Dispose(); }
public void Setup() { LoggerMock = new Mock <ILogger>(); ErrorHandlerMock = new Mock <IErrorHandler>(); Config = DatafileProjectConfig.Create(TestData.Datafile, LoggerMock.Object, ErrorHandlerMock.Object); }
/// <summary> /// Optimizely constructor for managing Full Stack .NET projects. /// </summary> /// <param name="datafile">string JSON string representing the project</param> /// <param name="eventDispatcher">EventDispatcherInterface</param> /// <param name="logger">LoggerInterface</param> /// <param name="errorHandler">ErrorHandlerInterface</param> /// <param name="skipJsonValidation">boolean representing whether JSON schema validation needs to be performed</param> /// <param name="eventProcessor">EventProcessor</param> public Optimizely(string datafile, IEventDispatcher eventDispatcher = null, ILogger logger = null, IErrorHandler errorHandler = null, UserProfileService userProfileService = null, bool skipJsonValidation = false, EventProcessor eventProcessor = null) { try { InitializeComponents(eventDispatcher, logger, errorHandler, userProfileService, null, eventProcessor); if (ValidateInputs(datafile, skipJsonValidation)) { var config = DatafileProjectConfig.Create(datafile, Logger, ErrorHandler); ProjectConfigManager = new FallbackProjectConfigManager(config); } else { Logger.Log(LogLevel.ERROR, "Provided 'datafile' has invalid schema."); } } catch (Exception ex) { string error = String.Empty; if (ex.GetType() == typeof(ConfigParseException)) { error = ex.Message; } else { error = "Provided 'datafile' is in an invalid format. " + ex.Message; } Logger.Log(LogLevel.ERROR, error); ErrorHandler.HandleError(ex); } }
public void TestDecideOptionsByPassUPS() { var userProfileServiceMock = new Mock <UserProfileService>(); var flagKey = "string_single_variable_feature"; var experimentId = "122235"; var userId = "testUser3"; var variationKey = "control"; var fbVariationId = "122237"; var fbVariationKey = "variation"; var userProfile = new UserProfile(userId, new Dictionary <string, Decision> { { experimentId, new Decision(fbVariationId) } }); userProfileServiceMock.Setup(_ => _.Lookup(userId)).Returns(userProfile.ToMap()); var optimizely = new Optimizely(TestData.Datafile, EventDispatcherMock.Object, LoggerMock.Object, ErrorHandlerMock.Object, userProfileServiceMock.Object); var user = optimizely.CreateUserContext(userId); var projectConfig = DatafileProjectConfig.Create(TestData.Datafile, LoggerMock.Object, ErrorHandlerMock.Object); var variationUserProfile = user.Decide(flagKey); Assert.AreEqual(fbVariationKey, variationUserProfile.VariationKey); var decideOptions = new OptimizelyDecideOption[] { OptimizelyDecideOption.IGNORE_USER_PROFILE_SERVICE }; variationUserProfile = user.Decide(flagKey, decideOptions); Assert.AreEqual(variationKey, variationUserProfile.VariationKey); }
public void TestStaticProjectConfigManagerReturnsCorrectProjectConfig() { var expectedConfig = DatafileProjectConfig.Create(TestData.TypedAudienceDatafile, null, null); ConfigManager = new FallbackProjectConfigManager(expectedConfig); Assert.True(TestData.CompareObjects(expectedConfig, ConfigManager.GetConfig())); }
public void Setup() { LoggerMock = new Mock <ILogger>(); ErrorHandlerMock = new Mock <IErrorHandler>(); ErrorHandlerMock.Setup(e => e.HandleError(It.IsAny <Exception>())); Config = DatafileProjectConfig.Create(TestData.Datafile, LoggerMock.Object, ErrorHandlerMock.Object); }
public void TestGetOptimizelyConfigSDKAndEnvironmentKeyDefault() { var datafileProjectConfig = DatafileProjectConfig.Create(TestData.DuplicateRuleKeysDatafile, new NoOpLogger(), new ErrorHandler.NoOpErrorHandler()); var optimizelyConfigService = new OptimizelyConfigService(datafileProjectConfig); var optimizelyConfig = optimizelyConfigService.GetOptimizelyConfig(); Assert.AreEqual(optimizelyConfig.SDKKey, ""); Assert.AreEqual(optimizelyConfig.EnvironmentKey, ""); }
public void TestExperimentAudiencesRetrivedFromTypedAudiencesFirstThenFromAudiences() { var typedConfig = DatafileProjectConfig.Create(TestData.TypedAudienceDatafile, null, null); var experiment = typedConfig.GetExperimentFromKey("feat_with_var_test"); var expectedAudienceIds = new string[] { "3468206642", "3988293898", "3988293899", "3468206646", "3468206647", "3468206644", "3468206643" }; Assert.That(expectedAudienceIds, Is.EquivalentTo(experiment.AudienceIds)); }
protected override ProjectConfig Poll() { var datafile = GetRemoteDatafileResponse(); if (datafile == null) { return(null); } return(DatafileProjectConfig.Create(datafile, Logger, ErrorHandler)); }
public void TestGetOptimizelyConfigWithDuplicateExperimentKeys() { var datafileProjectConfig = DatafileProjectConfig.Create(TestData.DuplicateExpKeysDatafile, new NoOpLogger(), new ErrorHandler.NoOpErrorHandler()); var optimizelyConfigService = new OptimizelyConfigService(datafileProjectConfig); var optimizelyConfig = optimizelyConfigService.GetOptimizelyConfig(); Assert.AreEqual(optimizelyConfig.ExperimentsMap.Count, 1); var experimentMapFlag1 = optimizelyConfig.FeaturesMap["flag1"].ExperimentsMap; //9300000007569 var experimentMapFlag2 = optimizelyConfig.FeaturesMap["flag2"].ExperimentsMap; // 9300000007573 Assert.AreEqual(experimentMapFlag1["targeted_delivery"].Id, "9300000007569"); Assert.AreEqual(experimentMapFlag2["targeted_delivery"].Id, "9300000007573"); }
public void Setup() { LoggerMock = new Mock <ILogger>(); LoggerMock.Setup(l => l.Log(It.IsAny <LogLevel>(), It.IsAny <string>())); ErrorHandlerMock = new Mock <IErrorHandler>(); ErrorHandlerMock.Setup(e => e.HandleError(It.IsAny <Exception>())); ProjectConfig = DatafileProjectConfig.Create(TestData.Datafile, LoggerMock.Object, new NoOpErrorHandler()); EventDispatcher = new TestForwardingEventDispatcher { IsUpdated = false }; EventProcessor = new ForwardingEventProcessor(EventDispatcher, NotificationCenter, LoggerMock.Object, ErrorHandlerMock.Object); }
public void Setup() { LoggerMock = new Mock <ILogger>(); LoggerMock.Setup(l => l.Log(It.IsAny <LogLevel>(), It.IsAny <string>())); Config = DatafileProjectConfig.Create(TestData.Datafile, LoggerMock.Object, new ErrorHandler.NoOpErrorHandler()); eventQueue = new BlockingCollection <object>(100); EventDispatcherMock = new Mock <IEventDispatcher>(); NotificationCallbackMock = new Mock <TestNotificationCallbacks>(); NotificationCallbackMock.Setup(nc => nc.TestLogEventCallback(It.IsAny <LogEvent>())); NotificationCenter.AddNotification(NotificationCenter.NotificationType.LogEvent, NotificationCallbackMock.Object.TestLogEventCallback); }
public void TestBotFilteringValues() { // Verify that bot filtering value is true as defined in Config data. Assert.True(Config.BotFiltering.GetValueOrDefault()); // Remove botFilering node and verify returned value in null. JObject projConfig = JObject.Parse(TestData.Datafile); if (projConfig.TryGetValue("botFiltering", out JToken token)) { projConfig.Property("botFiltering").Remove(); var configWithoutBotFilter = DatafileProjectConfig.Create(JsonConvert.SerializeObject(projConfig), LoggerMock.Object, ErrorHandlerMock.Object); // Verify that bot filtering is null when not defined in datafile. Assert.Null(configWithoutBotFilter.BotFiltering); } }
public void TestGetOptimizelyConfigWithDuplicateRuleKeys() { var datafileProjectConfig = DatafileProjectConfig.Create(TestData.DuplicateRuleKeysDatafile, new NoOpLogger(), new ErrorHandler.NoOpErrorHandler()); var optimizelyConfigService = new OptimizelyConfigService(datafileProjectConfig); var optimizelyConfig = optimizelyConfigService.GetOptimizelyConfig(); Assert.AreEqual(optimizelyConfig.ExperimentsMap.Count, 0); var rolloutFlag1 = optimizelyConfig.FeaturesMap["flag_1"].DeliveryRules[0]; // 9300000004977, var rolloutFlag2 = optimizelyConfig.FeaturesMap["flag_2"].DeliveryRules[0]; // 9300000004979 var rolloutFlag3 = optimizelyConfig.FeaturesMap["flag_3"].DeliveryRules[0]; // 9300000004981 Assert.AreEqual(rolloutFlag1.Id, "9300000004977"); Assert.AreEqual(rolloutFlag1.Key, "targeted_delivery"); Assert.AreEqual(rolloutFlag2.Id, "9300000004979"); Assert.AreEqual(rolloutFlag2.Key, "targeted_delivery"); Assert.AreEqual(rolloutFlag3.Id, "9300000004981"); Assert.AreEqual(rolloutFlag3.Key, "targeted_delivery"); }
public void TestReturnDatafileImmediatelyOnceGetValidDatafileRemotely() { var projConfig = DatafileProjectConfig.Create(TestData.Datafile, LoggerMock.Object, null); var data = new List <TestPollingData>() { new TestPollingData { PollingTime = 500, ChangeVersion = false, ConfigDatafile = projConfig }, new TestPollingData { PollingTime = 500, ChangeVersion = false, ConfigDatafile = projConfig } }; var configManager = new TestPollingProjectConfigManager(TimeSpan.FromSeconds(3), TimeSpan.FromMilliseconds(5000), true, LoggerMock.Object, data.ToArray()); var config = configManager.GetConfig(); Assert.NotNull(config); Assert.AreEqual(1, configManager.Counter); configManager.Dispose(); }
public void Setup() { LoggerMock = new Mock <ILogger>(); LoggerMock.Setup(l => l.Log(It.IsAny <LogLevel>(), It.IsAny <string>())); ProjectConfig = DatafileProjectConfig.Create(TestData.Datafile, LoggerMock.Object, null); }
/// <summary> /// HttpProjectConfigManager.Builder that builds and starts a HttpProjectConfigManager. /// </summary> /// <param name="defer">When true, we will not wait for the configuration to be available /// before returning the HttpProjectConfigManager instance.</param> /// <returns>HttpProjectConfigManager instance</returns> public ExperimentationProjectConfigManager Build(bool defer) { ExperimentationProjectConfigManager configManager = null; if (Logger == null) { Logger = new DefaultLogger(); } if (ErrorHandler == null) { ErrorHandler = new DefaultErrorHandler(); } if (string.IsNullOrEmpty(Format)) { if (string.IsNullOrEmpty(DatafileAccessToken)) { Format = DEFAULT_FORMAT; } else { Format = DEFAULT_AUTHENTICATED_DATAFILE_FORMAT; } } if (string.IsNullOrEmpty(Url)) { if (string.IsNullOrEmpty(SdkKey)) { ErrorHandler.HandleError(new Exception("SdkKey cannot be null")); } Url = string.Format(Format, SdkKey); } if (IsPollingIntervalProvided && (Period.TotalMilliseconds <= 0 || Period.TotalMilliseconds > MAX_MILLISECONDS_LIMIT)) { Logger.Log(LogLevel.DEBUG, $"Polling interval is not valid for periodic calls, using default period {DEFAULT_PERIOD.TotalMilliseconds}ms"); Period = DEFAULT_PERIOD; } else if (!IsPollingIntervalProvided) { Logger.Log(LogLevel.DEBUG, $"No polling interval provided, using default period {DEFAULT_PERIOD.TotalMilliseconds}ms"); Period = DEFAULT_PERIOD; } if (IsBlockingTimeoutProvided && (BlockingTimeoutSpan.TotalMilliseconds <= 0 || BlockingTimeoutSpan.TotalMilliseconds > MAX_MILLISECONDS_LIMIT)) { Logger.Log(LogLevel.DEBUG, $"Blocking timeout is not valid, using default blocking timeout {DEFAULT_BLOCKINGOUT_PERIOD.TotalMilliseconds}ms"); BlockingTimeoutSpan = DEFAULT_BLOCKINGOUT_PERIOD; } else if (!IsBlockingTimeoutProvided) { Logger.Log(LogLevel.DEBUG, $"No Blocking timeout provided, using default blocking timeout {DEFAULT_BLOCKINGOUT_PERIOD.TotalMilliseconds}ms"); BlockingTimeoutSpan = DEFAULT_BLOCKINGOUT_PERIOD; } configManager = new ExperimentationProjectConfigManager(Period, Url, BlockingTimeoutSpan, AutoUpdate, Logger, ErrorHandler, DatafileAccessToken); if (Datafile != null) { try { var config = DatafileProjectConfig.Create(Datafile, Logger, ErrorHandler); configManager.SetConfig(config); } catch (Exception ex) { Logger.Log(LogLevel.WARN, "Error parsing fallback datafile." + ex.Message); } } configManager.NotifyOnProjectConfigUpdate += () => { NotificationCenter?.SendNotifications(NotificationCenter.NotificationType.OptimizelyConfigUpdate); }; if (StartByDefault) { configManager.Start(); } // Optionally block until config is available. if (!defer) { configManager.GetConfig(); } return(configManager); }
public void TestIfSendFlagDecisionKeyIsMissingItShouldReturnFalse() { var tempConfig = DatafileProjectConfig.Create(TestData.SimpleABExperimentsDatafile, LoggerMock.Object, ErrorHandlerMock.Object); Assert.IsFalse(tempConfig.SendFlagDecisions); }
public void TestCreateThrowsWithUnsupportedDatafileVersion() { var exception = Assert.Throws <ConfigParseException>(() => DatafileProjectConfig.Create(TestData.UnsupportedVersionDatafile, null, null)); Assert.AreEqual($"This version of the C# SDK does not support the given datafile version: 5", exception.Message); }
public void TestCreateThrowsWithEmptyDatafile() { var exception = Assert.Throws <ConfigParseException>(() => DatafileProjectConfig.Create("", null, null)); Assert.AreEqual("Unable to parse empty datafile.", exception.Message); }
public void TestSendNotifications() { var config = DatafileProjectConfig.Create(TestData.Datafile, LoggerMock.Object, new NoOpErrorHandler()); var logEventMocker = new Mock <LogEvent>("http://mockedurl", new Dictionary <string, object>(), "POST", new Dictionary <string, string>()); // Mocking notification callbacks. var notificationCallbackMock = new Mock <TestNotificationCallbacks>(); notificationCallbackMock.Setup(nc => nc.TestActivateCallback(It.IsAny <Experiment>(), It.IsAny <string>(), It.IsAny <UserAttributes>(), It.IsAny <Variation>(), It.IsAny <LogEvent>())); notificationCallbackMock.Setup(nc => nc.TestAnotherActivateCallback(It.IsAny <Experiment>(), It.IsAny <string>(), It.IsAny <UserAttributes>(), It.IsAny <Variation>(), It.IsAny <LogEvent>())); notificationCallbackMock.Setup(nc => nc.TestLogEventCallback(It.IsAny <LogEvent>())); // Adding decision notifications. NotificationCenter.AddNotification(NotificationTypeActivate, notificationCallbackMock.Object.TestActivateCallback); NotificationCenter.AddNotification(NotificationTypeActivate, notificationCallbackMock.Object.TestAnotherActivateCallback); // Adding track notifications. NotificationCenter.AddNotification(NotificationTypeTrack, notificationCallbackMock.Object.TestTrackCallback); // Fire decision type notifications. NotificationCenter.SendNotifications(NotificationTypeActivate, config.GetExperimentFromKey("test_experiment"), "testUser", new UserAttributes(), config.GetVariationFromId("test_experiment", "7722370027"), logEventMocker.Object); // Verify that only the registered notifications of decision type are called. notificationCallbackMock.Verify(nc => nc.TestActivateCallback(It.IsAny <Experiment>(), It.IsAny <string>(), It.IsAny <UserAttributes>(), It.IsAny <Variation>(), It.IsAny <LogEvent>()), Times.Once); notificationCallbackMock.Verify(nc => nc.TestAnotherActivateCallback(It.IsAny <Experiment>(), It.IsAny <string>(), It.IsAny <UserAttributes>(), It.IsAny <Variation>(), It.IsAny <LogEvent>()), Times.Once); notificationCallbackMock.Verify(nc => nc.TestTrackCallback(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <UserAttributes>(), It.IsAny <EventTags>(), It.IsAny <LogEvent>()), Times.Never); // Add logEvent Notification. NotificationCenter.AddNotification(NotificationType.LogEvent, notificationCallbackMock.Object.TestLogEventCallback); // Fire logEvent Notification. NotificationCenter.SendNotifications(NotificationType.LogEvent, logEventMocker.Object); // Verify that registered notifications of logEvent type are called. notificationCallbackMock.Verify(nc => nc.TestLogEventCallback(It.IsAny <LogEvent>()), Times.Once); // Verify that after clearing notifications, SendNotification should not call any notification // which were previously registered. NotificationCenter.ClearAllNotifications(); notificationCallbackMock.ResetCalls(); NotificationCenter.SendNotifications(NotificationTypeActivate, config.GetExperimentFromKey("test_experiment"), "testUser", new UserAttributes(), config.GetVariationFromId("test_experiment", "7722370027"), null); // Again verify notifications which were registered are not called. notificationCallbackMock.Verify(nc => nc.TestActivateCallback(It.IsAny <Experiment>(), It.IsAny <string>(), It.IsAny <UserAttributes>(), It.IsAny <Variation>(), It.IsAny <LogEvent>()), Times.Never); notificationCallbackMock.Verify(nc => nc.TestAnotherActivateCallback(It.IsAny <Experiment>(), It.IsAny <string>(), It.IsAny <UserAttributes>(), It.IsAny <Variation>(), It.IsAny <LogEvent>()), Times.Never); notificationCallbackMock.Verify(nc => nc.TestTrackCallback(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <UserAttributes>(), It.IsAny <EventTags>(), It.IsAny <LogEvent>()), Times.Never); }
public void Initialize() { LoggerMock = new Mock <ILogger>(); Config = DatafileProjectConfig.Create(TestData.Datafile, LoggerMock.Object, new ErrorHandler.NoOpErrorHandler()); }
public void TestCreateDoesNotThrowWithValidDatafile() { Assert.DoesNotThrow(() => DatafileProjectConfig.Create(TestData.Datafile, null, null)); }
public void TestProjectConfigDatafileIsSame() { ProjectConfig config = DatafileProjectConfig.Create(TestData.Datafile, new Mock <ILogger>().Object, new DefaultErrorHandler()); Assert.AreEqual(config.ToDatafile(), TestData.Datafile); }