public void GetSportsTest()
        {
            var fixtureOneId = "fixtureOne";
            var fixtureTwoId = "fixtureTwo";

            var resourceOne = new Mock<IResourceFacade>();
            var resourceTwo = new Mock<IResourceFacade>();

            resourceOne.Setup(x => x.Id).Returns(fixtureOneId);
            resourceOne.Setup(x => x.Content).Returns(new Summary());
            resourceOne.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resourceOne.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureOneId)));
            resourceOne.Setup(x => x.Sport).Returns("TestSport1");
            resourceOne.Setup(x => x.StartStreaming()).Raises(r => r.StreamConnected += null, EventArgs.Empty);


            resourceTwo.Setup(x => x.Id).Returns(fixtureTwoId);
            resourceTwo.Setup(x => x.Content).Returns(new Summary());
            resourceTwo.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resourceTwo.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureTwoId)));
            resourceTwo.Setup(x => x.Sport).Returns("TestSport2");
            resourceTwo.Setup(x => x.StartStreaming()).Raises(r => r.StreamConnected += null, EventArgs.Empty);

            _supervisor.CreateStreamListener(resourceOne.Object, _plugin.Object);
            _supervisor.CreateStreamListener(resourceTwo.Object, _plugin.Object);
            
            _supervisor.GetSports().Should().NotBeEmpty();
            _supervisor.GetSports().Count().Should().Be(2);
            _supervisor.GetSportOverview("TestSport1").Should().NotBeNull();
            _supervisor.GetSportOverview("TestSport1").InPlay.Should().Be(1);
        }
