public void DataSourceStatusStartsAsSetOfflineIfConfiguredOffline()
        {
            var config = BasicConfig().Offline(true).Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                var initialStatus = client.DataSourceStatusProvider.Status;
                Assert.Equal(DataSourceState.SetOffline, initialStatus.State);
                Assert.Null(initialStatus.LastError);
            }
        }
Exemple #2
0
 public void InitFailsOn401Sync(UpdateMode mode)
 {
     using (var server = HttpServer.Start(Handlers.Status(401)))
     {
         var config = BaseConfig(server.Uri, mode);
         using (var client = TestUtil.CreateClient(config, _user))
         {
             Assert.False(client.Initialized);
         }
     }
 }
Exemple #3
0
        public void EventProcessorIsOnlineByDefault()
        {
            var eventProcessor = new MockEventProcessor();
            var config         = BasicConfig()
                                 .Events(eventProcessor.AsSingletonFactory())
                                 .Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                Assert.False(eventProcessor.Offline);
            }
        }
Exemple #4
0
 public void InitGetsFlagsSync(UpdateMode mode)
 {
     using (var server = HttpServer.Start(SetupResponse(_flagData1, mode)))
     {
         var config = BaseConfig(server.Uri, mode);
         using (var client = TestUtil.CreateClient(config, _user, TimeSpan.FromSeconds(10)))
         {
             VerifyRequest(server.Recorder, mode);
             VerifyFlagValues(client, _flagData1);
         }
     }
 }
        public void DataSourceStatusStartsAsNetworkUnavailableIfNetworkIsUnavailable()
        {
            var connectivity = new MockConnectivityStateManager(false);
            var config       = BasicConfig().ConnectivityStateManager(connectivity).Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                var initialStatus = client.DataSourceStatusProvider.Status;
                Assert.Equal(DataSourceState.NetworkUnavailable, initialStatus.State);
                Assert.Null(initialStatus.LastError);
            }
        }
        public void NoDiagnosticInitEventIsSentIfOptedOut()
        {
            var config = BasicConfig()
                         .DiagnosticOptOut(true)
                         .Events(Components.SendEvents().EventSender(_testEventSender))
                         .Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                _testEventSender.RequireNoPayloadSent(TimeSpan.FromMilliseconds(100));
            }
        }
 public void DefaultPollingDataSourceBaseUri()
 {
     using (var client = TestUtil.CreateClient(
                BasicConfig()
                .DataSource(Components.PollingDataSource())
                .Http(Components.HttpConfiguration().MessageHandler(_stubHandler))
                .Build(),
                BasicUser))
     {
         var req = _stubHandler.Requests.ExpectValue();
         Assert.Equal(StandardEndpoints.BaseUris.PollingBaseUri, BaseUriOf(req.RequestUri));
     }
 }
 public void DefaultEventsBaseUri()
 {
     using (var client = TestUtil.CreateClient(
                BasicConfig()
                .Events(Components.SendEvents().FlushIntervalNoMinimum(TimeSpan.FromMilliseconds(10)))
                .Http(Components.HttpConfiguration().MessageHandler(_stubHandler))
                .Build(),
                BasicUser))
     {
         var req = _stubHandler.Requests.ExpectValue();
         Assert.Equal(StandardEndpoints.BaseUris.EventsBaseUri, BaseUriOf(req.RequestUri));
     }
 }
        public void DataSourceStatusStartsAsInitializing()
        {
            var config = BasicConfig()
                         .DataSource(new MockDataSourceThatNeverInitializes().AsSingletonFactory())
                         .Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                var initialStatus = client.DataSourceStatusProvider.Status;
                Assert.Equal(DataSourceState.Initializing, initialStatus.State);
                Assert.Null(initialStatus.LastError);
            }
        }
Exemple #10
0
        public void ConnectionChangeShouldStopDataSource()
        {
            var mockUpdateProc = new MockPollingProcessor(null);
            var mockConnectivityStateManager = new MockConnectivityStateManager(true);
            var config = BasicConfig()
                         .DataSource(mockUpdateProc.AsFactory())
                         .ConnectivityStateManager(mockConnectivityStateManager)
                         .Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                mockConnectivityStateManager.Connect(false);
                Assert.False(mockUpdateProc.IsRunning);
            }
        }
