public void DiagnosticInitEventIsSent()
        {
            var config = BasicConfig()
                         .Events(Components.SendEvents().EventSender(testEventSender))
                         .Http(
                Components.HttpConfiguration().Wrapper(testWrapperName, testWrapperVersion)
                )
                         .Build();

            using (var client = new LdClient(config))
            {
                var payload = testEventSender.RequirePayload();

                Assert.Equal(EventDataKind.DiagnosticEvent, payload.Kind);
                Assert.Equal(1, payload.EventCount);

                var data = JsonOf(payload.Data);
                AssertJsonEqual(JsonFromValue("diagnostic-init"), data.Property("kind"));
                AssertJsonEqual(JsonFromValue("dotnet"), data.RequiredProperty("platform").Property("name"));
                AssertJsonEqual(JsonFromValue(ServerDiagnosticStore.GetDotNetTargetFramework()),
                                data.RequiredProperty("platform").Property("dotNetTargetFramework"));
                AssertJsonEqual(expectedSdk, data.Property("sdk"));
                AssertJsonEqual(JsonFromValue("dk-key"), data.Property("id").Property("sdkKeySuffix"));

                data.RequiredProperty("creationDate");
            }
        }
Esempio n. 2
0
        public void DiagnosticStoreNotPassedToFactoriesWhenOptedOut()
        {
            var epf    = new Mock <IEventProcessorFactory>();
            var dsf    = new Mock <IDataSourceFactory>();
            var config = BasicConfig()
                         .Events(epf.Object)
                         .DataSource(dsf.Object)
                         .DiagnosticOptOut(true)
                         .Build();

            IDiagnosticStore eventProcessorDiagnosticStore = null;
            IDiagnosticStore dataSourceDiagnosticStore     = null;
            var dataSource = MockDataSourceWithStartFn(_ => Task.FromResult(true));

            epf.Setup(f => f.CreateEventProcessor(It.IsAny <LdClientContext>()))
            .Callback((LdClientContext ctx) => eventProcessorDiagnosticStore = ctx.DiagnosticStore)
            .Returns(new ComponentsImpl.NullEventProcessor());
            dsf.Setup(f => f.CreateDataSource(It.IsAny <LdClientContext>(), It.IsAny <IDataSourceUpdates>()))
            .Callback((LdClientContext ctx, IDataSourceUpdates dsu) => dataSourceDiagnosticStore = ctx.DiagnosticStore)
            .Returns((LdClientContext ctx, IDataSourceUpdates dsu) => dataSource);

            using (var client = new LdClient(config))
            {
                epf.Verify(f => f.CreateEventProcessor(It.IsNotNull <LdClientContext>()), Times.Once());
                epf.VerifyNoOtherCalls();
                dsf.Verify(f => f.CreateDataSource(It.IsNotNull <LdClientContext>(), It.IsNotNull <IDataSourceUpdates>()), Times.Once());
                dsf.VerifyNoOtherCalls();
                Assert.Null(eventProcessorDiagnosticStore);
                Assert.Null(dataSourceDiagnosticStore);
            }
        }
        private void TestDiagnosticConfig(
            Func <ConfigurationBuilder, ConfigurationBuilder> modConfig,
            Func <EventProcessorBuilder, EventProcessorBuilder> modEvents,
            LdValue.ObjectBuilder expected
            )
        {
            var eventsBuilder = Components.SendEvents()
                                .EventSender(testEventSender);

            modEvents?.Invoke(eventsBuilder);
            var configBuilder = BasicConfig()
                                .DataSource(null)
                                .Events(eventsBuilder)
                                .Http(Components.HttpConfiguration().MessageHandler(new StubMessageHandler(HttpStatusCode.Unauthorized)))
                                .StartWaitTime(testStartWaitTime);

            configBuilder = modConfig is null ? configBuilder : modConfig(configBuilder);
            using (var client = new LdClient(configBuilder.Build()))
            {
                var payload = testEventSender.RequirePayload();

                Assert.Equal(EventDataKind.DiagnosticEvent, payload.Kind);
                Assert.Equal(1, payload.EventCount);

                var data = JsonOf(payload.Data);
                AssertJsonEqual(JsonFromValue("diagnostic-init"), data.Property("kind"));

                AssertJsonEqual(JsonOf(expected.Build().ToJsonString()), data.Property("configuration"));
            }
        }
        public void ExceptionWhenGettingOneFlagIsHandledCorrectly()
        {
            // If the data store's Get method throws an error, the expected behavior is that we log
            // a message and return the default value. The exception should not propagate to the caller.
            var ex        = new Exception("fake-error");
            var flagKey   = "flag-key";
            var mockStore = new Mock <IDataStore>();

            mockStore.Setup(s => s.Get(DataModel.Features, flagKey)).Throws(ex);
            var configWithCustomStore = Configuration.Builder("sdk-key")
                                        .DataStore(new SpecificDataStoreFactory(mockStore.Object))
                                        .DataSource(Components.ExternalUpdatesOnly)
                                        .Logging(testLogging)
                                        .Build();

            using (var clientWithCustomStore = new LdClient(configWithCustomStore))
            {
                var defaultValue = "default-value";
                var result       = clientWithCustomStore.StringVariationDetail("flag-key", user, defaultValue);
                Assert.Equal(defaultValue, result.Value);
                Assert.Null(result.VariationIndex);
                Assert.Equal(EvaluationReason.ErrorReason(EvaluationErrorKind.Exception), result.Reason);
                Assert.True(logCapture.HasMessageWithRegex(Logging.LogLevel.Error, ex.Message));
            }
        }
        public void ClientRetriesConnectionInStreamingModeWithNonFatalError()
        {
            var failThenSucceedHandler = Handlers.Sequential(Error503Response, ValidStreamingResponse);

            using (var streamServer = HttpServer.Start(failThenSucceedHandler))
            {
                var config = BasicConfig()
                             .DataSource(Components.StreamingDataSource())
                             .ServiceEndpoints(Components.ServiceEndpoints().Streaming(streamServer.Uri))
                             .StartWaitTime(TimeSpan.FromSeconds(5))
                             .Build();

                using (var client = new LdClient(config))
                {
                    Assert.True(client.Initialized);
                    Assert.Equal(DataSourceState.Valid, client.DataSourceStatusProvider.Status.State);

                    var value = client.BoolVariation(AlwaysTrueFlag.Key, BasicUser, false);
                    Assert.True(value);

                    var request1 = streamServer.Recorder.RequireRequest();
                    var request2 = streamServer.Recorder.RequireRequest();
                    Assert.Equal(BasicSdkKey, request1.Headers.Get("Authorization"));
                    Assert.Equal(BasicSdkKey, request2.Headers.Get("Authorization"));

                    Assert.NotEmpty(LogCapture.GetMessages().Where(
                                        m => m.Level == Logging.LogLevel.Warn && m.Text.Contains("error 503") &&
                                        m.Text.Contains("will retry")));
                    Assert.Empty(LogCapture.GetMessages().Where(m => m.Level == Logging.LogLevel.Error));
                }
            }
        }
        public void DiagnosticStoreNotPassedToFactoriesWhenOptedOut()
        {
            var epf    = new Mock <IEventProcessorFactory>();
            var dsf    = new Mock <IDataSourceFactory>();
            var config = Configuration.Builder(sdkKey)
                         .DataSource(Components.ExternalUpdatesOnly)
                         .StartWaitTime(TimeSpan.Zero)
                         .Events(epf.Object)
                         .DataSource(dsf.Object)
                         .DiagnosticOptOut(true)
                         .Logging(Components.Logging(testLogging))
                         .Build();

            IDiagnosticStore eventProcessorDiagnosticStore = null;
            IDiagnosticStore dataSourceDiagnosticStore     = null;

            epf.Setup(f => f.CreateEventProcessor(It.IsAny <LdClientContext>()))
            .Callback((LdClientContext ctx) => eventProcessorDiagnosticStore = ctx.DiagnosticStore)
            .Returns(new ComponentsImpl.NullEventProcessor());
            dsf.Setup(f => f.CreateDataSource(It.IsAny <LdClientContext>(), It.IsAny <IDataSourceUpdates>()))
            .Callback((LdClientContext ctx, IDataSourceUpdates dsu) => dataSourceDiagnosticStore = ctx.DiagnosticStore)
            .Returns((LdClientContext ctx, IDataSourceUpdates dsu) => dataSource);

            using (var client = new LdClient(config))
            {
                epf.Verify(f => f.CreateEventProcessor(It.IsNotNull <LdClientContext>()), Times.Once());
                epf.VerifyNoOtherCalls();
                dsf.Verify(f => f.CreateDataSource(It.IsNotNull <LdClientContext>(), It.IsNotNull <IDataSourceUpdates>()), Times.Once());
                dsf.VerifyNoOtherCalls();
                Assert.Null(eventProcessorDiagnosticStore);
                Assert.Null(dataSourceDiagnosticStore);
            }
        }
