public void PingCausesPoll() { var data = new DataSetBuilder() .Add("flag1", 1, LdValue.Of(true), 0) .Build(); var streamWithPing = Handlers.SSE.Start() .Then(PingEvent) .Then(Handlers.SSE.LeaveOpen()); using (var pollingServer = HttpServer.Start(PollingResponse(data))) { using (var streamingServer = HttpServer.Start(streamWithPing)) { using (var dataSource = MakeDataSource(streamingServer.Uri, BasicUser, c => c.ServiceEndpoints(Components.ServiceEndpoints() .Streaming(streamingServer.Uri).Polling(pollingServer.Uri)))) { var initTask = dataSource.Start(); pollingServer.Recorder.RequireRequest(); var receivedData = _updateSink.ExpectInit(BasicUser); AssertHelpers.DataSetsEqual(data, receivedData); Assert.True(AsyncUtils.WaitSafely(() => initTask, TimeSpan.FromSeconds(1))); Assert.False(initTask.IsFaulted); Assert.True(dataSource.Initialized); } } } }
public void InitIsNotRepeatedIfServerReturnsNotModifiedStatus() { var etag = @"""abc123"""; // note that etag strings must be quoted var responses = Handlers.SequentialWithLastRepeating( Handlers.Header("Etag", etag).Then(PollingResponse(AllData)), Handlers.Status(304) ); using (var server = HttpServer.Start(responses)) { using (var dataSource = MakeDataSource(server.Uri, BasicUser, c => c.DataSource(Components.PollingDataSource().PollIntervalNoMinimum(BriefInterval)))) { dataSource.Start(); var receivedData = _updateSink.ExpectInit(BasicUser); AssertHelpers.DataSetsEqual(AllData, receivedData); // We've set it up above so that all requests except the first one return a 304 // status, so the data source should *not* push a new data set with Init. _updateSink.ExpectNoMoreActions(); var req1 = server.Recorder.RequireRequest(); var req2 = server.Recorder.RequireRequest(); var req3 = server.Recorder.RequireRequest(); Assert.Null(req1.Headers.Get("If-None-Match")); Assert.Equal(etag, req2.Headers.Get("If-None-Match")); Assert.Equal(etag, req3.Headers.Get("If-None-Match")); } } }
public void GetAllWhenNotInitialized() { var data = _store.GetAll(); Assert.NotNull(data); AssertHelpers.DataSetsEqual(DataSetBuilder.Empty, data.Value); }
public void UpsertUpdatesPersistentStore() { var flag1a = new FeatureFlagBuilder().Version(1).Value(true).Build(); var flag1b = new FeatureFlagBuilder().Version(2).Value(true).Build(); var flag2 = new FeatureFlagBuilder().Version(1).Value(false).Build(); var data1a = new DataSetBuilder().Add("flag1", flag1a).Add("flag2", flag2).Build(); var data1b = new DataSetBuilder().Add("flag1", flag1b).Add("flag2", flag2).Build(); var store = MakeStore(1); store.Init(BasicUser, data1a, true); var updated = store.Upsert("flag1", flag1b.ToItemDescriptor()); Assert.True(updated); var item = store.Get("flag1"); // this is reading only from memory, not the persistent store Assert.Equal(flag1b.ToItemDescriptor(), item); var data = _persistentStore.InspectUserData(BasicMobileKey, BasicUser.Key); Assert.NotNull(data); AssertHelpers.DataSetsEqual(data1b, data.Value); }
public void GetAllWithEmptyFlags() { _store.Init(BasicUser, DataSetBuilder.Empty, false); var data = _store.GetAll(); Assert.NotNull(data); AssertHelpers.DataSetsEqual(DataSetBuilder.Empty, data.Value); }
public void InitWritesToPersistentStoreIfToldTo() { var store = MakeStore(1); store.Init(BasicUser, DataSet1, true); var data = _persistentStore.InspectUserData(BasicMobileKey, BasicUser.Key); Assert.NotNull(data); AssertHelpers.DataSetsEqual(DataSet1, data.Value); }
public void GetCachedDataForKnownUser() { _persistentStore.SetupUserData(BasicMobileKey, BasicUser.Key, DataSet1); _persistentStore.SetupUserData(BasicMobileKey, OtherUser.Key, DataSet2); var store = MakeStore(1); var data = store.GetCachedData(BasicUser); Assert.NotNull(data); AssertHelpers.DataSetsEqual(DataSet1, data.Value); }
public void GetUserDataForKnownUserWithValidData() { var expectedData = new DataSetBuilder().Add("flagkey", 1, LdValue.Of(true), 0).Build(); var serializedData = expectedData.ToJsonString(); _persistentStore.SetValue(ExpectedEnvironmentNamespace, ExpectedUserFlagsKey, serializedData); var data = _wrapper.GetUserData(UserHash); Assert.NotNull(data); AssertHelpers.DataSetsEqual(expectedData, data.Value); Assert.Empty(logCapture.GetMessages()); }
public void GetAllReturnsFlags() { var initData = new DataSetBuilder() .Add("flag1", 1, LdValue.Of(true), 0) .Add("flag2", 2, LdValue.Of(false), 1) .Build(); _store.Init(BasicUser, initData, false); var data = _store.GetAll(); Assert.NotNull(data); AssertHelpers.DataSetsEqual(initData, data.Value); }
public void SuccessfulRequestPutsFeatureDataInStore() { var expectedData = MakeAllData(); _mockFeatureRequestor.Setup(fr => fr.GetAllDataAsync()).ReturnsAsync(expectedData); using (PollingProcessor pp = MakeProcessor()) { var initTask = pp.Start(); initTask.Wait(); var receivedData = _updates.Inits.ExpectValue(); AssertHelpers.DataSetsEqual(expectedData, receivedData); } }
public void PutCausesDataToBeStoredAndDataSourceInitialized() { var data = new DataSetBuilder() .Add("flag1", 1, LdValue.Of(true), 0) .Build(); WithDataSourceAndServer(StreamWithInitialData(data), (dataSource, _, initTask) => { var receivedData = _updateSink.ExpectInit(BasicUser); AssertHelpers.DataSetsEqual(data, receivedData); Assert.True(AsyncUtils.WaitSafely(() => initTask, TimeSpan.FromSeconds(1))); Assert.False(initTask.IsFaulted); Assert.True(dataSource.Initialized); }); }
public void ResponseWithNewEtagUpdatesEtag() { var etag1 = @"""abc123"""; // note that etag strings must be quoted var etag2 = @"""def456"""; var data1 = AllData; var data2 = new DataSetBuilder().Add("flag2", new FeatureFlagBuilder().Build()).Build(); var data3 = new DataSetBuilder().Add("flag3", new FeatureFlagBuilder().Build()).Build(); var responses = Handlers.SequentialWithLastRepeating( Handlers.Header("Etag", etag1).Then(PollingResponse(data1)), Handlers.Status(304), Handlers.Header("Etag", etag2).Then(PollingResponse(data2)), Handlers.Status(304), PollingResponse(data3) // no etag - even though the server will normally send one ); using (var server = HttpServer.Start(responses)) { using (var dataSource = MakeDataSource(server.Uri, BasicUser, c => c.DataSource(Components.PollingDataSource().PollIntervalNoMinimum(BriefInterval)))) { dataSource.Start(); var receivedData1 = _updateSink.ExpectInit(BasicUser); AssertHelpers.DataSetsEqual(data1, receivedData1); var receivedData2 = _updateSink.ExpectInit(BasicUser); AssertHelpers.DataSetsEqual(data2, receivedData2); var receivedData3 = _updateSink.ExpectInit(BasicUser); AssertHelpers.DataSetsEqual(data3, receivedData3); var req1 = server.Recorder.RequireRequest(); var req2 = server.Recorder.RequireRequest(); var req3 = server.Recorder.RequireRequest(); var req4 = server.Recorder.RequireRequest(); var req5 = server.Recorder.RequireRequest(); var req6 = server.Recorder.RequireRequest(); Assert.Null(req1.Headers.Get("If-None-Match")); Assert.Equal(etag1, req2.Headers.Get("If-None-Match")); Assert.Equal(etag1, req3.Headers.Get("If-None-Match")); Assert.Equal(etag2, req4.Headers.Get("If-None-Match")); // etag was updated by 3rd response Assert.Equal(etag2, req5.Headers.Get("If-None-Match")); // etag was updated by 3rd response Assert.Null(req6.Headers.Get("If-None-Match")); // etag was cleared by 5th response } } }
public void SuccessfulRequestCausesDataToBeStoredAndDataSourceInitialized() { using (var server = HttpServer.Start(PollingResponse(AllData))) { using (var dataSource = MakeDataSource(server.Uri, BasicUser)) { var initTask = dataSource.Start(); var receivedData = _updateSink.ExpectInit(BasicUser); AssertHelpers.DataSetsEqual(AllData, receivedData); Assert.True(AsyncUtils.WaitSafely(() => initTask, TimeSpan.FromSeconds(1))); Assert.False(initTask.IsFaulted); Assert.True(dataSource.Initialized); } } }
public async Task GetAllParsesResponseAsync() { var resp = Handlers.BodyJson(AllDataJson); using (var server = HttpServer.Start(resp)) { using (var requestor = MakeRequestor(server)) { var result = await requestor.GetAllDataAsync(); var req = server.Recorder.RequireRequest(); Assert.Equal("/sdk/latest-all", req.Path); var expectedData = new DataSetBuilder().Flags(flag1).Segments(segment1).Build(); AssertHelpers.DataSetsEqual(expectedData, result.Value); } } }
public async Task GetAllUsesCorrectUriAndParsesResponseAsync() { using (var server = await TestHttpUtils.StartServerAsync()) { server.Given(Request.Create().UsingGet()) .RespondWith(Response.Create().WithStatusCode(200).WithBody(AllDataJson)); using (var requestor = MakeRequestor(server)) { var result = await requestor.GetAllDataAsync(); var req = GetLastRequest(server); Assert.Equal("/sdk/latest-all", req.Path); var expectedData = new DataSetBuilder().Flags(flag1).Segments(segment1).Build(); AssertHelpers.DataSetsEqual(expectedData, result.Value); } } }
public void GetAllDoesNotReadFromPersistentStore() { var flag1 = new FeatureFlagBuilder().Version(1).Value(true).Build(); var flag2 = new FeatureFlagBuilder().Version(2).Value(false).Build(); var data1 = new DataSetBuilder().Add("flag1", flag1).Build(); var data2 = new DataSetBuilder().Add("flag2", flag2).Build(); var store = MakeStore(1); store.Init(BasicUser, data1, true); // Hack the underlying store to change the data so we can verify it isn't being reread _persistentStore.SetupUserData(BasicMobileKey, BasicUser.Key, data2); var data = store.GetAll(); Assert.NotNull(data); AssertHelpers.DataSetsEqual(data1, data.Value); }
public void InitDoesNotWriteToPersistentStoreIfToldNotTo() { _persistentStore.SetupUserData(BasicMobileKey, BasicUser.Key, DataSet1); var store = MakeStore(1); var data = store.GetCachedData(BasicUser); Assert.NotNull(data); AssertHelpers.DataSetsEqual(DataSet1, data.Value); // Hack the underlying store to remove the data so we can tell if it gets rewritten _persistentStore.SetupUserData(BasicMobileKey, BasicUser.Key, DataSetBuilder.Empty); store.Init(BasicUser, data.Value, false); // Because we passed false in Init, it does not rewrite the data - this behavior is to // avoid unnecessary writes on startup when we've just read the data from the cache. var underlyingData = _persistentStore.InspectUserData(BasicMobileKey, BasicUser.Key); Assert.NotNull(underlyingData); AssertHelpers.DataSetsEqual(DataSetBuilder.Empty, underlyingData.Value); }
public void ParsePutData() { var allDataJson = @"{ ""flags"": { ""flag1"": { ""key"": ""flag1"", ""version"": 1}, ""flag2"": { ""key"": ""flag2"", ""version"": 2} }, ""segments"": { ""segment1"": {""key"": ""segment1"",""version"": 3} } }"; var expectedAllData = new DataSetBuilder() .Flags(new FeatureFlagBuilder("flag1").Version(1).Build(), new FeatureFlagBuilder("flag2").Version(2).Build()) .Segments(new SegmentBuilder("segment1").Version(3).Build()) .Build(); var validInput = @"{""path"": ""/"", ""data"": " + allDataJson + "}"; var validResult = StreamProcessorEvents.ParsePutData(Utf8Bytes(validInput)); Assert.Equal("/", validResult.Path); AssertHelpers.DataSetsEqual(expectedAllData, validResult.Data); var inputWithoutPath = @"{""data"": " + allDataJson + "}"; var resultWithoutPath = StreamProcessorEvents.ParsePutData(Utf8Bytes(inputWithoutPath)); Assert.Null(resultWithoutPath.Path); // we don't consider this an error; some versions of Relay don't send a path AssertHelpers.DataSetsEqual(expectedAllData, resultWithoutPath.Data); var inputWithoutData = @"{""path"": ""/""}"; Assert.ThrowsAny <JsonReadException>(() => StreamProcessorEvents.ParsePutData(Utf8Bytes(inputWithoutData))); var malformedJsonInput = @"{no"; Assert.ThrowsAny <JsonReadException>(() => StreamProcessorEvents.ParsePutData(Utf8Bytes(malformedJsonInput))); }