Exemple #11
0
        public void FlagsAreSavedToPersistentStorageByDefault()
        {
            var storage      = new MockPersistentDataStore();
            var initialFlags = new DataSetBuilder().Add("flag", 1, LdValue.Of(100), 0).Build();
            var config       = BasicConfig()
                               .DataSource(MockPollingProcessor.Factory(initialFlags))
                               .Persistence(Components.Persistence().Storage(storage.AsSingletonFactory()))
                               .Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                var storedData = storage.InspectUserData(config.MobileKey, BasicUser.Key);
                Assert.NotNull(storedData);
                AssertHelpers.DataSetsEqual(initialFlags, storedData.Value);
            }
        }
Exemple #12
0
        public void FlagsAreLoadedFromPersistentStorageByDefault()
        {
            var storage = new MockPersistentDataStore();
            var data    = new DataSetBuilder().Add("flag", 1, LdValue.Of(100), 0).Build();
            var config  = BasicConfig()
                          .Persistence(Components.Persistence().Storage(storage.AsSingletonFactory()))
                          .Offline(true)
                          .Build();

            storage.SetupUserData(config.MobileKey, BasicUser.Key, data);

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                Assert.Equal(100, client.IntVariation("flag", 99));
            }
        }
        public void ErrorIsLoggedIfANecessaryUriIsNotSetWhenOtherCustomUrisAreSet()
        {
            var logCapture1 = Logs.Capture();

            using (var client = TestUtil.CreateClient(
                       BasicConfig()
                       .DataSource(Components.StreamingDataSource())
                       .Http(Components.HttpConfiguration().MessageHandler(_stubHandler))
                       .Logging(logCapture1)
                       .ServiceEndpoints(Components.ServiceEndpoints().Polling(CustomUri))
                       .Build(),
                       BasicUser))
            {
                Assert.True(logCapture1.HasMessageWithRegex(LogLevel.Error,
                                                            "You have set custom ServiceEndpoints without specifying the Streaming base URI"));
            }

            var logCapture2 = Logs.Capture();

            using (var client = TestUtil.CreateClient(
                       BasicConfig()
                       .DataSource(Components.PollingDataSource())
                       .Http(Components.HttpConfiguration().MessageHandler(_stubHandler))
                       .Logging(logCapture2)
                       .ServiceEndpoints(Components.ServiceEndpoints().Events(CustomUri))
                       .Build(),
                       BasicUser))
            {
                Assert.True(logCapture2.HasMessageWithRegex(LogLevel.Error,
                                                            "You have set custom ServiceEndpoints without specifying the Polling base URI"));
            }

            var logCapture3 = Logs.Capture();

            using (var client = TestUtil.CreateClient(
                       BasicConfig()
                       .Events(Components.SendEvents())
                       .Http(Components.HttpConfiguration().MessageHandler(_stubHandler))
                       .Logging(logCapture3)
                       .ServiceEndpoints(Components.ServiceEndpoints().Streaming(CustomUri))
                       .Build(),
                       BasicUser))
            {
                Assert.True(logCapture3.HasMessageWithRegex(LogLevel.Error,
                                                            "You have set custom ServiceEndpoints without specifying the Events base URI"));
            }
        }
        public void CustomPollingDataSourceBaseUri()
        {
            using (var client = TestUtil.CreateClient(
                       BasicConfig()
                       .DataSource(Components.PollingDataSource())
                       .Http(Components.HttpConfiguration().MessageHandler(_stubHandler))
                       .ServiceEndpoints(Components.ServiceEndpoints().Polling(CustomUri))
                       .Build(),
                       BasicUser))
            {
                var req = _stubHandler.Requests.ExpectValue();
                Assert.Equal(CustomUri, BaseUriOf(req.RequestUri));

                Assert.False(logCapture.HasMessageWithRegex(LogLevel.Error,
                                                            "You have set custom ServiceEndpoints without specifying"));
            }
        }
        public void CustomEventsBaseUri()
        {
            using (var client = TestUtil.CreateClient(
                       BasicConfig()
                       .Events(Components.SendEvents().FlushIntervalNoMinimum(TimeSpan.FromMilliseconds(10)))
                       .Http(Components.HttpConfiguration().MessageHandler(_stubHandler))
                       .ServiceEndpoints(Components.ServiceEndpoints().Events(CustomUri))
                       .Build(),
                       BasicUser))
            {
                var req = _stubHandler.Requests.ExpectValue();
                Assert.Equal(CustomUri, BaseUriOf(req.RequestUri));

                Assert.False(logCapture.HasMessageWithRegex(LogLevel.Error,
                                                            "You have set custom ServiceEndpoints without specifying"));
            }
        }