Esempio n. 7
0
        private void TestDiagnosticConfig(
            Func <ConfigurationBuilder, ConfigurationBuilder> modConfig,
            Func <EventProcessorBuilder, EventProcessorBuilder> modEvents,
            LdValue.ObjectBuilder expected
            )
        {
            var eventsBuilder = Components.SendEvents()
                                .EventSender(testEventSender);

            modEvents?.Invoke(eventsBuilder);
            var configBuilder = Configuration.Builder(sdkKey)
                                .Events(eventsBuilder)
                                .Http(Components.HttpConfiguration().MessageHandler(new StubMessageHandler(HttpStatusCode.Unauthorized)))
                                .Logging(Components.Logging(testLogging))
                                .StartWaitTime(testStartWaitTime);

            modConfig?.Invoke(configBuilder);
            using (var client = new LdClient(configBuilder.Build()))
            {
                var payload = testEventSender.RequirePayload();

                Assert.Equal(EventDataKind.DiagnosticEvent, payload.Kind);
                Assert.Equal(1, payload.EventCount);

                var data = LdValue.Parse(payload.Data);
                Assert.Equal("diagnostic-init", data.Get("kind").AsString);

                AssertHelpers.JsonEqual(expected.Build(), data.Get("configuration"));
            }
        }
        public void DataSourceStatusProviderReturnsLatestStatus()
        {
            var testData = TestData.DataSource();
            var config   = Configuration.Builder("")
                           .DataSource(testData)
                           .Events(Components.NoEvents)
                           .Logging(Components.Logging(testLogging))
                           .Build();
            var timeBeforeStarting = DateTime.Now;

            using (var client = new LdClient(config))
            {
                var initialStatus = client.DataSourceStatusProvider.Status;
                Assert.Equal(DataSourceState.Valid, initialStatus.State);
                Assert.InRange(initialStatus.StateSince, timeBeforeStarting, timeBeforeStarting.AddSeconds(1));
                Assert.Null(initialStatus.LastError);

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

                var newStatus = client.DataSourceStatusProvider.Status;
                Assert.Equal(DataSourceState.Off, newStatus.State);
                Assert.InRange(newStatus.StateSince, errorInfo.Time, errorInfo.Time.AddSeconds(1));
                Assert.Equal(errorInfo, newStatus.LastError);
            }
        }