Exemple #2
0
        public void AllowReconnectionAfterDisconnection()
        {
            Mock <IResourceFacade> resource  = new Mock <IResourceFacade>();
            Mock <IAdapterPlugin>  connector = new Mock <IAdapterPlugin>();
            Mock <IEventState>     state     = new Mock <IEventState>();
            Mock <ISettings>       settings  = new Mock <ISettings>();

            var provider = new StateManager(settings.Object, connector.Object);

            Fixture fixture = new Fixture {
                Id = "Reconnect", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString()
            };

            resource.Setup(x => x.Content).Returns(new Summary());
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resource.Setup(r => r.Id).Returns("Reconnect");
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty);
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();

            listener.ResourceOnStreamDisconnected(this, EventArgs.Empty);

            listener.IsStreaming.Should().BeFalse();

            listener.UpdateResourceState(resource.Object);

            listener.IsStreaming.Should().BeTrue();
        }
        public void GetFullOverviewTest()
        {
            var fixtureOneId = "fixtureOne";
            var fixtureTwoId = "fixtureTwo";

            var resourceOne = new Mock<IResourceFacade>();
            var resourceTwo = new Mock<IResourceFacade>();

            resourceOne.Setup(x => x.Id).Returns(fixtureOneId);
            resourceOne.Setup(x => x.Content).Returns(new Summary());
            resourceOne.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resourceOne.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureOneId)));
            resourceOne.Setup(x => x.Sport).Returns("TestSport1");

            resourceTwo.Setup(x => x.Id).Returns(fixtureTwoId);
            resourceTwo.Setup(x => x.Content).Returns(new Summary());
            resourceTwo.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resourceTwo.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureTwoId)));
            resourceTwo.Setup(x => x.Sport).Returns("TestSport2");

            _supervisor.CreateStreamListener(resourceOne.Object, _plugin.Object);
            _supervisor.CreateStreamListener(resourceTwo.Object, _plugin.Object);

            var fixtureOverviews = _supervisor.GetFixtures();
            fixtureOverviews.Should().NotBeNullOrEmpty();
            fixtureOverviews.Should().Contain(f => f.Id == fixtureOneId);
            fixtureOverviews.Should().Contain(f => f.Id == fixtureTwoId);
            fixtureOverviews.Any(f=> f.Sport == "TestSport1").Should().BeTrue();
            fixtureOverviews.Any(f => f.Sport == "TestSport2").Should().BeTrue();
        }
        public void DoNotSuspendFixtureOnDisconeectIfDeletedTest()
        {
            // STEP 1: prepare stub data
            Mock <IResourceFacade> resource  = new Mock <IResourceFacade>();
            Mock <IAdapterPlugin>  connector = new Mock <IAdapterPlugin>();
            Mock <IEventState>     state     = new Mock <IEventState>();
            Mock <ISettings>       settings  = new Mock <ISettings>();
            var provider = new StateManager(settings.Object, connector.Object);


            // STEP 3: prepare the fixture data
            Fixture fixture = new Fixture {
                Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString()
            };

            fixture.Tags.Add("Sport", "Football"); // add at least one tags, so the MarketsRulesManager recognize it as a full-snapshot

            fixture.Markets.Add(new Market("MKT-1"));
            var mkt = new Market("MKT-2");

            mkt.AddOrUpdateTagValue("traded_in_play", "false");
            fixture.Markets.Add(mkt);

            // ...and MatchStatus=MatchOver
            Fixture update = new Fixture
            {
                Id                    = "ABC",
                Sequence              = 2,
                MatchStatus           = ((int)MatchStatus.InRunning).ToString(),
                Epoch                 = 2,
                LastEpochChangeReason = new[] { (int)EpochChangeReason.Deleted }
            };

            StreamMessage message = new StreamMessage {
                Content = update
            };


            resource.Setup(x => x.Id).Returns("ABC");
            resource.Setup(x => x.Content).Returns(new Summary());
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected   += null, EventArgs.Empty);
            resource.Setup(x => x.StopStreaming()).Raises(x => x.StreamDisconnected += null, EventArgs.Empty);
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            // STEP 4: start the listener
            StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();

            // STEP 5: send the update
            listener.ResourceOnStreamEvent(this, new StreamEventArgs(JsonConvert.SerializeObject(message)));


            // STEP 6: check the result, note tha MKT-2 is not in-play
            connector.Verify(x => x.ProcessStreamUpdate(It.Is <Fixture>(y => y.Id == "ABC" && y.Markets.Count == 0), It.IsAny <bool>()));
        }
        public void SuspendFixtureOnDisconnectTest()
        {
            // STEP 1: prepare stub data
            Mock <IResourceFacade> resource  = new Mock <IResourceFacade>();
            Mock <IAdapterPlugin>  connector = new Mock <IAdapterPlugin>();
            Mock <IEventState>     state     = new Mock <IEventState>();
            Mock <ISettings>       settings  = new Mock <ISettings>();
            var provider = new StateManager(settings.Object, connector.Object);

            provider.SuspensionManager.RegisterAction(provider.SuspensionManager.SuspendInPlayMarketsStrategy, SuspensionReason.DISCONNECT_EVENT);

            // STEP 3: prepare the fixture data
            Fixture fixture = new Fixture {
                Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString()
            };

            fixture.Tags.Add("Sport", "Football"); // add at least one tags, so the MarketsRulesManager recognize it as a full-snapshot

            var mkt = new Market("MKT-1");

            mkt.Selections.Add(new Selection {
                Id = "SELN-1", Status = SelectionStatus.Active
            });
            fixture.Markets.Add(mkt);

            mkt = new Market("MKT-2");
            mkt.AddOrUpdateTagValue("traded_in_play", "false");
            fixture.Markets.Add(mkt);

            resource.Setup(x => x.Id).Returns("ABC");
            resource.Setup(x => x.Content).Returns(new Summary());
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty);
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            // STEP 4: start the listener
            StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();


            // STEP 5: send the disconnect event
            listener.ResourceOnStreamDisconnected(this, EventArgs.Empty);


            // STEP 6: check the result, note tha MKT-2 is not in-play
            connector.Verify(x => x.ProcessStreamUpdate(It.Is <Fixture>(
                                                            y => y.Id == "ABC" &&
                                                            y.Markets.Count == 1 &&
                                                            y.Markets.FirstOrDefault(z => z.Id == "MKT-1") != null &&
                                                            y.Markets.FirstOrDefault(z => z.Id == "MKT-2") == null),
                                                        It.IsAny <bool>()));
        }
        public void GetDeltaOverviewTest()
        {
            var fixtureOneId = "fixtureOne";
            
            _resource.Setup(x => x.Id).Returns(fixtureOneId);
            _resource.Setup(x => x.Content).Returns(new Summary());
            _resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            _resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureOneId)));
            _resource.Setup(x => x.StartStreaming()).Raises(r => r.StreamConnected += null, EventArgs.Empty);

            var deltas = new List<IFixtureOverviewDelta>();
            var subscriber = _supervisor.GetFixtureOverviewStream().ObserveOn(NewThreadScheduler.Default).Subscribe(deltas.Add);

            _supervisor.CreateStreamListener(_resource.Object, _plugin.Object);

            var fixtureOverviews = _supervisor.GetFixtures();
            fixtureOverviews.Should().NotBeNullOrEmpty();
            fixtureOverviews.Should().Contain(f => f.Id == fixtureOneId);
            
            _supervisor.StartStreaming(fixtureOneId);

            var epoch = 1;

            var streamUpdate = new Fixture
            {
                Id = fixtureOneId,
                Sequence = 2,
                Epoch = epoch,
                MatchStatus = ((int)MatchStatus.InRunning).ToString()
            };

            SendStreamUpdate(streamUpdate);
            
            Thread.Sleep(1000);

            deltas.Should().NotBeEmpty();
            var sequenceTwoDeltas = deltas.Where(d => d.FeedUpdate != null && d.FeedUpdate.Sequence == 2).ToList();
            sequenceTwoDeltas.Should().NotBeNull();
            sequenceTwoDeltas.Count.Should().Be(2);
            
            //FeedUpdate with IsProcessed in both states exists
            sequenceTwoDeltas.Any(d => d.FeedUpdate.IsProcessed).Should().BeTrue();
            sequenceTwoDeltas.Any(d => !d.FeedUpdate.IsProcessed).Should().BeTrue();

            //deltas are filtered by sequence = 2 and there was only stream update with that sequence
            sequenceTwoDeltas.All(d => !d.FeedUpdate.IsSnapshot).Should().BeTrue();
            sequenceTwoDeltas.All(d => d.FeedUpdate.Epoch == epoch).Should().BeTrue();
            
            subscriber.Dispose();
        }
        public void GetDeltaErrorsTest()
        {
            var fixtureOneId = "fixtureOne";

            var resourceOne = new Mock<IResourceFacade>();

            resourceOne.Setup(x => x.Id).Returns(fixtureOneId);
            resourceOne.Setup(x => x.Content).Returns(new Summary());
            resourceOne.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resourceOne.Setup(x => x.Sport).Returns("Football");
            resourceOne.SetupSequence(x => x.GetSnapshot())
                .Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureOneId)))
                .Returns(String.Empty)
                .Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureOneId, 10, 3)));

            resourceOne.Setup(x => x.StartStreaming()).Raises(r => r.StreamConnected += null, EventArgs.Empty);

            _supervisor.CreateStreamListener(resourceOne.Object, _plugin.Object);

            var fixtureOverviews = _supervisor.GetFixtures();
            fixtureOverviews.Should().NotBeNullOrEmpty();
            fixtureOverviews.Should().Contain(f => f.Id == fixtureOneId);

            _supervisor.StartStreaming(fixtureOneId);

            var streamUpdate = new Fixture
            {
                Id = fixtureOneId,
                Sequence = 2,
                //Epoch increased
                Epoch = 10,
                MatchStatus = ((int)MatchStatus.InRunning).ToString()
            };

            var deltas = new List<IFixtureOverviewDelta>();

            using (var subscriber = _supervisor.GetFixtureOverviewStream().Subscribe(deltas.Add))
            {
                //in order to generate error the resource is setup to return empty snapshot
                //the snapshot should be taken because epoch is changed
                SendStreamUpdate(streamUpdate);
                
                deltas.Should().NotBeEmpty();
                deltas.FirstOrDefault(d => d.LastError != null).Should().NotBeNull();

                //error was resolved with a further snapshot
                deltas.FirstOrDefault(d => d.LastError != null && !d.LastError.IsErrored).Should().NotBeNull();
            }
        }
        public void CheckUpdatesAreTrackedTest()
        {
            var fixtureOneId = "fixtureOne";

            var resourceOne = new Mock<IResourceFacade>();

            resourceOne.Setup(x => x.Id).Returns(fixtureOneId);
            resourceOne.Setup(x => x.Content).Returns(new Summary());
            resourceOne.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resourceOne.SetupSequence(x => x.GetSnapshot())
                .Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureOneId)))
                .Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureOneId, 10, 3)));

            resourceOne.Setup(x => x.StartStreaming()).Raises(r => r.StreamConnected += null, EventArgs.Empty);

            _supervisor.CreateStreamListener(resourceOne.Object, _plugin.Object);

            var fixtureOverviews = _supervisor.GetFixtures();
            fixtureOverviews.Should().NotBeNullOrEmpty();
            fixtureOverviews.Should().Contain(f => f.Id == fixtureOneId);

            _supervisor.StartStreaming(fixtureOneId);

            var streamUpdate = new Fixture
            {
                Id = fixtureOneId,
                Sequence = 2,
                //Epoch increased
                Epoch = 10,
                MatchStatus = ((int)MatchStatus.InRunning).ToString()
            };


            Enumerable.Range(3, 13).ForEach(s =>
            {
                streamUpdate.Sequence = s;
                SendStreamUpdate(streamUpdate);
            });

            var fixtureOverview = _supervisor.GetFixtureOverview(fixtureOneId);
            fixtureOverview.GetFeedAudit().Should().NotBeEmpty();
            fixtureOverview.GetFeedAudit().FirstOrDefault(f => f.Sequence == 12 && f.IsProcessed).Should().NotBeNull();

            fixtureOverview.FeedUpdate.Sequence.Should().BeGreaterThan(10);
        }
        public void ForceSnapshotTest()
        {
            var snapshotId = "testFixtureId";
            Fixture fixture = GetSnapshotWithMarkets(snapshotId);

            _resource.Setup(x => x.Id).Returns(snapshotId);
            _resource.Setup(x => x.Content).Returns(new Summary());
            _resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            _resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            _supervisor.CreateStreamListener(_resource.Object, _plugin.Object);

            _supervisor.ForceSnapshot(fixture.Id);
            _supervisor.ForceSnapshot(fixture.Id);

            

            //inital snapshot + 2 forced snapshots = 3
            _resource.Verify(x => x.GetSnapshot(), Times.Exactly(3));
            _plugin.Verify(x => x.ProcessSnapshot(It.Is<Fixture>(f => f.Markets.Count == 1), It.IsAny<bool>()), Times.Exactly(3));
        }
        public void CheckErrorsAreTrackedTest()
        {
            var fixtureOneId = "fixtureOne";
            
            _resource.Setup(x => x.Id).Returns(fixtureOneId);
            _resource.Setup(x => x.Content).Returns(new Summary());
            _resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            _resource.SetupSequence(x => x.GetSnapshot())
                .Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureOneId)))
                .Returns(String.Empty)
                .Returns(String.Empty)
                .Returns(String.Empty)
                .Returns(String.Empty)
                .Returns(FixtureJsonHelper.ToJson(GetSnapshotWithMarkets(fixtureOneId, 10, 15)));

            _resource.Setup(x => x.StartStreaming()).Raises(r => r.StreamConnected += null, EventArgs.Empty);

            _supervisor.CreateStreamListener(_resource.Object, _plugin.Object);

            var fixtureOverviews = _supervisor.GetFixtures();
            fixtureOverviews.Should().NotBeNullOrEmpty();
            fixtureOverviews.Should().Contain(f => f.Id == fixtureOneId);

            _supervisor.StartStreaming(fixtureOneId);

            var streamUpdate = new Fixture
            {
                Id = fixtureOneId,
                Sequence = 2,
                //Epoch increased
                Epoch = 10,
                MatchStatus = ((int)MatchStatus.InRunning).ToString()
            };

            var deltas = new List<IFixtureOverviewDelta>();

            using (var subscriber = _supervisor.GetFixtureOverviewStream().Subscribe(deltas.Add))
            {
                Enumerable.Range(3, 10).ForEach(s =>
                {
                    streamUpdate.Sequence = s;
                    SendStreamUpdate(streamUpdate);
                });
            }

            var fixtureOverview = _supervisor.GetFixtureOverview(fixtureOneId);
            fixtureOverview.GetErrorsAudit().Should().NotBeEmpty();
            var errorsAudit = fixtureOverview.GetErrorsAudit();

            //at least 4 failed snapshots
            errorsAudit.Count().Should().Be(4);

            //the final snapshot sholud have succeeded
            fixtureOverview.LastError.IsErrored.Should().BeFalse();

            //there should be delta notification with LastError update IsErrored = false
            deltas.FirstOrDefault(d=> 
                d.LastError != null 
                && d.LastError.ResolvedAt == fixtureOverview.LastError.ResolvedAt 
                && d.LastError.Sequence == fixtureOverview.LastError.Sequence).Should().NotBeNull();
        }
