public void GivenFixtureStateActorWhenSpecifiedIntervalPassesThenStateIsPersistedToStore() { // //Arrange // ActorOfAsTestActorRef <FixtureStateActor>( Props.Create(() => new FixtureStateActor( SettingsMock.Object, StoreProviderMock.Object)), FixtureStateActor.ActorName); // //Act // //wait for 2.5s while the internal persistence should be operated at least twice, //given the interval has been mocked to 1s Task.Delay(TimeSpan.FromMilliseconds(2500)).Wait(); // //Assert // StoreProviderMock.Verify(a => a.Write( It.Is <string>(path => path.Equals(SettingsMock.Object.FixturesStateFilePath)), It.IsAny <string>()), Times.AtLeast(2)); }
public void GivenExistingFixtureStateWhenSendRemoveFixtureStateMsgThenRemovesTheFixtureState() { // //Arrange // var storedFixtureState = new FixtureState { Id = "id1", Sport = "sport1", Epoch = 1, Sequence = 1, MatchStatus = MatchStatus.Setup }; StoreProviderMock.Setup(o => o.Read(It.IsAny <string>())) .Returns(JsonConvert.SerializeObject( new Dictionary <string, FixtureState> { { storedFixtureState.Id, storedFixtureState } }, Formatting.Indented)); var fixtureStateActor = ActorOfAsTestActorRef <FixtureStateActor>( Props.Create(() => new FixtureStateActor( SettingsMock.Object, StoreProviderMock.Object)), FixtureStateActor.ActorName); var fixtureState = fixtureStateActor .Ask <FixtureState>(new GetFixtureStateMsg { FixtureId = storedFixtureState.Id }) .Result; Assert.AreEqual(storedFixtureState, fixtureState); // //Act // //Send RemoveFixtureStateMsg and wait for completion fixtureStateActor.Ask(new RemoveFixtureStateMsg { FixtureId = storedFixtureState.Id }); fixtureState = fixtureStateActor .Ask <FixtureState>(new GetFixtureStateMsg { FixtureId = storedFixtureState.Id }) .Result; // //Assert // Assert.IsNull(fixtureState); }
public void WhenStreamingAndMatchOverUpdateAfterSecondTimeMissingSequencesThenRecreateStreamListenerAndProcessMatchOver() { // //Arrange // Fixture snapshot; Mock <IResourceFacade> resourceFacadeMock; SetupCommonMockObjects( /*sport*/ FootabllSportMock.Object.Name, /*fixtureData*/ FixtureSamples.football_inplay_snapshot_2, /*storedData*/ new { Epoch = 3, Sequence = 1, MatchStatus = MatchStatus.InRunning }, out snapshot, out resourceFacadeMock); ServiceMock.Setup(o => o.GetResources(It.Is <string>(s => s.Equals(FootabllSportMock.Object.Name)))) .Returns(new List <IResourceFacade> { resourceFacadeMock.Object }); StreamHealthCheckValidationMock.Setup(a => a.CanConnectToStreamServer( It.IsAny <IResourceFacade>(), It.IsAny <StreamListenerState>())) .Returns(true); FixtureValidationMock.Setup(a => a.IsSnapshotNeeded( It.IsAny <IResourceFacade>(), It.IsAny <FixtureState>())) .Returns(true); // //Act // var streamListenerManagerActor = ActorOfAsTestActorRef <StreamListenerManagerActor>( Props.Create(() => new StreamListenerManagerActor( SettingsMock.Object, PluginMock.Object, StateManagerMock.Object, SuspensionManagerMock.Object, StreamHealthCheckValidationMock.Object, FixtureValidationMock.Object)), StreamListenerManagerActor.ActorName); var sportProcessorRouterActor = ActorOfAsTestActorRef <SportProcessorRouterActor>( Props.Create(() => new SportProcessorRouterActor(ServiceMock.Object)) .WithRouter(new SmallestMailboxPool(SettingsMock.Object.FixtureCreationConcurrency)), SportProcessorRouterActor.ActorName); sportProcessorRouterActor.Tell(new ProcessSportMsg { Sport = FootabllSportMock.Object.Name }); IActorRef streamListenerActorRef; StreamListenerActor streamListenerActor = null; IActorRef resourceActorRef; IActorRef healthCheckActorRef; // //Assert // #region 1st processing //first time the stream listeners goes into Streaming State AwaitAssert(() => { streamListenerActorRef = GetChildActorRef( streamListenerManagerActor, StreamListenerActor.GetName(resourceFacadeMock.Object.Id)); streamListenerActor = GetUnderlyingActor <StreamListenerActor>(streamListenerActorRef); resourceActorRef = GetChildActorRef(streamListenerActorRef, ResourceActor.ActorName); healthCheckActorRef = GetChildActorRef(streamListenerActorRef, StreamHealthCheckActor.ActorName); Assert.NotNull(streamListenerActorRef); Assert.NotNull(streamListenerActor); Assert.NotNull(resourceActorRef); Assert.NotNull(healthCheckActorRef); Assert.AreEqual(StreamListenerState.Streaming, streamListenerActor.State); }, TimeSpan.FromMilliseconds(ASSERT_WAIT_TIMEOUT), TimeSpan.FromMilliseconds(ASSERT_EXEC_INTERVAL)); #endregion #region 2nd processing //second time the stream is not valid because of missing sequences and the fixture is suspended and snapshot processed StreamHealthCheckValidationMock.Reset(); StreamHealthCheckValidationMock.Setup(a => a.CanConnectToStreamServer( It.IsAny <IResourceFacade>(), It.IsAny <StreamListenerState>())) .Returns(true); StreamHealthCheckValidationMock.Setup(a => a.ValidateStream( It.IsAny <IResourceFacade>(), It.IsAny <StreamListenerState>(), It.IsAny <int>())) .Returns(false); //This call will trigger health check message sportProcessorRouterActor.Tell(new ProcessSportMsg { Sport = FootabllSportMock.Object.Name }); // //Assert // AwaitAssert(() => { resourceFacadeMock.Verify(a => a.GetSnapshot(), Times.Exactly(2)); PluginMock.Verify(a => a.ProcessSnapshot(It.Is <Fixture>(f => f.Id.Equals(resourceFacadeMock.Object.Id)), false), Times.Exactly(2)); PluginMock.Verify(a => a.ProcessSnapshot(It.Is <Fixture>(f => f.Id.Equals(resourceFacadeMock.Object.Id)), true), Times.Never); PluginMock.Verify(a => a.ProcessMatchStatus(It.Is <Fixture>(f => f.Id.Equals(resourceFacadeMock.Object.Id))), Times.Never); SuspensionManagerMock.Verify(a => a.Unsuspend(It.Is <Fixture>(f => f.Id.Equals(resourceFacadeMock.Object.Id))), Times.Never); SuspensionManagerMock.Verify(a => a.Suspend(It.Is <Fixture>(f => f.Id.Equals(resourceFacadeMock.Object.Id)), SuspensionReason.SUSPENSION), Times.Once); Assert.AreEqual(StreamListenerState.Streaming, streamListenerActor.State); }, TimeSpan.FromMilliseconds(ASSERT_WAIT_TIMEOUT), TimeSpan.FromMilliseconds(ASSERT_EXEC_INTERVAL)); #endregion #region 3rd processing //third time the stream is not valid because of missing sequences //and the stream listener is stopped because of second stream invalid detection in a row due to missing sequences //but Resource is Match Over so a new Stream Listener instance is created and Match Over is processed StreamHealthCheckValidationMock.Reset(); StreamHealthCheckValidationMock.Setup(a => a.CanConnectToStreamServer( It.IsAny <IResourceFacade>(), It.IsAny <StreamListenerState>())) .Returns(true); StreamHealthCheckValidationMock.Setup(a => a.ValidateStream( It.IsAny <IResourceFacade>(), It.IsAny <StreamListenerState>(), It.IsAny <int>())) .Returns(false); //This call will trigger health check message sportProcessorRouterActor.Tell(new ProcessSportMsg { Sport = FootabllSportMock.Object.Name }); streamListenerActorRef = null; try { AwaitAssert(() => { streamListenerActorRef = GetChildActorRef( streamListenerManagerActor, StreamListenerActor.GetName(resourceFacadeMock.Object.Id)); streamListenerActor = GetUnderlyingActor <StreamListenerActor>(streamListenerActorRef); if (streamListenerActor != null) { Assert.AreEqual(StreamListenerState.Stopped, streamListenerActor.State); } }, TimeSpan.FromMilliseconds(ASSERT_WAIT_TIMEOUT), TimeSpan.FromMilliseconds(ASSERT_EXEC_INTERVAL)); } catch (Exception) { //exception could be caught here as Stream Listener Actor becomes stopped //and eventually killed before we actually have the chance to assert for Stopped state } streamListenerActorRef = null; try { AwaitAssert(() => { streamListenerActorRef = GetChildActorRef( streamListenerManagerActor, StreamListenerActor.GetName(resourceFacadeMock.Object.Id)); Assert.IsNull(streamListenerActorRef); }, TimeSpan.FromMilliseconds(ASSERT_WAIT_TIMEOUT), TimeSpan.FromMilliseconds(ASSERT_EXEC_INTERVAL)); } catch (Exception) { //exception is expected here as Stream Listener Actor should not exist at this time } resourceFacadeMock.Reset(); StateManagerMock.Reset(); StoreProviderMock.Reset(); SetupCommonMockObjects( /*sport*/ FootabllSportMock.Object.Name, /*fixtureData*/ FixtureSamples.football_matchover_snapshot_2, /*storedData*/ new { Epoch = 2, Sequence = 1, MatchStatus = MatchStatus.InRunning }, out snapshot, out resourceFacadeMock); ServiceMock.Reset(); ServiceMock.Setup(o => o.GetResources(It.Is <string>(s => s.Equals(FootabllSportMock.Object.Name)))) .Returns(new List <IResourceFacade> { resourceFacadeMock.Object }); //This call will trigger stream listener actor creation sportProcessorRouterActor.Tell(new ProcessSportMsg { Sport = FootabllSportMock.Object.Name }); streamListenerActorRef = null; try { AwaitAssert(() => { streamListenerActorRef = GetChildActorRef( streamListenerManagerActor, StreamListenerActor.GetName(resourceFacadeMock.Object.Id)); streamListenerActor = GetUnderlyingActor <StreamListenerActor>(streamListenerActorRef); if (streamListenerActor != null) { Assert.AreEqual(StreamListenerState.Stopped, streamListenerActor.State); } }, TimeSpan.FromMilliseconds(ASSERT_WAIT_TIMEOUT), TimeSpan.FromMilliseconds(ASSERT_EXEC_INTERVAL)); } catch (Exception) { //exception could be caught here as Stream Listener Actor becomes stopped //and eventually killed before we actually have the chance to assert for Stopped state } streamListenerActorRef = null; try { AwaitAssert(() => { streamListenerActorRef = GetChildActorRef( streamListenerManagerActor, StreamListenerActor.GetName(resourceFacadeMock.Object.Id)); Assert.IsNull(streamListenerActorRef); resourceFacadeMock.Verify(a => a.GetSnapshot(), Times.Once); PluginMock.Verify(a => a.ProcessSnapshot(It.Is <Fixture>(f => f.Id.Equals(resourceFacadeMock.Object.Id)), false), Times.Never); PluginMock.Verify(a => a.ProcessSnapshot(It.Is <Fixture>(f => f.Id.Equals(resourceFacadeMock.Object.Id)), true), Times.Once); PluginMock.Verify(a => a.ProcessMatchStatus(It.Is <Fixture>(f => f.Id.Equals(resourceFacadeMock.Object.Id))), Times.Never); SuspensionManagerMock.Verify(a => a.Unsuspend(It.Is <Fixture>(f => f.Id.Equals(resourceFacadeMock.Object.Id))), Times.Never); SuspensionManagerMock.Verify(a => a.Suspend(It.Is <Fixture>(f => f.Id.Equals(resourceFacadeMock.Object.Id)), SuspensionReason.SUSPENSION), Times.Once); }, TimeSpan.FromMilliseconds(ASSERT_WAIT_TIMEOUT), TimeSpan.FromMilliseconds(ASSERT_EXEC_INTERVAL)); } catch (Exception) { //exception is expected here as Stream Listener Actor should not exist at this time } #endregion #region 4th processing //fourth time no Stream Listener is created as Match is already Over and was already processed sportProcessorRouterActor.Tell(new ProcessSportMsg { Sport = FootabllSportMock.Object.Name }); streamListenerActorRef = null; try { AwaitAssert(() => { streamListenerActorRef = GetChildActorRef( streamListenerManagerActor, StreamListenerActor.GetName(resourceFacadeMock.Object.Id)); streamListenerActor = GetUnderlyingActor <StreamListenerActor>(streamListenerActorRef); Assert.NotNull(streamListenerActorRef); Assert.NotNull(streamListenerActor); }, TimeSpan.FromMilliseconds(ASSERT_WAIT_TIMEOUT), TimeSpan.FromMilliseconds(ASSERT_EXEC_INTERVAL)); } catch (Exception) { //exception is expected here as Stream Listener Actor should not exist at this time } // //Assert // AwaitAssert(() => { Assert.IsNull(streamListenerActorRef); }, TimeSpan.FromMilliseconds(ASSERT_WAIT_TIMEOUT), TimeSpan.FromMilliseconds(ASSERT_EXEC_INTERVAL)); #endregion }