Esempio n. 9
0
        public void BigSegmentStoreStatusProviderSendsStatusUpdates()
        {
            var storeMock    = new MockBigSegmentStore();
            var storeFactory = storeMock.AsSingletonFactory();

            storeMock.SetupMetadataReturns(
                new BigSegmentStoreTypes.StoreMetadata {
                LastUpToDate = UnixMillisecondTime.Now
            });

            var config = BasicConfig()
                         .BigSegments(
                Components.BigSegments(storeFactory).StatusPollInterval(TimeSpan.FromMilliseconds(10))
                )
                         .Build();

            using (var client = new LdClient(config))
            {
                var status1 = client.BigSegmentStoreStatusProvider.Status;
                Assert.True(status1.Available);

                var statuses = new EventSink <BigSegmentStoreStatus>();
                client.BigSegmentStoreStatusProvider.StatusChanged += statuses.Add;

                storeMock.SetupMetadataThrows(new Exception("sorry"));

                var status2 = statuses.ExpectValue();
                if (status2.Available)
                {
                    // depending on timing, we might or might not receive an initial update of Available = true
                    status2 = statuses.ExpectValue();
                    Assert.False(status2.Available);
                }
            }
        }
Esempio n. 10
0
        public void DiagnosticInitEventIsSent()
        {
            var config = Configuration.Builder(sdkKey)
                         .DataSource(Components.ExternalUpdatesOnly)
                         .Events(Components.SendEvents().EventSender(testEventSender))
                         .Http(
                Components.HttpConfiguration().Wrapper(testWrapperName, testWrapperVersion)
                )
                         .Logging(Components.Logging(testLogging))
                         .Build();

            using (var client = new LdClient(config))
            {
                var payload = testEventSender.RequirePayload();

                Assert.Equal(EventDataKind.DiagnosticEvent, payload.Kind);
                Assert.Equal(1, payload.EventCount);

                var data = LdValue.Parse(payload.Data);
                Assert.Equal("diagnostic-init", data.Get("kind").AsString);
                AssertHelpers.JsonEqual(ExpectedPlatform(), data.Get("platform"));
                AssertHelpers.JsonEqual(expectedSdk, data.Get("sdk"));
                Assert.Equal("DK_KEY", data.Get("id").Get("sdkKeySuffix").AsString);

                var timestamp = data.Get("creationDate").AsLong;
                Assert.NotEqual(0, timestamp);
            }
        }
        public void ClientFailsToStartInStreamingModeWith401Error()
        {
            using (var streamServer = HttpServer.Start(Error401Response))
            {
                var config = BasicConfig()
                             .DataSource(Components.StreamingDataSource())
                             .ServiceEndpoints(Components.ServiceEndpoints().Streaming(streamServer.Uri))
                             .StartWaitTime(TimeSpan.FromSeconds(5))
                             .Build();

                using (var client = new LdClient(config))
                {
                    Assert.False(client.Initialized);
                    Assert.Equal(DataSourceState.Off, client.DataSourceStatusProvider.Status.State);

                    var value = client.BoolVariation(AlwaysTrueFlag.Key, BasicUser, false);
                    Assert.False(value);

                    var request = streamServer.Recorder.RequireRequest();
                    Assert.Equal(BasicSdkKey, request.Headers.Get("Authorization"));

                    Assert.NotEmpty(LogCapture.GetMessages().Where(
                                        m => m.Level == Logging.LogLevel.Error && m.Text.Contains("error 401") &&
                                        m.Text.Contains("giving up permanently")));
                }
            }
        }
        public void DataSetIsPassedToDataStoreInCorrectOrder()
        {
            // The underlying functionality here is also covered in DataStoreSorterTest, but we want to verify that the
            // client object is actually *using* DataStoreSorter.

            var mockStore = new Mock <IDataStore>();
            var store     = mockStore.Object;
            FullDataSet <ItemDescriptor> receivedData = new FullDataSet <ItemDescriptor>();

            mockStore.Setup(s => s.Init(It.IsAny <FullDataSet <ItemDescriptor> >()))
            .Callback((FullDataSet <ItemDescriptor> data) => {
                receivedData = data;
            });

            mockDataSource.Setup(up => up.Start()).Returns(initTask);

            var config = Configuration.Builder(sdkKey)
                         .DataStore(TestUtils.SpecificDataStore(store))
                         .DataSource(TestUtils.DataSourceWithData(DataStoreSorterTest.DependencyOrderingTestData))
                         .Events(Components.NoEvents)
                         .Logging(Components.Logging(testLogging))
                         .Build();

            using (var client = new LdClient(config))
            {
                Assert.NotNull(receivedData);
                DataStoreSorterTest.VerifyDataSetOrder(receivedData, DataStoreSorterTest.DependencyOrderingTestData,
                                                       DataStoreSorterTest.ExpectedOrderingForSortedDataSet);
            }
        }