Exemple #16
0
        public void InitCanTimeOutSync()
        {
            var handler = Handlers.Delay(TimeSpan.FromSeconds(2)).Then(SetupResponse(_flagData1, UpdateMode.Polling));

            using (var server = HttpServer.Start(handler))
            {
                var config = BaseConfig(builder =>
                                        builder.DataSource(Components.PollingDataSource())
                                        .ServiceEndpoints(Components.ServiceEndpoints().Polling(server.Uri)));
                using (var client = TestUtil.CreateClient(config, _user, TimeSpan.FromMilliseconds(200)))
                {
                    Assert.False(client.Initialized);
                    Assert.Null(client.StringVariation(_flagData1.Items.First().Key, null));
                    Assert.True(logCapture.HasMessageWithText(Logging.LogLevel.Warn,
                                                              "Client did not successfully initialize within 200 milliseconds."));
                }
            }
        }
        public void DiagnosticEventsAreNotSentWhenConfiguredOffline()
        {
            var config = BasicConfig()
                         .Offline(true)
                         .Events(Components.SendEvents()
                                 .EventSender(_testEventSender)
                                 .DiagnosticRecordingIntervalNoMinimum(TimeSpan.FromMilliseconds(50)))
                         .Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                _testEventSender.RequireNoPayloadSent(TimeSpan.FromMilliseconds(100));

                client.SetOffline(false, TimeSpan.FromMilliseconds(100));

                _testEventSender.RequirePayload();
            }
        }
Exemple #18
0
 public void HttpConfigurationIsAppliedToPolling()
 {
     TestHttpUtils.TestWithSpecialHttpConfigurations(
         PollingResponse(_flagData1),
         (targetUri, httpConfig, server) =>
     {
         var config = BasicConfig()
                      .DataSource(Components.PollingDataSource())
                      .Http(httpConfig)
                      .ServiceEndpoints(Components.ServiceEndpoints().Polling(targetUri))
                      .Build();
         using (var client = TestUtil.CreateClient(config, BasicUser))
         {
             VerifyFlagValues(client, _flagData1);
         }
     },
         testLogger
         );
 }
        public void DataSourceStatusProviderSendsStatusUpdates()
        {
            var testData = TestData.DataSource();
            var config   = BasicConfig().DataSource(testData).Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                var statuses = new EventSink <DataSourceStatus>();
                client.DataSourceStatusProvider.StatusChanged += statuses.Add;

                var errorInfo = DataSourceStatus.ErrorInfo.FromHttpError(401);
                testData.UpdateStatus(DataSourceState.Shutdown, errorInfo);

                var newStatus = statuses.ExpectValue();
                Assert.Equal(DataSourceState.Shutdown, newStatus.State);
                Assert.True(newStatus.StateSince >= errorInfo.Time);
                Assert.Equal(errorInfo, newStatus.LastError);
            }
        }
        public void DiagnosticEventsAreNotSentWhenNetworkIsUnavailable()
        {
            var connectivityStateManager = new MockConnectivityStateManager(false);
            var config = BasicConfig()
                         .ConnectivityStateManager(connectivityStateManager)
                         .Events(Components.SendEvents()
                                 .EventSender(_testEventSender)
                                 .DiagnosticRecordingIntervalNoMinimum(TimeSpan.FromMilliseconds(50)))
                         .Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                _testEventSender.RequireNoPayloadSent(TimeSpan.FromMilliseconds(100));

                connectivityStateManager.Connect(true);

                _testEventSender.RequirePayload();
            }
        }
