public void TestAfterDisposeGetOptimizelyConfigIsNoLongerValid() { var httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithDatafile(TestData.Datafile) .WithPollingInterval(TimeSpan.FromMilliseconds(50000)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(500)) .Build(true); var optimizely = new Optimizely(httpManager); httpManager.Start(); var optimizelyConfig = optimizely.GetOptimizelyConfig(); Assert.NotNull(optimizelyConfig); Assert.NotNull(optimizelyConfig.ExperimentsMap); Assert.NotNull(optimizelyConfig.FeaturesMap); Assert.NotNull(optimizelyConfig.Revision); optimizely.Dispose(); var optimizelyConfigAfterDispose = optimizely.GetOptimizelyConfig(); Assert.Null(optimizelyConfigAfterDispose); }
public void TestHttpConfigManagerDoesNotWaitForTheConfigWhenDeferIsTrue() { var t = MockSendAsync(TestData.Datafile, TimeSpan.FromMilliseconds(150)); var httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithLogger(LoggerMock.Object) .WithPollingInterval(TimeSpan.FromSeconds(2)) // negligible timeout .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(50)) .WithStartByDefault() .Build(false); // When blocking timeout is 0 and defer is false and getconfig immediately called // should return null Assert.IsNull(httpManager.GetConfig()); // wait until config is retrieved. t.Wait(); // in case deadlock, it will release after 3sec. httpManager.OnReady().Wait(8000); HttpClientMock.Verify(_ => _.SendAsync(It.IsAny <HttpRequestMessage>())); Assert.NotNull(httpManager.GetConfig()); httpManager.Dispose(); }
public void TestPollingGivenOnlySdkKeyGetOptimizelyConfig() { HttpProjectConfigManager httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithLogger(LoggerMock.Object) .WithPollingInterval(TimeSpan.FromMilliseconds(1000)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(500)) .WithStartByDefault() .Build(true); Assert.NotNull(httpManager.GetConfig()); var optimizely = new Optimizely(httpManager); var optimizelyConfig = optimizely.GetOptimizelyConfig(); Assert.NotNull(optimizelyConfig); Assert.NotNull(optimizelyConfig.ExperimentsMap); Assert.NotNull(optimizelyConfig.FeaturesMap); Assert.NotNull(optimizelyConfig.Revision); optimizely.Dispose(); var optimizelyConfigAfterDispose = optimizely.GetOptimizelyConfig(); Assert.Null(optimizelyConfigAfterDispose); }
public void TestHttpProjectConfigManagerDoesntRaiseExceptionForDefaultErrorHandler() { var t = MockSendAsync(TestData.Datafile); HttpProjectConfigManager httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("10192104166") .WithFormat("https://cdn.optimizely.com/json/{0}.json") .WithLogger(LoggerMock.Object) .WithPollingInterval(TimeSpan.FromMilliseconds(1000)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(500)) .WithStartByDefault() .Build(true); t.Wait(1000); HttpClientMock.Verify(_ => _.SendAsync( It.Is <System.Net.Http.HttpRequestMessage>(requestMessage => requestMessage.RequestUri.ToString() == "https://cdn.optimizely.com/json/10192104166.json" ))); var datafileConfig = httpManager.GetConfig(); Assert.IsNotNull(datafileConfig); Assert.IsNull(datafileConfig.GetExperimentFromKey("project_config_not_valid").Key); LoggerMock.Verify(_ => _.Log(LogLevel.DEBUG, "Making datafile request to url \"https://cdn.optimizely.com/json/10192104166.json\"")); httpManager.Dispose(); }
public void TestEventProcessorWithBatchEventProcessorObj() { var eventDispatcher = new DefaultEventDispatcher(LoggerMock.Object); var notificationCenter = new NotificationCenter(); var projectConfigManager = new HttpProjectConfigManager.Builder() .WithSdkKey("10192104166") .Build(true); var batchEventProcessor = new BatchEventProcessor.Builder() .WithLogger(LoggerMock.Object) .WithMaxBatchSize(20) .WithFlushInterval(TimeSpan.FromSeconds(3)) .WithEventDispatcher(eventDispatcher) .WithNotificationCenter(notificationCenter) .Build(); var optimizely = OptimizelyFactory.NewDefaultInstance(projectConfigManager, notificationCenter, eventProcessor: batchEventProcessor); var actualbatchEventProcessor = Reflection.GetFieldValue <BatchEventProcessor, Optimizely>(optimizely, "EventProcessor"); var actualEventProcessorProps = new EventProcessorProps(actualbatchEventProcessor); var expectedEventProcessorProps = new EventProcessorProps(batchEventProcessor); Assert.AreEqual(actualEventProcessorProps, expectedEventProcessorProps); optimizely.Dispose(); }
public static Optimizely NewDefaultInstance() { var logger = OptimizelyLogger ?? new DefaultLogger(); OptimizelySDKConfigSection OptlySDKConfigSection = null; try { OptlySDKConfigSection = ConfigurationManager.GetSection(ConfigSectionName) as OptimizelySDKConfigSection; } catch (ConfigurationErrorsException ex) { logger.Log(LogLevel.ERROR, "Invalid App.Config. Unable to initialize optimizely instance" + ex.Message); return(null); } HttpProjectConfigElement httpProjectConfigElement = OptlySDKConfigSection.HttpProjectConfig; if (httpProjectConfigElement == null) { return(null); } var errorHandler = new DefaultErrorHandler(logger, false); var eventDispatcher = new DefaultEventDispatcher(logger); var builder = new HttpProjectConfigManager.Builder(); var notificationCenter = new NotificationCenter(); var configManager = builder .WithSdkKey(httpProjectConfigElement.SDKKey) .WithUrl(httpProjectConfigElement.Url) .WithFormat(httpProjectConfigElement.Format) .WithPollingInterval(TimeSpan.FromMilliseconds(httpProjectConfigElement.PollingInterval)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(httpProjectConfigElement.BlockingTimeOutPeriod)) #if !NET40 && !NET35 .WithAccessToken(httpProjectConfigElement.DatafileAccessToken) #endif .WithLogger(logger) .WithErrorHandler(errorHandler) .WithNotificationCenter(notificationCenter) .Build(true); EventProcessor eventProcessor = null; var batchEventProcessorElement = OptlySDKConfigSection.BatchEventProcessor; if (batchEventProcessorElement == null) { return(null); } eventProcessor = new BatchEventProcessor.Builder() .WithMaxBatchSize(batchEventProcessorElement.BatchSize) .WithFlushInterval(TimeSpan.FromMilliseconds(batchEventProcessorElement.FlushInterval)) .WithTimeoutInterval(TimeSpan.FromMilliseconds(batchEventProcessorElement.TimeoutInterval)) .WithLogger(logger) .WithEventDispatcher(eventDispatcher) .WithNotificationCenter(notificationCenter) .Build(); return(NewDefaultInstance(configManager, notificationCenter, eventDispatcher, errorHandler, logger, eventProcessor: eventProcessor)); }
public void TestOnReadyPromiseResolvedImmediatelyWhenDatafileIsProvided() { // Revision - 42 var t = MockSendAsync(TestData.SimpleABExperimentsDatafile, TimeSpan.FromMilliseconds(100)); HttpProjectConfigManager httpManager = new HttpProjectConfigManager.Builder() // Revision - 15 .WithSdkKey("10192104166") .WithDatafile(TestData.Datafile) .WithLogger(LoggerMock.Object) .WithPollingInterval(TimeSpan.FromMilliseconds(1000)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(500)) .WithStartByDefault() .Build(); // OnReady waits until is resolved, need to add time in case of deadlock. httpManager.OnReady().Wait(10000); Assert.AreEqual("15", httpManager.GetConfig().Revision); // loaded datafile from config manager after a second. // This wait triggers when SendAsync is triggered, OnReadyPromise is already resolved because of hardcoded datafile. t.Wait(); Task.Delay(200).Wait(); Assert.AreEqual("42", httpManager.GetConfig().Revision); httpManager.Dispose(); }
public static Optimizely NewDefaultInstance(string sdkKey, string fallback) { var logger = OptimizelyLogger ?? new DefaultLogger(); var errorHandler = new DefaultErrorHandler(); var eventDispatcher = new DefaultEventDispatcher(logger); var builder = new HttpProjectConfigManager.Builder(); var notificationCenter = new NotificationCenter(); var configManager = builder .WithSdkKey(sdkKey) .WithDatafile(fallback) .WithLogger(logger) .WithErrorHandler(errorHandler) .WithNotificationCenter(notificationCenter) .Build(true); EventProcessor eventProcessor = null; #if !NETSTANDARD1_6 && !NET35 eventProcessor = new BatchEventProcessor.Builder() .WithLogger(logger) .WithMaxBatchSize(MaxEventBatchSize) .WithFlushInterval(MaxEventFlushInterval) .WithEventDispatcher(eventDispatcher) .WithNotificationCenter(notificationCenter) .Build(); #endif return(NewDefaultInstance(configManager, notificationCenter, eventDispatcher, errorHandler, logger, eventProcessor: eventProcessor)); }
public void TestDefaultValuesWhenNotProvided() { var httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithDatafile(TestData.Datafile) .WithLogger(LoggerMock.Object) .Build(true); LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, $"No polling interval provided, using default period {TimeSpan.FromMinutes(5).TotalMilliseconds}ms")); LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, $"No Blocking timeout provided, using default blocking timeout {TimeSpan.FromSeconds(15).TotalMilliseconds}ms")); httpManager.Dispose(); }
public void TestDefaultPeriodWhileNotProvidingValue() { var httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithDatafile(TestData.Datafile) .WithLogger(LoggerMock.Object) .Build(true); var fieldInfo = typeof(PollingProjectConfigManager).GetField("PollingInterval", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); var expectedPollingInterval = (TimeSpan)fieldInfo.GetValue(httpManager); Assert.AreNotEqual(expectedPollingInterval.TotalSeconds, TimeSpan.Zero.TotalSeconds); LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, $"No polling interval provided, using default period {TimeSpan.FromMinutes(5).TotalMilliseconds}ms")); httpManager.Dispose(); }
public void TestDefaultBlockingTimeoutWhileNotProvidingValue() { var httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithDatafile(TestData.Datafile) .WithLogger(LoggerMock.Object) .Build(true); var fieldInfo = httpManager.GetType().GetField("BlockingTimeout", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); var expectedBlockingTimeout = (TimeSpan)fieldInfo.GetValue(httpManager); Assert.AreNotEqual(expectedBlockingTimeout.TotalSeconds, TimeSpan.Zero.TotalSeconds); LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, $"No Blocking timeout provided, using default blocking timeout {TimeSpan.FromSeconds(15).TotalMilliseconds}ms")); httpManager.Dispose(); }
public void TestHttpConfigManagerWithInvalidStatus() { var t = MockSendAsync(statusCode: HttpStatusCode.Forbidden); HttpProjectConfigManager httpManager = new HttpProjectConfigManager.Builder() .WithUrl("https://cdn.optimizely.com/datafiles/QBw9gFM8oTn7ogY9ANCC1z.json") .WithLogger(LoggerMock.Object) .WithPollingInterval(TimeSpan.FromMilliseconds(1000)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(500)) .WithStartByDefault() .Build(); LoggerMock.Verify(_ => _.Log(LogLevel.ERROR, $"Error fetching datafile \"{HttpStatusCode.Forbidden}\""), Times.AtLeastOnce); httpManager.Dispose(); }
public void TestDefaultUrlWhenTokenNotProvided() { var t = MockSendAsync(); var httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithLogger(LoggerMock.Object) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(50)) .Build(true); // it's to wait if SendAsync is not triggered. t.Wait(2000); HttpClientMock.Verify(_ => _.SendAsync( It.Is <System.Net.Http.HttpRequestMessage>(requestMessage => requestMessage.RequestUri.ToString() == "https://cdn.optimizely.com/datafiles/QBw9gFM8oTn7ogY9ANCC1z.json" ))); httpManager.Dispose(); }
public void TestHttpConfigManagerDoesNotSendConfigUpdateNotificationWhenDatafileIsProvided() { var t = MockSendAsync(TestData.Datafile, TimeSpan.FromMilliseconds(100)); var httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithDatafile(TestData.Datafile) .WithLogger(LoggerMock.Object) .WithPollingInterval(TimeSpan.FromMilliseconds(1000)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(500)) .Build(); httpManager.NotifyOnProjectConfigUpdate += NotificationCallbackMock.Object.TestConfigUpdateCallback; NotificationCallbackMock.Verify(nc => nc.TestConfigUpdateCallback(), Times.Never); Assert.NotNull(httpManager.GetConfig()); Assert.NotNull(httpManager.GetConfig()); httpManager.Dispose(); }
public void TestProjectConfigManagerWithCustomProjectConfigManager() { var projectConfigManager = new HttpProjectConfigManager.Builder() .WithSdkKey("10192104166") .WithFormat("https://optimizely.com/json/{0}.json") .WithPollingInterval(TimeSpan.FromMilliseconds(3000)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(4500)) .WithStartByDefault() .WithAccessToken("access-token") .Build(true); var optimizely = OptimizelyFactory.NewDefaultInstance(projectConfigManager); var actualProjectConfigManager = optimizely.ProjectConfigManager as HttpProjectConfigManager; var actualConfigManagerProps = new ProjectConfigManagerProps(actualProjectConfigManager); var expectedConfigManagerProps = new ProjectConfigManagerProps(projectConfigManager); Assert.AreEqual(actualConfigManagerProps, expectedConfigManagerProps); optimizely.Dispose(); }
/// <summary> /// Create optimizely client by set of parameters. Datafile will be updated from optimizely server /// </summary> /// <param name="createParameters"></param> /// <returns></returns> public static IOptimizely Create(OptimizelyClientCreateParameters createParameters) { if (createParameters == null) { throw new ArgumentNullException(nameof(createParameters)); } var builder = new HttpProjectConfigManager.Builder() .WithSdkKey(createParameters.SdkKey) .WithStartByDefault(); var projectConfigManager = builder .WithPollingInterval(TimeSpan.FromSeconds(createParameters.PollingPeriodInSeconds)) .Build(); var optimizely = new OptimizelySDK.Optimizely(projectConfigManager); return(new OptimizelyClient(optimizely)); }
public void TestFormatUrlHigherPriorityThanDefaultUrl() { var t = MockSendAsync(); var httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithLogger(LoggerMock.Object) .WithFormat("http://customformat/{0}.json") .WithAccessToken("datafile1") .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(50)) .Build(true); // it's to wait if SendAsync is not triggered. t.Wait(2000); HttpClientMock.Verify(_ => _.SendAsync( It.Is <System.Net.Http.HttpRequestMessage>(requestMessage => requestMessage.RequestUri.ToString() == "http://customformat/QBw9gFM8oTn7ogY9ANCC1z.json" ))); httpManager.Dispose(); }
public void TestHttpConfigManagerSendConfigUpdateNotificationWhenProjectConfigGetsUpdated() { var t = MockSendAsync(TestData.Datafile); var httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithLogger(LoggerMock.Object) .WithPollingInterval(TimeSpan.FromMilliseconds(1000)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(1000)) .WithStartByDefault(false) .Build(true); httpManager.NotifyOnProjectConfigUpdate += NotificationCallbackMock.Object.TestConfigUpdateCallback; httpManager.Start(); Assert.NotNull(httpManager.GetConfig()); Task.Delay(200).Wait(); NotificationCallbackMock.Verify(nc => nc.TestConfigUpdateCallback(), Times.AtLeastOnce); httpManager.Dispose(); }
public void TestAuthenticationHeaderWhenTokenProvided() { var t = MockSendAsync(); var httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithLogger(LoggerMock.Object) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(50)) .WithAccessToken("datafile1") .Build(true); // it's to wait if SendAsync is not triggered. t.Wait(2000); HttpClientMock.Verify(_ => _.SendAsync( It.Is <System.Net.Http.HttpRequestMessage>(requestMessage => requestMessage.Headers.Authorization.ToString() == "Bearer datafile1" ))); httpManager.Dispose(); }
public void TestHttpConfigManagerRetreiveProjectConfigBySDKKey() { var t = MockSendAsync(TestData.Datafile); HttpProjectConfigManager httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithLogger(LoggerMock.Object) .WithPollingInterval(TimeSpan.FromMilliseconds(1000)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(500)) .WithStartByDefault() .Build(); t.Wait(1000); HttpClientMock.Verify(_ => _.SendAsync( It.Is <System.Net.Http.HttpRequestMessage>(requestMessage => requestMessage.RequestUri.ToString() == "https://cdn.optimizely.com/datafiles/QBw9gFM8oTn7ogY9ANCC1z.json" ))); Assert.IsNotNull(httpManager.GetConfig()); httpManager.Dispose(); }
public void TestOnReadyPromiseWaitsForProjectConfigRetrievalWhenDatafileIsNotProvided() { // Revision - 42 var t = MockSendAsync(TestData.SimpleABExperimentsDatafile, TimeSpan.FromMilliseconds(1000)); HttpProjectConfigManager httpManager = new HttpProjectConfigManager.Builder() .WithSdkKey("QBw9gFM8oTn7ogY9ANCC1z") .WithLogger(LoggerMock.Object) .WithPollingInterval(TimeSpan.FromSeconds(2)) .WithBlockingTimeoutPeriod(TimeSpan.FromSeconds(1)) .WithStartByDefault(true) .Build(); t.Wait(); // OnReady waits until is resolved, need to add time in case of deadlock. httpManager.OnReady().Wait(10000); Assert.NotNull(httpManager.GetConfig()); httpManager.Dispose(); }
public void TestHttpConfigManagerRetreiveProjectConfigByURL() { var t = MockSendAsync(TestData.Datafile); HttpProjectConfigManager httpManager = new HttpProjectConfigManager.Builder() .WithUrl("https://cdn.optimizely.com/datafiles/QBw9gFM8oTn7ogY9ANCC1z.json") .WithLogger(LoggerMock.Object) .WithPollingInterval(TimeSpan.FromMilliseconds(1000)) .WithBlockingTimeoutPeriod(TimeSpan.FromMilliseconds(500)) .WithStartByDefault() .Build(); // This method waits until SendAsync is not triggered. // Time is given here to avoid hanging-up in any worst case. t.Wait(1000); HttpClientMock.Verify(_ => _.SendAsync( It.Is <System.Net.Http.HttpRequestMessage>(requestMessage => requestMessage.RequestUri.ToString() == "https://cdn.optimizely.com/datafiles/QBw9gFM8oTn7ogY9ANCC1z.json" ))); httpManager.Dispose(); }