Esempio n. 13
0
        public void OfflineClientHasNullEventProcessor()
        {
            var config = BasicConfig().Offline(true).Build();

            using (var client = new LdClient(config))
            {
                Assert.IsType <ComponentsImpl.NullEventProcessor>(client._eventProcessor);
            }
        }
Esempio n. 14
0
        public void OfflineClientIsInitialized()
        {
            var config = BasicConfig().Offline(true).Build();

            using (var client = new LdClient(config))
            {
                Assert.True(client.Initialized);
            }
        }
Esempio n. 15
0
        public void OfflineReturnsDefaultValue()
        {
            var config = BasicConfig().Offline(true).Build();

            using (var client = new LdClient(config))
            {
                Assert.Equal("x", client.StringVariation("key", User.WithKey("user"), "x"));
            }
        }
Esempio n. 16
0
        public void DataStoreStatusMonitoringIsDisabledForInMemoryDataStore()
        {
            var config = BasicConfig().Build();

            using (var client = new LdClient(config))
            {
                Assert.False(client.DataStoreStatusProvider.StatusMonitoringEnabled);
            }
        }
Esempio n. 17
0
        public void OfflineClientStartupMessage()
        {
            var config = BasicConfig().Offline(true).Build();

            using (var client = new LdClient(config))
            {
                AssertLogMessage(true, LogLevel.Info, "Starting LaunchDarkly client in offline mode");
            }
        }
Esempio n. 18
0
        public void OfflineClientHasNullDataSource()
        {
            var config = BasicConfig().Offline(true).Build();

            using (var client = new LdClient(config))
            {
                Assert.IsType <ComponentsImpl.NullDataSource>(client._dataSource);
            }
        }
