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"); } }
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); } }
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); } }
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); } } }
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); } }
public void OfflineClientHasNullEventProcessor() { var config = BasicConfig().Offline(true).Build(); using (var client = new LdClient(config)) { Assert.IsType <ComponentsImpl.NullEventProcessor>(client._eventProcessor); } }
public void OfflineClientIsInitialized() { var config = BasicConfig().Offline(true).Build(); using (var client = new LdClient(config)) { Assert.True(client.Initialized); } }
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")); } }
public void DataStoreStatusMonitoringIsDisabledForInMemoryDataStore() { var config = BasicConfig().Build(); using (var client = new LdClient(config)) { Assert.False(client.DataStoreStatusProvider.StatusMonitoringEnabled); } }
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"); } }
public void OfflineClientHasNullDataSource() { var config = BasicConfig().Offline(true).Build(); using (var client = new LdClient(config)) { Assert.IsType <ComponentsImpl.NullDataSource>(client._dataSource); } }
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); } }
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); } }
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")); } }
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); } }
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"))); } }
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)); } }
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()); } }
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"))); } }
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); } }
public void LddModeClientHasNullDataSource() { var config = BasicConfig() .DataSource(Components.ExternalUpdatesOnly) .Build(); using (var client = new LdClient(config)) { Assert.IsType <ComponentsImpl.NullDataSource>(client._dataSource); } }
public void LddModeClientIsInitialized() { var config = BasicConfig() .DataSource(Components.ExternalUpdatesOnly) .Build(); using (var client = new LdClient(config)) { Assert.True(client.Initialized); } }
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); } }