Exemple #21
0
        public void IdentifyDoesNotSendAliasEventIfOptedOUt()
        {
            User oldUser = User.Builder("anon-key").Anonymous(true).Build();
            User newUser = User.WithKey("real-key");

            var config = BasicConfig()
                         .Events(_factory)
                         .AutoAliasingOptOut(true)
                         .Build();

            using (LdClient client = TestUtil.CreateClient(config, oldUser))
            {
                User actualOldUser = client.User; // so we can get any automatic properties that the client added
                client.Identify(newUser, TimeSpan.FromSeconds(1));

                Assert.Collection(eventProcessor.Events,
                                  e => CheckIdentifyEvent(e, actualOldUser),
                                  e => CheckIdentifyEvent(e, newUser));
            }
        }
        public void DataSourceStatusIsRestoredWhenNoLongerSetOffline()
        {
            var testData = TestData.DataSource();
            var config   = BasicConfig().DataSource(testData).Offline(true).Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                Assert.True(client.DataSourceStatusProvider.WaitFor(DataSourceState.SetOffline, TimeSpan.FromSeconds(5)));

                var statuses = new EventSink <DataSourceStatus>();
                client.DataSourceStatusProvider.StatusChanged += statuses.Add;

                client.SetOffline(false, TimeSpan.FromSeconds(1));

                var newStatus1 = statuses.ExpectValue();
                Assert.Equal(DataSourceState.Initializing, newStatus1.State);

                var newStatus2 = statuses.ExpectValue();
                Assert.Equal(DataSourceState.Valid, newStatus2.State);
            }
        }
Exemple #23
0
 public void HttpConfigurationIsAppliedToEvents()
 {
     TestHttpUtils.TestWithSpecialHttpConfigurations(
         EventsAcceptedResponse,
         (targetUri, httpConfig, server) =>
     {
         var config = BasicConfig()
                      .DiagnosticOptOut(true)
                      .Events(Components.SendEvents())
                      .Http(httpConfig)
                      .ServiceEndpoints(Components.ServiceEndpoints().Events(targetUri))
                      .Build();
         using (var client = TestUtil.CreateClient(config, BasicUser))
         {
             client.Flush();
             server.Recorder.RequireRequest();
         }
     },
         testLogger
         );
 }
        public void DataSourceStatusRemainsInitializingAfterErrorIfNeverInitialized()
        {
            var dataSourceFactory = new CapturingDataSourceFactory();

            var config = BasicConfig()
                         .DataSource(dataSourceFactory)
                         .Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                var statuses = new EventSink <DataSourceStatus>();
                client.DataSourceStatusProvider.StatusChanged += statuses.Add;

                var errorInfo = DataSourceStatus.ErrorInfo.FromHttpError(503);
                dataSourceFactory.UpdateSink.UpdateStatus(DataSourceState.Interrupted, errorInfo);

                var newStatus1 = statuses.ExpectValue();
                Assert.Equal(DataSourceState.Initializing, newStatus1.State);
                Assert.Equal(errorInfo, newStatus1.LastError);
            }
        }
Exemple #25
0
        public void IdentifyCanTimeOutSync(UpdateMode mode)
        {
            using (var server = HttpServer.Start(Handlers.Switchable(out var switchable)))
            {
                switchable.Target = SetupResponse(_flagData1, mode);

                var config = BaseConfig(server.Uri, mode);
                using (var client = TestUtil.CreateClient(config, _user))
                {
                    var req1 = VerifyRequest(server.Recorder, mode);
                    VerifyFlagValues(client, _flagData1);

                    switchable.Target = Handlers.Delay(TimeSpan.FromSeconds(2))
                                        .Then(SetupResponse(_flagData1, mode));

                    var success = client.Identify(_otherUser, TimeSpan.FromMilliseconds(100));
                    Assert.False(success);
                    Assert.False(client.Initialized);
                    Assert.Null(client.StringVariation(_flagData1.Items.First().Key, null));
                }
            }
        }
        public void DataSourceStatusProviderReturnsLatestStatus()
        {
            var testData           = TestData.DataSource();
            var config             = BasicConfig().DataSource(testData).Build();
            var timeBeforeStarting = DateTime.Now;

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                var initialStatus = client.DataSourceStatusProvider.Status;
                Assert.Equal(DataSourceState.Valid, initialStatus.State);
                Assert.True(initialStatus.StateSince >= timeBeforeStarting);
                Assert.Null(initialStatus.LastError);

                var errorInfo = DataSourceStatus.ErrorInfo.FromHttpError(401);
                testData.UpdateStatus(DataSourceState.Shutdown, errorInfo);

                var newStatus = client.DataSourceStatusProvider.Status;
                Assert.Equal(DataSourceState.Shutdown, newStatus.State);
                Assert.True(newStatus.StateSince >= errorInfo.Time);
                Assert.Equal(errorInfo, newStatus.LastError);
            }
        }
