public async Task InitWithKeylessAnonUserGeneratesRandomizedIdOnNonMobilePlatforms() { var config = BasicConfig() .Persistence(Components.Persistence().Storage(new MockPersistentDataStore().AsSingletonFactory())) .Build(); string generatedKey = null; using (var client = await TestUtil.CreateClientAsync(config, KeylessAnonUser)) { generatedKey = client.User.Key; Assert.NotNull(generatedKey); AssertHelpers.UsersEqualExcludingAutoProperties( User.Builder(KeylessAnonUser).Key(client.User.Key).Build(), client.User); } using (var client = await TestUtil.CreateClientAsync(config, KeylessAnonUser)) { Assert.Equal(generatedKey, client.User.Key); } // Now use a configuration where persistence is disabled - a different key is generated var configWithoutPersistence = BasicConfig().Persistence(Components.NoPersistence).Build(); using (var client = await TestUtil.CreateClientAsync(configWithoutPersistence, KeylessAnonUser)) { Assert.NotNull(client.User.Key); Assert.NotEqual(generatedKey, client.User.Key); } }
public async Task IdentifySwitchesUserAndGetsFlagsAsync(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 = await TestUtil.CreateClientAsync(config, _user)) { var req1 = VerifyRequest(server.Recorder, mode); VerifyFlagValues(client, _flagData1); var user1RequestPath = req1.Path; switchable.Target = SetupResponse(_flagData2, mode); var success = await client.IdentifyAsync(_otherUser); Assert.True(success); Assert.True(client.Initialized); Assert.Equal(_otherUser.Key, client.User.Key); // don't compare entire user, because SDK may have added device/os attributes var req2 = VerifyRequest(server.Recorder, mode); Assert.NotEqual(user1RequestPath, req2.Path); VerifyFlagValues(client, _flagData2); } } }
public async Task InitGetsFlagsAsync(UpdateMode mode) { using (var server = HttpServer.Start(SetupResponse(_flagData1, mode))) { var config = BaseConfig(server.Uri, mode); using (var client = await TestUtil.CreateClientAsync(config, _user)) { VerifyRequest(server.Recorder, mode); } } }
public async Task InitWithKeylessAnonUserAddsKey() { // Note, we don't care about polling mode vs. streaming mode for this functionality. var mockDeviceInfo = new MockDeviceInfo("fake-device-id"); var config = BasicConfig().DeviceInfo(mockDeviceInfo).Persistence(Components.NoPersistence).Build(); using (var client = await TestUtil.CreateClientAsync(config, KeylessAnonUser)) { Assert.Equal("fake-device-id", client.User.Key); AssertHelpers.UsersEqualExcludingAutoProperties( User.Builder(KeylessAnonUser).Key(client.User.Key).Build(), client.User); } }
public async Task IdentifyWithKeylessAnonUserAddsKey() { var mockDeviceInfo = new MockDeviceInfo("fake-device-id"); var config = BasicConfig().DeviceInfo(mockDeviceInfo).Persistence(Components.NoPersistence).Build(); using (var client = await TestUtil.CreateClientAsync(config, BasicUser)) { await client.IdentifyAsync(KeylessAnonUser); Assert.Equal("fake-device-id", client.User.Key); AssertHelpers.UsersEqualExcludingAutoProperties( User.Builder(KeylessAnonUser).Key(client.User.Key).Build(), client.User); } }
public async Task InitFailsOn401Async(UpdateMode mode) { using (var server = HttpServer.Start(Handlers.Status(401))) { var config = BaseConfig(server.Uri, mode); // Currently the behavior of LdClient.InitAsync is somewhat inconsistent with LdClient.Init if there is // an unrecoverable error: LdClient.Init throws an exception, but LdClient.InitAsync returns a task that // will complete successfully with an uninitialized client. using (var client = await TestUtil.CreateClientAsync(config, _user)) { Assert.False(client.Initialized); } } }
public async Task OfflineClientGoesOnlineAndGetsFlagsAsync(UpdateMode mode) { using (var server = HttpServer.Start(SetupResponse(_flagData1, mode))) { var config = BaseConfig(server.Uri, mode, builder => builder.Offline(true)); using (var client = await TestUtil.CreateClientAsync(config, _user)) { VerifyNoFlagValues(client, _flagData1); Assert.Equal(0, server.Recorder.Count); await client.SetOfflineAsync(false); VerifyFlagValues(client, _flagData1); } } }
public async Task BackgroundModePollingCanBeDisabledAsync() { var mockBackgroundModeManager = new MockBackgroundModeManager(); var backgroundInterval = TimeSpan.FromMilliseconds(50); var hackyUpdateDelay = TimeSpan.FromMilliseconds(200); using (var server = HttpServer.Start(Handlers.Switchable(out var switchable))) { switchable.Target = SetupResponse(_flagData1, UpdateMode.Streaming); var config = BaseConfig(builder => builder .BackgroundModeManager(mockBackgroundModeManager) .EnableBackgroundUpdating(false) .DataSource(Components.StreamingDataSource().BackgroundPollInterval(backgroundInterval)) .ServiceEndpoints(Components.ServiceEndpoints().Streaming(server.Uri).Polling(server.Uri)) ); using (var client = await TestUtil.CreateClientAsync(config, _user)) { VerifyFlagValues(client, _flagData1); // The SDK should *not* hit this polling endpoint, but we're providing some data there so we can // detect whether it does. switchable.Target = SetupResponse(_flagData2, UpdateMode.Polling); mockBackgroundModeManager.UpdateBackgroundMode(true); await Task.Delay(hackyUpdateDelay); VerifyFlagValues(client, _flagData1); // we should *not* have done a poll var receivedChangeSignal = new SemaphoreSlim(0, 1); client.FlagTracker.FlagValueChanged += (sender, args) => { receivedChangeSignal.Release(); }; // Now switch back to streaming switchable.Target = SetupResponse(_flagData2, UpdateMode.Streaming); mockBackgroundModeManager.UpdateBackgroundMode(false); Assert.True(await receivedChangeSignal.WaitAsync(TimeSpan.FromSeconds(5))); VerifyFlagValues(client, _flagData2); } } }
public async Task BackgroundModeForcesPollingAsync() { var mockBackgroundModeManager = new MockBackgroundModeManager(); var backgroundInterval = TimeSpan.FromMilliseconds(50); using (var server = HttpServer.Start(Handlers.Switchable(out var switchable))) { switchable.Target = SetupResponse(_flagData1, UpdateMode.Streaming); var config = BaseConfig(builder => builder .BackgroundModeManager(mockBackgroundModeManager) .DataSource(Components.StreamingDataSource().BackgroundPollingIntervalWithoutMinimum(backgroundInterval)) .ServiceEndpoints(Components.ServiceEndpoints().Streaming(server.Uri).Polling(server.Uri)) ); using (var client = await TestUtil.CreateClientAsync(config, _user)) { VerifyFlagValues(client, _flagData1); // Set it up so that when the client switches to background mode and does a polling request, it will // receive _flagData2, and we will be notified of that via a change event. SetupResponse will only // configure the polling endpoint, so if the client makes a streaming request here it'll fail. switchable.Target = SetupResponse(_flagData2, UpdateMode.Polling); var receivedChangeSignal = new SemaphoreSlim(0, 1); client.FlagTracker.FlagValueChanged += (sender, args) => { receivedChangeSignal.Release(); }; mockBackgroundModeManager.UpdateBackgroundMode(true); Assert.True(await receivedChangeSignal.WaitAsync(TimeSpan.FromSeconds(5))); VerifyFlagValues(client, _flagData2); // Now switch back to streaming switchable.Target = SetupResponse(_flagData1, UpdateMode.Streaming); mockBackgroundModeManager.UpdateBackgroundMode(false); Assert.True(await receivedChangeSignal.WaitAsync(TimeSpan.FromSeconds(5))); VerifyFlagValues(client, _flagData1); } } }
public async Task InitWithKeylessAnonUserUsesStableDeviceIDOnMobilePlatforms() { var config = BasicConfig().Persistence(Components.NoPersistence).Build(); string generatedKey = null; using (var client = await TestUtil.CreateClientAsync(config, KeylessAnonUser)) { generatedKey = client.User.Key; Assert.NotNull(generatedKey); AssertHelpers.UsersEqualExcludingAutoProperties( User.Builder(KeylessAnonUser).Key(client.User.Key).Build(), client.User); } using (var client = await TestUtil.CreateClientAsync(config, KeylessAnonUser)) { Assert.Equal(generatedKey, client.User.Key); } }
public async Task OfflineClientUsesCachedFlagsAsync() { 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 = await TestUtil.CreateClientAsync(config, _user)) { VerifyFlagValues(client, _flagData1); } // At this point the SDK should have written the flags to persistent storage for this user key. var offlineConfig = BasicConfig().Offline(true).Persistence(sharedPersistenceConfig).Build(); using (var client = await TestUtil.CreateClientAsync(offlineConfig, _user)) { VerifyFlagValues(client, _flagData1); } } }