Exemple #11
0
        public void AcquireSnapshotAfterFixtureStatusChangeTest()
        {
            var settings = new Mock <ISettings>();
            var service  = new Mock <IServiceFacade>();

            var plugin     = new Mock <IAdapterPlugin>();
            var feature    = new Mock <IFeature>();
            var resource   = new Mock <IResourceFacade>();
            var eventstate = new Mock <IEventState>();
            var provider   = new StateManager(settings.Object, plugin.Object);

            Fixture fixture = new Fixture {
                Id = "ABC", FixtureName = "ABC", Sequence = 2, MatchStatus = "10"
            };

            fixture.Tags.Add("Sport", "Football");

            settings.Setup(x => x.FixtureCreationConcurrency).Returns(1);
            settings.Setup(x => x.FixtureCheckerFrequency).Returns(1000);
            settings.Setup(x => x.EventStateFilePath).Returns(".");
            settings.Setup(x => x.ProcessingLockTimeOutInSecs).Returns(10);
            settings.Setup(x => x.StreamSafetyThreshold).Returns(int.MaxValue);

            var streamListenerManager = new StreamListenerManager(settings.Object);

            streamListenerManager.StateManager = new Mock <IStateManager>().Object;
            feature.Setup(x => x.Name).Returns("Football");

            service.Setup(x => x.GetSports()).Returns(new List <IFeature> {
                feature.Object
            });
            service.Setup(x => x.GetResources(It.Is <string>(y => y == "Football"))).Returns(new List <IResourceFacade> {
                resource.Object
            });
            service.Setup(x => x.IsConnected).Returns(true);

            eventstate.Setup(x => x.GetFixtureState(It.Is <string>(y => y == "ABC"))).Returns(
                new FixtureState
            {
                MatchStatus = MatchStatus.Setup,
                Sequence    = 2,
                Id          = "ABC",
                Sport       = "Football"
            });

            resource.Setup(x => x.Id).Returns("ABC");
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.Setup);
            resource.Setup(x => x.Content).Returns(new Summary
            {
                Id          = "ABC",
                MatchStatus = 10, // InSetup
                Sequence    = 2
            });

            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty);

            Adapter adapter = new Adapter(settings.Object, service.Object, plugin.Object, streamListenerManager)
            {
                StateManager = provider
            };

            streamListenerManager.EventState = eventstate.Object;

            adapter.Start();


            Thread.Sleep(3000);

            resource.Verify(x => x.GetSnapshot(), Times.Once);
            resource.Verify(x => x.StartStreaming(), Times.Never);

            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.Prematch);
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected += null, EventArgs.Empty);
            resource.Setup(x => x.Content).Returns(new Summary
            {
                Id          = "ABC",
                MatchStatus = 30,
                Sequence    = 3
            });

            service.Setup(x => x.GetResources(It.Is <string>(y => y == "Football"))).Returns(new List <IResourceFacade> {
                resource.Object
            });

            Thread.Sleep(3000);

            resource.Verify(x => x.GetSnapshot(), Times.Exactly(2));
        }
        public void SerializeModelTest()
        {
            Fixture fixture = new Fixture
            {
                FixtureName           = "TEST-NAME",
                Epoch                 = 10,
                LastEpochChangeReason = new[] { 10, 20 },
                Id          = "TEST-ID",
                StartTime   = new DateTime(2000, 01, 01),
                Sequence    = 12,
                MatchStatus = "40"
            };

            fixture.Tags.Add("TEST-TAG-1", "1");
            fixture.Tags.Add("TEST-TAG-2", 2);
            fixture.GameState.Add("TEST-STATE-1", 1);
            fixture.GameState.Add("TEST-STATE-2", "2");

            Participant p1 = new Participant {
                Id = 1, Name = "P1"
            };

            p1.Tags.Add("TEST-TAG-1", "1");
            p1.Tags.Add("TEST-TAG-2", 2);

            Participant p2 = new Participant {
                Id = 2, Name = "P2"
            };

            fixture.Participants.Add(p1);
            fixture.Participants.Add(p2);

            Market mkt1 = new Market {
                Id = "MKT1"
            };

            mkt1.AddOrUpdateTagValue("name", "MKT1");

            Selection seln1 = new Selection
            {
                Id       = "SELN1",
                Price    = 2.0,
                Status   = SelectionStatus.Active,
                Tradable = false
            };

            seln1.AddOrUpdateTagValue("name", "seln1");
            seln1.AddOrUpdateTagValue("displayed", "true");

            Selection seln2 = new Selection
            {
                Id       = "SELN2",
                Price    = 3.0,
                Status   = SelectionStatus.Pending,
                Tradable = true
            };

            seln2.AddOrUpdateTagValue("name", "seln2");
            seln2.AddOrUpdateTagValue("displayed", "false");

            mkt1.Selections.Add(seln1);
            mkt1.Selections.Add(seln2);

            RollingMarket mkt2 = new RollingMarket {
                Id = "RMKT2", Line = 2.0
            };

            mkt2.AddOrUpdateTagValue("name", "RMKT2");

            RollingSelection seln3 = new RollingSelection
            {
                Id       = "SELN3",
                Price    = 7.0,
                Status   = SelectionStatus.Pending,
                Tradable = true,
                Line     = 21
            };

            ((Market)mkt2).Selections.Add(seln3);
            Market test2 = mkt2;

            test2.Selections.Count.Should().Be(1);
            (test2.Selections.FirstOrDefault() is RollingSelection).Should().BeTrue();

            Market mkt3 = new RollingMarket();

            mkt3.Id = "RMKT3";
            mkt3.AddOrUpdateTagValue("name", "RMKT3");

            fixture.Markets.Add(mkt1);
            fixture.Markets.Add(mkt2);
            fixture.Markets.Add(mkt3);

            fixture.RollingMarkets.FirstOrDefault(x => x.Id == "MKT1").Should().BeNull();
            fixture.RollingMarkets.FirstOrDefault(x => x.Id == "RMKT2").Should().NotBeNull();
            fixture.RollingMarkets.FirstOrDefault(x => x.Id == "RMKT3").Should().NotBeNull();

            fixture.StandardMarkets.FirstOrDefault(x => x.Id == "MKT1").Should().NotBeNull();
            fixture.StandardMarkets.FirstOrDefault(x => x.Id == "RMKT2").Should().BeNull();
            fixture.StandardMarkets.FirstOrDefault(x => x.Id == "RMKT3").Should().BeNull();

            string value = FixtureJsonHelper.ToJson(fixture);

            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(value)))
            {
                stream.Position = 0;
                string value2 = Encoding.UTF8.GetString(stream.ToArray());

                value.Should().BeEquivalentTo(value2);

                fixture = FixtureJsonHelper.GetFromJson(value2);
            }

            fixture.RollingMarkets.Count().Should().Be(2);
            fixture.StandardMarkets.Count().Should().Be(1);
            fixture.Markets.Count().Should().Be(3);
            fixture.Tags.Count.Should().Be(2);
            fixture.GameState.Count().Should().Be(2);
            fixture.Participants.Count().Should().Be(2);

            fixture.Markets.FirstOrDefault(x => x.Id == "MKT1").Selections.Count.Should().Be(2);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT2").Selections.Count.Should().Be(1);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT3").Selections.Count.Should().Be(0);

            BinaryStoreProvider <Fixture> provider = new BinaryStoreProvider <Fixture>(".", "test-{0}.dat");

            provider.SetObject("TEST", fixture);

            fixture = provider.GetObject("TEST");

            fixture.RollingMarkets.Count().Should().Be(2);
            fixture.StandardMarkets.Count().Should().Be(1);
            fixture.Markets.Count().Should().Be(3);
            fixture.Tags.Count.Should().Be(2);
            fixture.GameState.Count().Should().Be(2);
            fixture.Participants.Count().Should().Be(2);

            fixture.Markets.FirstOrDefault(x => x.Id == "MKT1").Selections.Count.Should().Be(2);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT2").Selections.Count.Should().Be(1);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT3").Selections.Count.Should().Be(0);

            fixture = value.FromJson <Fixture>();

            fixture.RollingMarkets.Count().Should().Be(2);
            fixture.StandardMarkets.Count().Should().Be(1);
            fixture.Markets.Count().Should().Be(3);
            fixture.Tags.Count.Should().Be(2);
            fixture.GameState.Count().Should().Be(2);
            fixture.Participants.Count().Should().Be(2);

            fixture.Markets.FirstOrDefault(x => x.Id == "MKT1").Selections.Count.Should().Be(2);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT2").Selections.Count.Should().Be(1);
            fixture.Markets.FirstOrDefault(x => x.Id == "RMKT3").Selections.Count.Should().Be(0);
        }
        public void UnsuspendFixtureAndMarketsTest()
        {
            // STEP 1: prepare stub data
            Mock <IResourceFacade> resource  = new Mock <IResourceFacade>();
            Mock <IAdapterPlugin>  connector = new Mock <IAdapterPlugin>();
            Mock <IEventState>     state     = new Mock <IEventState>();
            Mock <ISettings>       settings  = new Mock <ISettings>();
            var provider = new StateManager(settings.Object, connector.Object);

            provider.SuspensionManager.RegisterAction(provider.SuspensionManager.SuspendInPlayMarketsStrategy, SuspensionReason.DISCONNECT_EVENT);

            // STEP 2: prepare the fixture data
            Fixture fixture = new Fixture {
                Id = "ABC", Sequence = 1, MatchStatus = ((int)MatchStatus.InRunning).ToString()
            };

            fixture.Tags.Add("Sport", "Football"); // add at least one tags, so the MarketsRulesManager recognize it as a full-snapshot

            var mkt1 = new Market {
                Id = "MKT-1"
            };

            mkt1.Selections.Add(new Selection {
                Id = "SELN", Status = SelectionStatus.Active, Tradable = true
            });
            fixture.Markets.Add(mkt1);

            var mkt = new Market("MKT-2");

            mkt.AddOrUpdateTagValue("traded_in_play", "false");
            fixture.Markets.Add(mkt);

            resource.Setup(x => x.Id).Returns("ABC");
            resource.Setup(x => x.Content).Returns(new Summary()
            {
                Sequence = 1
            });
            resource.Setup(x => x.MatchStatus).Returns(MatchStatus.InRunning);
            resource.Setup(x => x.StartStreaming()).Raises(x => x.StreamConnected   += null, EventArgs.Empty);
            resource.Setup(x => x.StopStreaming()).Raises(x => x.StreamDisconnected += null, EventArgs.Empty);
            resource.Setup(x => x.GetSnapshot()).Returns(FixtureJsonHelper.ToJson(fixture));

            // STEP 4: start the listener
            StreamListener listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, settings.Object);

            listener.Start();

            listener.IsStreaming.Should().BeTrue();

            connector.Verify(x => x.ProcessStreamUpdate(It.IsAny <Fixture>(), It.IsAny <bool>()), Times.Never);

            listener.Dispose();


            //Should suspend at the fixture level only
            connector.Verify(x => x.Suspend(It.Is <string>(fId => fId == "ABC")), Times.Once);


            //recreate listener
            //must have state setup otherwise it will process snapshot not unsuspend
            state.Setup(x => x.GetFixtureState(It.Is <string>(fId => fId == fixture.Id)))
            .Returns(new FixtureState()
            {
                Id          = fixture.Id,
                MatchStatus = MatchStatus.InRunning,
                Sequence    = fixture.Sequence
            });

            listener = new StreamListener(resource.Object, connector.Object, state.Object, provider, settings.Object);
            listener.Start();

            // Unsuspend should be called on reconnect
            connector.Verify(x => x.UnSuspend(It.IsAny <Fixture>()), Times.Once);
        }