Exemple #27
0
        public void StreamingInitMakesPollRequestIfStreamSendsPing()
        {
            Handler streamHandler = Handlers.SSE.Start()
                                    .Then(Handlers.SSE.Event("ping", ""))
                                    .Then(Handlers.SSE.LeaveOpen());

            using (var streamServer = HttpServer.Start(streamHandler))
            {
                using (var pollServer = HttpServer.Start(SetupResponse(_flagData1, UpdateMode.Polling)))
                {
                    var config = BaseConfig(b =>
                                            b.DataSource(Components.StreamingDataSource())
                                            .ServiceEndpoints(Components.ServiceEndpoints().Streaming(streamServer.Uri).Polling(pollServer.Uri)));
                    using (var client = TestUtil.CreateClient(config, _user, TimeSpan.FromSeconds(5)))
                    {
                        VerifyRequest(streamServer.Recorder, UpdateMode.Streaming);
                        VerifyRequest(pollServer.Recorder, UpdateMode.Polling);
                        VerifyFlagValues(client, _flagData1);
                    }
                }
            }
        }
        public void DiagnosticPeriodicEventsAreSent()
        {
            var config = BasicConfig()
                         .Events(Components.SendEvents()
                                 .EventSender(_testEventSender)
                                 .DiagnosticRecordingIntervalNoMinimum(TimeSpan.FromMilliseconds(50)))
                         .Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                var payload1 = _testEventSender.RequirePayload();

                Assert.Equal(EventDataKind.DiagnosticEvent, payload1.Kind);
                Assert.Equal(1, payload1.EventCount);
                var data1 = LdValue.Parse(payload1.Data);
                Assert.Equal("diagnostic-init", data1.Get("kind").AsString);
                var timestamp1 = data1.Get("creationDate").AsLong;
                Assert.NotEqual(0, timestamp1);

                var payload2 = _testEventSender.RequirePayload();

                Assert.Equal(EventDataKind.DiagnosticEvent, payload2.Kind);
                Assert.Equal(1, payload2.EventCount);
                var data2 = LdValue.Parse(payload2.Data);
                Assert.Equal("diagnostic", data2.Get("kind").AsString);
                var timestamp2 = data2.Get("creationDate").AsLong;
                Assert.InRange(timestamp2, timestamp1, timestamp1 + 1000);

                var payload3 = _testEventSender.RequirePayload();

                Assert.Equal(EventDataKind.DiagnosticEvent, payload3.Kind);
                Assert.Equal(1, payload3.EventCount);
                var data3 = LdValue.Parse(payload3.Data);
                Assert.Equal("diagnostic", data3.Get("kind").AsString);
                var timestamp3 = data2.Get("creationDate").AsLong;
                Assert.InRange(timestamp3, timestamp2, timestamp1 + 1000);
            }
        }
Exemple #29
0
        public void OfflineClientUsesCachedFlagsSync()
        {
            var sharedPersistenceConfig = Components.Persistence()
                                          .Storage(new MockPersistentDataStore().AsSingletonFactory());

            // streaming vs. polling should make no difference for this
            using (var server = HttpServer.Start(SetupResponse(_flagData1, UpdateMode.Polling)))
            {
                var config = BaseConfig(server.Uri, UpdateMode.Polling, c => c.Persistence(sharedPersistenceConfig));
                using (var client = TestUtil.CreateClient(config, _user))
                {
                    VerifyFlagValues(client, _flagData1);
                }

                // At this point the SDK should have written the flags to persistent storage for this user key.
                // We'll now start over in offline mode, and we should still see the earlier flag values.
                var offlineConfig = BasicConfig().Offline(true).Persistence(sharedPersistenceConfig).Build();
                using (var client = TestUtil.CreateClient(offlineConfig, _user))
                {
                    VerifyFlagValues(client, _flagData1);
                }
            }
        }
        public void EventSenderIsClientInstance()
        {
            // We're only checking one kind of events here (FlagValueChanged), but since the SDK uses the
            // same TaskExecutor instance for all event dispatches and the sender is configured in
            // that object, the sender should be the same for all events.

            var flagKey  = "flagKey";
            var testData = TestData.DataSource();

            testData.Update(testData.Flag(flagKey).Variation(true));
            var config = BasicConfig().DataSource(testData).Build();

            using (var client = TestUtil.CreateClient(config, BasicUser))
            {
                var receivedSender = new EventSink <object>();
                client.FlagTracker.FlagValueChanged += (s, e) => receivedSender.Enqueue(s);

                testData.Update(testData.Flag(flagKey).Variation(false));

                var sender = receivedSender.ExpectValue();
                Assert.Same(client, sender);
            }
        }