Esempio n. 19
0
        public void OfflineClientIsInitialized()
        {
            var config = Configuration.Builder(sdkKey).Offline(true)
                         .Logging(Components.Logging(testLogging)).Build();

            using (var client = new LdClient(config))
            {
                Assert.True(client.Initialized);
            }
        }
Esempio n. 20
0
        public void OfflineClientHasNullDataSource()
        {
            var config = Configuration.Builder(sdkKey).Offline(true)
                         .Logging(Components.Logging(testLogging)).Build();

            using (var client = new LdClient(config))
            {
                Assert.IsType <ComponentsImpl.NullDataSource>(client._dataSource);
            }
        }
Esempio n. 21
0
        public void OfflineReturnsDefaultValue()
        {
            var config = Configuration.Builder(sdkKey).Offline(true)
                         .Logging(Components.Logging(testLogging)).Build();

            using (var client = new LdClient(config))
            {
                Assert.Equal("x", client.StringVariation("key", User.WithKey("user"), "x"));
            }
        }
Esempio n. 22
0
        public void OfflineClientHasNullEventProcessor()
        {
            var config = Configuration.Builder(sdkKey).Offline(true)
                         .Logging(Components.Logging(testLogging)).Build();

            using (var client = new LdClient(config))
            {
                Assert.IsType <ComponentsImpl.NullEventProcessor>(client._eventProcessor);
            }
        }
Esempio n. 23
0
        public void TestSecureModeHash()
        {
            var config = BasicConfig().SdkKey("secret").Offline(true).Build();

            using (var client = new LdClient(config))
            {
                Assert.Equal("aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597",
                             client.SecureModeHash(User.WithKey("Message")));
            }
        }
Esempio n. 24
0
        public void ClientStartupMessage()
        {
            var config = BasicConfig().Build();

            using (var client = new LdClient(config))
            {
                AssertLogMessage(true, LogLevel.Info,
                                 "Starting LaunchDarkly client " + AssemblyVersions.GetAssemblyVersionStringForType(typeof(LdClient)));
                Assert.All(LogCapture.GetMessages(), m => m.LoggerName.StartsWith(LogNames.DefaultBase));
            }
        }
Esempio n. 25
0
        public void OfflineClientStartupMessage()
        {
            var config = Configuration.Builder(sdkKey).Offline(true)
                         .Logging(Components.Logging(testLogging)).Build();

            using (var client = new LdClient(config))
            {
                Assert.True(logCapture.HasMessageWithText(LogLevel.Info,
                                                          "Starting LaunchDarkly client in offline mode"), logCapture.ToString());
            }
        }
Esempio n. 26
0
        public void TestSecureModeHash()
        {
            var config = Configuration.Builder("secret").Offline(true)
                         .Logging(Components.Logging(testLogging)).Build();

            using (var client = new LdClient(config))
            {
                Assert.Equal("aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597",
                             client.SecureModeHash(User.WithKey("Message")));
            }
        }
Esempio n. 27
0
        public void BigSegmentStoreStatusProviderReturnsUnavailableStatusWhenNotConfigured()
        {
            var config = BasicConfig().Build();

            using (var client = new LdClient(config))
            {
                var status = client.BigSegmentStoreStatusProvider.Status;
                Assert.False(status.Available);
                Assert.False(status.Stale);
            }
        }
Esempio n. 28
0
        public void LddModeClientHasNullDataSource()
        {
            var config = BasicConfig()
                         .DataSource(Components.ExternalUpdatesOnly)
                         .Build();

            using (var client = new LdClient(config))
            {
                Assert.IsType <ComponentsImpl.NullDataSource>(client._dataSource);
            }
        }
Esempio n. 29
0
        public void LddModeClientIsInitialized()
        {
            var config = BasicConfig()
                         .DataSource(Components.ExternalUpdatesOnly)
                         .Build();

            using (var client = new LdClient(config))
            {
                Assert.True(client.Initialized);
            }
        }
Esempio n. 30
0
        public void LddModeClientHasDefaultEventProcessor()
        {
            var config = BasicConfig()
                         .DataSource(Components.ExternalUpdatesOnly)
                         .Events(null) // BasicConfig sets this to NoEvents, restore it to the default
                         .Build();

            using (var client = new LdClient(config))
            {
                Assert.IsType <DefaultEventProcessorWrapper> (client._eventProcessor);
            }
        }