public void TwoFeatureEventsForSameUserGenerateOnlyOneIndexEvent() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { var flag1 = new TestFlagProperties { Key = "flagkey1", Version = 11, TrackEvents = true }; var flag2 = new TestFlagProperties { Key = "flagkey2", Version = 22, TrackEvents = true }; var value = LdValue.Of("value"); RecordEval(ep, flag1, BasicEval); RecordEval(ep, flag2, BasicEval); ep.Flush(); ep.WaitUntilInactive(); Assert.Collection(captured.Events, item => CheckIndexEvent(item, BasicEval.Timestamp, _userJson), item => CheckFeatureEvent(item, flag1, BasicEval, LdValue.Null), item => CheckFeatureEvent(item, flag2, BasicEval, LdValue.Null), item => CheckSummaryEvent(item)); } }
public void EventsInBatchRecorded() { var expectedStats = LdValue.BuildObject().Add("stats", "testValue").Build(); var mockDiagnosticStore = MakeDiagnosticStore(null, null, new DiagnosticEvent(expectedStats)); var mockSender = MakeMockSender(); var eventCapture = EventCapture.From(mockSender); var diagnosticCapture = EventCapture.DiagnosticsFrom(mockSender); CountdownEvent diagnosticCountdown = new CountdownEvent(1); using (var ep = MakeProcessor(_config, mockSender, mockDiagnosticStore.Object, null, diagnosticCountdown)) { RecordEval(ep, BasicFlagWithTracking, BasicEval); FlushAndWait(ep); mockDiagnosticStore.Verify(diagStore => diagStore.RecordEventsInBatch(2), Times.Once(), "Diagnostic store's RecordEventsInBatch should be called with the number of events in last flush"); ep.DoDiagnosticSend(null); diagnosticCountdown.Wait(); mockDiagnosticStore.Verify(diagStore => diagStore.CreateEventAndReset(), Times.Once()); Assert.Equal(expectedStats, diagnosticCapture.EventsQueue.Take()); } }
public void DebugModeExpiresBasedOnServerTimeIfServerTimeIsLaterThanClientTime() { // Pick a server time that is somewhat ahead of the client time var serverTime = DateTime.Now.Add(TimeSpan.FromSeconds(20)); var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender, new EventSenderResult(DeliveryStatus.Succeeded, serverTime)); using (var ep = MakeProcessor(_config, mockSender)) { // Send and flush an event we don't care about, just to set the last server time RecordIdentify(ep, _fixedTimestamp, User.WithKey("otherUser")); FlushAndWait(ep); captured.Events.Clear(); // Now send an event with debug mode on, with a "debug until" time that is further in // the future than the client time, but in the past compared to the server. var flag = BasicFlag; flag.DebugEventsUntilDate = UnixMillisecondTime.FromDateTime(serverTime).PlusMillis(-1000); RecordEval(ep, flag, BasicEval); FlushAndWait(ep); // Should get a summary event only, not a full feature event Assert.Collection(captured.Events, item => CheckIndexEvent(item, BasicEval.Timestamp, _userJson), item => CheckSummaryEvent(item)); } }
public void FeatureEventCanHaveReason() { _config.InlineUsersInEvents = true; var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { var reasons = new EvaluationReason[] { _irrelevantReason, EvaluationReason.FallthroughReason, EvaluationReason.TargetMatchReason, EvaluationReason.RuleMatchReason(1, "id"), EvaluationReason.PrerequisiteFailedReason("key"), EvaluationReason.ErrorReason(EvaluationErrorKind.WrongType) }; foreach (var reason in reasons) { captured.Events.Clear(); var eval = BasicEval; eval.Reason = reason; RecordEval(ep, BasicFlagWithTracking, eval); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckFeatureEvent(item, BasicFlagWithTracking, eval, _userJson), item => CheckSummaryEvent(item)); } } }
public void FlushDoesNothingIfThereAreNoEvents() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { ep.Flush(); ep.WaitUntilInactive(); Assert.Empty(captured.Events); } }
public void IdentifyEventCanHaveNullUser() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { RecordIdentify(ep, _fixedTimestamp, null); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckIdentifyEvent(item, _fixedTimestamp, LdValue.Null)); } }
public void UserDetailsAreScrubbedInIdentifyEvent() { _config.AllAttributesPrivate = true; var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { RecordIdentify(ep, _fixedTimestamp, _user); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckIdentifyEvent(item, _fixedTimestamp, _scrubbedUserJson)); } }
public void IndividualFeatureEventIsQueuedWithIndexEvent() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { RecordEval(ep, BasicFlagWithTracking, BasicEval); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckIndexEvent(item, BasicEval.Timestamp, _userJson), item => CheckFeatureEvent(item, BasicFlagWithTracking, BasicEval, LdValue.Null), item => CheckSummaryEvent(item)); } }
public void FinalFlushIsDoneOnDispose() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { RecordIdentify(ep, _fixedTimestamp, _user); ep.Dispose(); Assert.Collection(captured.Events, item => CheckIdentifyEvent(item, _fixedTimestamp, _userJson)); mockSender.Verify(s => s.Dispose(), Times.Once()); } }
public void FeatureEventCanHaveNullUser() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { var eval = BasicEval; eval.User = null; RecordEval(ep, BasicFlagWithTracking, eval); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckFeatureEvent(item, BasicFlagWithTracking, eval, LdValue.Null), item => CheckSummaryEvent(item)); } }
public void CustomEventCanHaveNullUser() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { var ce = BasicCustom; ce.User = null; RecordCustom(ep, ce); ep.Flush(); ep.WaitUntilInactive(); Assert.Collection(captured.Events, item => CheckCustomEvent(item, ce, LdValue.Null)); } }
public void CustomEventCanContainInlineUser() { _config.InlineUsersInEvents = true; var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { RecordCustom(ep, BasicCustom); ep.Flush(); ep.WaitUntilInactive(); Assert.Collection(captured.Events, item => CheckCustomEvent(item, BasicCustom, _userJson)); } }
public void FeatureEventCanContainInlineUser() { _config.InlineUsersInEvents = true; var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { RecordEval(ep, BasicFlagWithTracking, BasicEval); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckFeatureEvent(item, BasicFlagWithTracking, BasicEval, _userJson), item => CheckSummaryEvent(item)); } }
public void IndexEventIsStillGeneratedIfInlineUsersIsTrueButFeatureEventIsNotTracked() { _config.InlineUsersInEvents = true; var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { RecordEval(ep, BasicFlag, BasicEval); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckIndexEvent(item, BasicEval.Timestamp, _userJson), item => CheckSummaryEvent(item)); } }
public void UserDetailsAreScrubbedInFeatureEvent() { _config.AllAttributesPrivate = true; _config.InlineUsersInEvents = true; var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { RecordEval(ep, BasicFlagWithTracking, BasicEval); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckFeatureEvent(item, BasicFlagWithTracking, BasicEval, _scrubbedUserJson), item => CheckSummaryEvent(item)); } }
public void UserDetailsAreScrubbedInCustomEvent() { _config.AllAttributesPrivate = true; _config.InlineUsersInEvents = true; var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { RecordCustom(ep, BasicCustom); ep.Flush(); ep.WaitUntilInactive(); Assert.Collection(captured.Events, item => CheckCustomEvent(item, BasicCustom, _scrubbedUserJson)); } }
public void DiagnosticStoreInitEventSentToDiagnosticUri() { var expected = LdValue.BuildObject().Add("testKey", "testValue").Build(); var mockDiagnosticStore = MakeDiagnosticStore(null, new DiagnosticEvent(expected), new DiagnosticEvent(LdValue.Null)); var mockSender = MakeMockSender(); var eventCapture = EventCapture.From(mockSender); var diagnosticCapture = EventCapture.DiagnosticsFrom(mockSender); var diagnosticCountdown = new CountdownEvent(1); using (var ep = MakeProcessor(_config, mockSender, mockDiagnosticStore.Object, null, diagnosticCountdown)) { diagnosticCountdown.Wait(); Assert.Equal(expected, diagnosticCapture.EventsQueue.Take()); } }
public void EventKindIsDebugIfFlagIsTemporarilyInDebugMode() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { var flag = BasicFlag; flag.DebugEventsUntilDate = UnixMillisecondTime.Now.PlusMillis(1000000); RecordEval(ep, flag, BasicEval); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckIndexEvent(item, BasicEval.Timestamp, _userJson), item => CheckDebugEvent(item, flag, BasicEval, _userJson), item => CheckSummaryEvent(item)); } }
public void EventCanBeBothTrackedAndDebugged() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { var flag = BasicFlagWithTracking; flag.DebugEventsUntilDate = UnixMillisecondTime.Now.PlusMillis(1000000); RecordEval(ep, flag, BasicEval); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckIndexEvent(item, BasicEval.Timestamp, _userJson), item => CheckFeatureEvent(item, flag, BasicEval, LdValue.Null), item => CheckDebugEvent(item, flag, BasicEval, _userJson), item => CheckSummaryEvent(item)); } }
public void EventsAreNotPostedAfterUnrecoverableFailure() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender, new EventSenderResult(DeliveryStatus.FailedAndMustShutDown, null)); using (var ep = MakeProcessor(_config, mockSender)) { RecordIdentify(ep, _fixedTimestamp, _user); ep.Flush(); ep.WaitUntilInactive(); RecordCustom(ep, BasicCustom); ep.Flush(); ep.WaitUntilInactive(); Assert.Collection(captured.Events, item => CheckIdentifyEvent(item, _fixedTimestamp, _userJson)); } }
public void DiagnosticDisablerDisablesInitialDiagnostics() { var testDiagnostic = LdValue.BuildObject().Add("testKey", "testValue").Build(); var mockDiagnosticStore = MakeDiagnosticStore(new DiagnosticEvent(testDiagnostic), new DiagnosticEvent(testDiagnostic), new DiagnosticEvent(LdValue.Null)); var mockDiagnosticDisabler = new Mock <IDiagnosticDisabler>(MockBehavior.Strict); mockDiagnosticDisabler.Setup(diagDisabler => diagDisabler.Disabled).Returns(true); var mockSender = MakeMockSender(); var eventCapture = EventCapture.From(mockSender); var diagnosticCapture = EventCapture.DiagnosticsFrom(mockSender); using (var ep = MakeProcessor(_config, mockSender, mockDiagnosticStore.Object, mockDiagnosticDisabler.Object, null)) { } mockDiagnosticStore.Verify(diagStore => diagStore.InitEvent, Times.Never()); mockDiagnosticStore.Verify(diagStore => diagStore.PersistedUnsentEvent, Times.Never()); Assert.Empty(diagnosticCapture.Events); }
public void AliasEventIsQueued() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { var ae = new AliasEvent { Timestamp = _fixedTimestamp, Key = "newkey", PreviousKey = "oldkey", ContextKind = ContextKind.User, PreviousContextKind = ContextKind.AnonymousUser }; ep.RecordAliasEvent(ae); FlushAndWait(ep); Assert.Collection(captured.Events, item => CheckAliasEvent(item, ae)); } }
public void FlushDoesNothingWhenOffline() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { ep.SetOffline(true); RecordIdentify(ep, _fixedTimestamp, _user); ep.Flush(); ep.WaitUntilInactive(); Assert.Empty(captured.Events); // We should have still held on to that event, so if we go online again and flush, it is sent. ep.SetOffline(false); ep.Flush(); ep.WaitUntilInactive(); Assert.Collection(captured.Events, item => CheckIdentifyEvent(item, _fixedTimestamp, _userJson)); }; }
public void DiagnosticDisablerEnabledInitialDiagnostics() { var expectedStats = LdValue.BuildObject().Add("stats", "testValue").Build(); var expectedInit = LdValue.BuildObject().Add("init", "testValue").Build(); var mockDiagnosticStore = MakeDiagnosticStore(new DiagnosticEvent(expectedStats), new DiagnosticEvent(expectedInit), new DiagnosticEvent(LdValue.Null)); var mockDiagnosticDisabler = new Mock <IDiagnosticDisabler>(MockBehavior.Strict); mockDiagnosticDisabler.Setup(diagDisabler => diagDisabler.Disabled).Returns(false); var mockSender = MakeMockSender(); var eventCapture = EventCapture.From(mockSender); var diagnosticCapture = EventCapture.DiagnosticsFrom(mockSender); var diagnosticCountdown = new CountdownEvent(1); using (var ep = MakeProcessor(_config, mockSender, mockDiagnosticStore.Object, mockDiagnosticDisabler.Object, diagnosticCountdown)) { diagnosticCountdown.Wait(); Assert.Equal(expectedStats, diagnosticCapture.EventsQueue.Take()); Assert.Equal(expectedInit, diagnosticCapture.EventsQueue.Take()); } }
public void CustomEventIsQueuedWithUser() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { var ce = new TestCustomEventProperties { Timestamp = _fixedTimestamp, User = _user, Key = "eventkey", Data = LdValue.Of(3), MetricValue = 1.5 }; RecordCustom(ep, ce); ep.Flush(); ep.WaitUntilInactive(); Assert.Collection(captured.Events, item => CheckIndexEvent(item, ce.Timestamp, _userJson), item => CheckCustomEvent(item, ce, LdValue.Null)); } }
public void NonTrackedEventsAreSummarized() { var mockSender = MakeMockSender(); var captured = EventCapture.From(mockSender); using (var ep = MakeProcessor(_config, mockSender)) { var flag1 = new TestFlagProperties { Key = "flagkey1", Version = 11 }; var flag2 = new TestFlagProperties { Key = "flagkey2", Version = 22 }; var value1 = LdValue.Of("value1"); var value2 = LdValue.Of("value2"); var default1 = LdValue.Of("default1"); var default2 = LdValue.Of("default2"); var earliestTime = UnixMillisecondTime.OfMillis(10000); var latestTime = UnixMillisecondTime.OfMillis(20000); RecordEval(ep, flag1, new TestEvalProperties { Timestamp = earliestTime, User = _user, Variation = 1, Value = value1, DefaultValue = default1 }); RecordEval(ep, flag1, new TestEvalProperties { Timestamp = UnixMillisecondTime.OfMillis(earliestTime.Value + 10), User = _user, Variation = 1, Value = value1, DefaultValue = default1 }); RecordEval(ep, flag1, new TestEvalProperties { Timestamp = UnixMillisecondTime.OfMillis(earliestTime.Value + 20), User = _user, Variation = 2, Value = value2, DefaultValue = default1 }); RecordEval(ep, flag2, new TestEvalProperties { Timestamp = latestTime, User = _user, Variation = 2, Value = value2, DefaultValue = default2 }); ep.Flush(); ep.WaitUntilInactive(); Assert.Collection(captured.Events, item => CheckIndexEvent(item, earliestTime, _userJson), item => CheckSummaryEventDetails(item, earliestTime, latestTime, MustHaveFlagSummary(flag1.Key, default1, MustHaveFlagSummaryCounter(value1, 1, flag1.Version, 2), MustHaveFlagSummaryCounter(value2, 2, flag1.Version, 1) ), MustHaveFlagSummary(flag2.Key, default2, MustHaveFlagSummaryCounter(value2, 2, flag2.Version, 1) ) ) ); } }