public void VariationSendsFeatureEventForUnknownFlagWhenClientIsNotInitialized() { var config = BasicConfig() .DataSource(new MockDataSourceThatNeverInitializes().AsSingletonFactory()) .Events(_factory); using (LdClient client = TestUtil.CreateClient(config.Build(), user)) { string result = client.StringVariation("flag", "b"); Assert.Equal("b", result); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, user), e => { EvaluationEvent fe = Assert.IsType <EvaluationEvent>(e); Assert.Equal("flag", fe.FlagKey); Assert.Equal("b", fe.Value.AsString); Assert.Null(fe.Variation); Assert.Null(fe.FlagVersion); Assert.Equal("b", fe.Default.AsString); Assert.Null(fe.Reason); Assert.NotEqual(0, fe.Timestamp.Value); }); } }
public void VariationSendsFeatureEventWithReasonForUnknownFlagWhenClientIsNotInitialized() { var config = BasicConfig() .DataSource(new MockDataSourceThatNeverInitializes().AsSingletonFactory()) .Events(_factory); using (LdClient client = TestUtil.CreateClient(config.Build(), user)) { EvaluationDetail <string> result = client.StringVariationDetail("flag", "b"); var expectedReason = EvaluationReason.ErrorReason(EvaluationErrorKind.ClientNotReady); Assert.Equal("b", result.Value); Assert.Equal(expectedReason, result.Reason); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, user), e => { EvaluationEvent fe = Assert.IsType <EvaluationEvent>(e); Assert.Equal("flag", fe.FlagKey); Assert.Equal("b", fe.Value.AsString); Assert.Null(fe.Variation); Assert.Null(fe.FlagVersion); Assert.Equal("b", fe.Default.AsString); Assert.False(fe.TrackEvents); Assert.Null(fe.DebugEventsUntilDate); Assert.Equal(expectedReason, fe.Reason); Assert.NotEqual(0, fe.Timestamp.Value); }); } }
public void CanCreateClientWithInfiniteWaitTime() { var config = BasicConfig().Build(); using (var client = LdClient.Init(config, BasicUser, System.Threading.Timeout.InfiniteTimeSpan)) { } TestUtil.ClearClient(); }
public void VariationDetailSendsFeatureEventWithReasonForValidFlag() { var flag = new FeatureFlagBuilder().Value(LdValue.Of("a")).Variation(1).Version(1000) .TrackEvents(true).DebugEventsUntilDate(UnixMillisecondTime.OfMillis(2000)) .Reason(EvaluationReason.OffReason).Build(); _testData.Update(_testData.Flag("flag").PreconfiguredFlag(flag)); using (LdClient client = MakeClient(user)) { EvaluationDetail <string> result = client.StringVariationDetail("flag", "b"); Assert.Equal("a", result.Value); Assert.Equal(EvaluationReason.OffReason, result.Reason); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, user), e => { EvaluationEvent fe = Assert.IsType <EvaluationEvent>(e); Assert.Equal("flag", fe.FlagKey); Assert.Equal("a", fe.Value.AsString); Assert.Equal(1, fe.Variation); Assert.Equal(1000, fe.FlagVersion); Assert.Equal("b", fe.Default.AsString); Assert.True(fe.TrackEvents); Assert.Equal(UnixMillisecondTime.OfMillis(2000), fe.DebugEventsUntilDate); Assert.Equal(EvaluationReason.OffReason, fe.Reason); Assert.NotEqual(0, fe.Timestamp.Value); }); } }
private async Task IdentifyCompletesOnlyWhenNewFlagsAreAvailable(Func <LdClient, User, Task> identifyTask) { var userA = User.WithKey("a"); var userB = User.WithKey("b"); var flagKey = "flag"; var userAFlags = new DataSetBuilder() .Add(flagKey, 1, LdValue.Of("a-value"), 0).Build(); var userBFlags = new DataSetBuilder() .Add(flagKey, 2, LdValue.Of("b-value"), 1).Build(); var startedIdentifyUserB = new SemaphoreSlim(0, 1); var canFinishIdentifyUserB = new SemaphoreSlim(0, 1); var finishedIdentifyUserB = new SemaphoreSlim(0, 1); var dataSourceFactory = new MockDataSourceFactoryFromLambda((ctx, updates, user, bg) => new MockDataSourceFromLambda(user, async() => { switch (user.Key) { case "a": updates.Init(user, userAFlags); break; case "b": startedIdentifyUserB.Release(); await canFinishIdentifyUserB.WaitAsync(); updates.Init(user, userBFlags); break; } })); var config = BasicConfig() .DataSource(dataSourceFactory) .Build(); using (var client = await LdClient.InitAsync(config, userA)) { Assert.True(client.Initialized); Assert.Equal("a-value", client.StringVariation(flagKey, null)); var identifyUserBTask = Task.Run(async() => { await identifyTask(client, userB); finishedIdentifyUserB.Release(); }); await startedIdentifyUserB.WaitAsync(); Assert.False(client.Initialized); Assert.Null(client.StringVariation(flagKey, null)); canFinishIdentifyUserB.Release(); await finishedIdentifyUserB.WaitAsync(); Assert.True(client.Initialized); Assert.Equal("b-value", client.StringVariation(flagKey, null)); } }
// Calls LdClient.Init, but then sets LdClient.Instance to null so other tests can // instantiate their own independent clients. Application code cannot do this because // the LdClient.Instance setter has internal scope. public static async Task <LdClient> CreateClientAsync(Configuration config, User user) { return(await WithClientLockAsync(async() => { ClearClient(); LdClient client = await LdClient.InitAsync(config, user); client.DetachInstance(); return client; })); }
// Calls LdClient.Init, but then sets LdClient.Instance to null so other tests can // instantiate their own independent clients. Application code cannot do this because // the LdClient.Instance setter has internal scope. public static LdClient CreateClient(Configuration config, User user, TimeSpan?timeout = null) { return(WithClientLock(() => { ClearClient(); LdClient client = LdClient.Init(config, user, timeout ?? TimeSpan.FromSeconds(1)); client.DetachInstance(); return client; })); }
public void IdentifySendsIdentifyEvent() { using (LdClient client = MakeClient(user)) { User user1 = User.WithKey("userkey1"); client.Identify(user1, TimeSpan.FromSeconds(1)); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, user), // there's always an initial identify event e => CheckIdentifyEvent(e, user1)); } }
public void SharedClientIsTheOnlyClientAvailable() { TestUtil.WithClientLock(() => { var config = BasicConfig().Build(); using (var client = LdClient.Init(config, BasicUser, TimeSpan.Zero)) { Assert.Throws <Exception>(() => LdClient.Init(config, BasicUser, TimeSpan.Zero)); } TestUtil.ClearClient(); }); }
public void CanCreateNewClientAfterDisposingOfSharedInstance() { TestUtil.WithClientLock(() => { TestUtil.ClearClient(); var config = BasicConfig().Build(); using (var client0 = LdClient.Init(config, BasicUser, TimeSpan.Zero)) { } Assert.Null(LdClient.Instance); // Dispose() is called automatically at end of "using" block using (var client1 = LdClient.Init(config, BasicUser, TimeSpan.Zero)) { } }); }
static LdClient CreateInstance(Configuration configuration, User user, TimeSpan maxWaitTime) { lock (_createInstanceLock) { if (_instance != null) { throw new Exception("LdClient instance already exists."); } var c = new LdClient(configuration, user, maxWaitTime); _instance = c; return(c); } }
public async void InitPassesUserToDataSource() { MockPollingProcessor stub = new MockPollingProcessor(DataSetBuilder.Empty); var config = BasicConfig() .DataSource(stub.AsFactory()) .Build(); using (var client = await LdClient.InitAsync(config, BasicUser)) { var actualUser = client.User; // may have been transformed e.g. to add device/OS properties Assert.Equal(BasicUser.Key, actualUser.Key); Assert.Equal(actualUser, stub.ReceivedUser); } }
public void IdentifyDoesNotSendAliasEventIfNewUserIsAnonymousOrOldUserIsNot( bool oldAnon, bool newAnon) { User oldUser = User.Builder("old-key").Anonymous(oldAnon).Build(); User newUser = User.Builder("new-key").Anonymous(newAnon).Build(); using (LdClient client = MakeClient(oldUser)) { client.Identify(newUser, TimeSpan.FromSeconds(1)); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, oldUser), e => CheckIdentifyEvent(e, newUser)); } }
public async void InitWithKeylessAnonUserPassesGeneratedUserToDataSource() { MockPollingProcessor stub = new MockPollingProcessor(DataSetBuilder.Empty); var config = BasicConfig() .DataSource(stub.AsFactory()) .Build(); using (var client = await LdClient.InitAsync(config, KeylessAnonUser)) { AssertHelpers.UsersEqualExcludingAutoProperties( User.Builder(KeylessAnonUser).Key(stub.ReceivedUser.Key).Build(), stub.ReceivedUser); } }
public void TrackSendsCustomEvent() { using (LdClient client = MakeClient(user)) { client.Track("eventkey"); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, user), e => { CustomEvent ce = Assert.IsType <CustomEvent>(e); Assert.Equal("eventkey", ce.EventKey); Assert.Equal(user.Key, ce.User.Key); Assert.Equal(LdValue.Null, ce.Data); Assert.Null(ce.MetricValue); Assert.NotEqual(0, ce.Timestamp.Value); }); } }
public void AliasSendsAliasEvent() { User oldUser = User.Builder("anon-key").Anonymous(true).Build(); User newUser = User.WithKey("real-key"); using (LdClient client = MakeClient(user)) { client.Alias(user, oldUser); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, user), e => { AliasEvent ae = Assert.IsType <AliasEvent>(e); Assert.Equal(user, ae.User); Assert.Equal(oldUser, ae.PreviousUser); Assert.NotEqual(0, ae.Timestamp.Value); }); } }
public void TrackWithMetricValueSendsCustomEvent() { using (LdClient client = MakeClient(user)) { LdValue data = LdValue.Of("hi"); double metricValue = 1.5; client.Track("eventkey", data, metricValue); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, user), e => { CustomEvent ce = Assert.IsType <CustomEvent>(e); Assert.Equal("eventkey", ce.EventKey); Assert.Equal(user.Key, ce.User.Key); Assert.Equal(data, ce.Data); Assert.Equal(metricValue, ce.MetricValue); Assert.NotEqual(0, ce.Timestamp.Value); }); } }
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 async void IdentifyPassesUserToDataSource() { MockPollingProcessor stub = new MockPollingProcessor(DataSetBuilder.Empty); User newUser = User.WithKey("new-user"); var config = BasicConfig() .DataSource(stub.AsFactory()) .Build(); using (var client = await LdClient.InitAsync(config, BasicUser)) { AssertHelpers.UsersEqualExcludingAutoProperties(BasicUser, client.User); Assert.Equal(client.User, stub.ReceivedUser); await client.IdentifyAsync(newUser); AssertHelpers.UsersEqualExcludingAutoProperties(newUser, client.User); Assert.Equal(client.User, stub.ReceivedUser); } }
public void VariationSendsFeatureEventForUnknownFlag() { using (LdClient client = MakeClient(user)) { string result = client.StringVariation("flag", "b"); Assert.Equal("b", result); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, user), e => { EvaluationEvent fe = Assert.IsType <EvaluationEvent>(e); Assert.Equal("flag", fe.FlagKey); Assert.Equal("b", fe.Value.AsString); Assert.Null(fe.Variation); Assert.Null(fe.FlagVersion); Assert.Equal("b", fe.Default.AsString); Assert.Null(fe.Reason); Assert.NotEqual(0, fe.Timestamp.Value); }); } }
public void IdentifySendsAliasEventFromAnonUserToNonAnonUserIfNotOptedOut() { User oldUser = User.Builder("anon-key").Anonymous(true).Build(); User newUser = User.WithKey("real-key"); using (LdClient client = MakeClient(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), e => { AliasEvent ae = Assert.IsType <AliasEvent>(e); Assert.Equal(newUser, ae.User); Assert.Equal(actualOldUser, ae.PreviousUser); Assert.NotEqual(0, ae.Timestamp.Value); }); } }
public void VariationSendsFeatureEventForDefaultValue() { var flag = new FeatureFlagBuilder().Version(1000).Build(); _testData.Update(_testData.Flag("flag").PreconfiguredFlag(flag)); using (LdClient client = MakeClient(user)) { string result = client.StringVariation("flag", "b"); Assert.Equal("b", result); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, user), e => { EvaluationEvent fe = Assert.IsType <EvaluationEvent>(e); Assert.Equal("flag", fe.FlagKey); Assert.Equal("b", fe.Value.AsString); Assert.Null(fe.Variation); Assert.Equal(1000, fe.FlagVersion); Assert.Equal("b", fe.Default.AsString); Assert.Null(fe.Reason); Assert.NotEqual(0, fe.Timestamp.Value); }); } }
public void VariationDetailSendsFeatureEventWithReasonForUnknownFlag() { using (LdClient client = MakeClient(user)) { EvaluationDetail <string> result = client.StringVariationDetail("flag", "b"); var expectedReason = EvaluationReason.ErrorReason(EvaluationErrorKind.FlagNotFound); Assert.Equal("b", result.Value); Assert.Equal(expectedReason, result.Reason); Assert.Collection(eventProcessor.Events, e => CheckIdentifyEvent(e, user), e => { EvaluationEvent fe = Assert.IsType <EvaluationEvent>(e); Assert.Equal("flag", fe.FlagKey); Assert.Equal("b", fe.Value.AsString); Assert.Null(fe.Variation); Assert.Null(fe.FlagVersion); Assert.Equal("b", fe.Default.AsString); Assert.False(fe.TrackEvents); Assert.Null(fe.DebugEventsUntilDate); Assert.Equal(expectedReason, fe.Reason); Assert.NotEqual(0, fe.Timestamp.Value); }); } }
private LdClient MakeClient(User u) => LdClient.Init(BasicConfig().DataSource(_testData).Events(_factory).Build(), u, TimeSpan.FromSeconds(1));
public void CannotCreateClientWithNegativeWaitTime() { var config = BasicConfig().Build(); Assert.Throws <ArgumentOutOfRangeException>(() => LdClient.Init(config, BasicUser, TimeSpan.FromMilliseconds(-2))); }
public void CannotCreateClientWithNullUser() { var config = BasicConfig().Build(); Assert.Throws <ArgumentNullException>(() => LdClient.Init(config, null, TimeSpan.Zero)); }
public void CannotCreateClientWithNullConfig() { Assert.Throws <ArgumentNullException>(() => LdClient.Init((Configuration)null, BasicUser, TimeSpan.Zero)); }