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 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 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 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 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 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 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 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 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 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 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 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 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 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 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();
        }