public static void Subscribe_PublishesExactSequenceOfItemsOverMultipleElapsedIntervals() { var jobStorage = A.Fake<IDurableJobQueue<Incoming, Incoming>>(); var scheduler = new HistoricalScheduler(); var monitor = new DurableJobQueueMonitor<Incoming, Incoming>(jobStorage, 20, DurableJobQueueMonitor.DefaultPollingInterval, scheduler); List<Incoming> incomingItems = new List<Incoming>(); var queuedItems = Enumerable.Repeat(Item.From(new Incoming() { Id = 1 }), 5) .Concat(new [] { Item.None<Incoming>() }) .Concat(Enumerable.Repeat(Item.From(new Incoming() { Id = 2 }), 5)) .Concat(new [] { Item.None<Incoming>() }) .Concat(Enumerable.Repeat(Item.From(new Incoming() { Id = 1 }), 2)) .Concat(new [] { Item.None<Incoming>() }).ToArray(); using (var subscription = monitor.Subscribe(publishedItem =>{ incomingItems.Add(publishedItem);})) { A.CallTo(() => jobStorage.NextQueuedItem()).ReturnsNextFromSequence(queuedItems); scheduler.AdvanceBy(monitor.PollingInterval); scheduler.AdvanceBy(monitor.PollingInterval); scheduler.AdvanceBy(monitor.PollingInterval); Assert.True(queuedItems.Where(item => item.Success) .Select(item => item.Value) .SequenceEqual(incomingItems, GenericEqualityComparer<Incoming>.ByAllMembers())); } }
public void PublishReconnect() { var scheduler = new HistoricalScheduler (); var source = Observable.Interval (TimeSpan.FromMilliseconds (50), scheduler); int result = 0; var published = source.Publish (); var pdis1 = published.Subscribe (i => result++); Assert.AreEqual (0, result, "#0"); var cdis1 = published.Connect (); scheduler.AdvanceBy (TimeSpan.FromMilliseconds (200)); // should be enough to receive some events Assert.AreEqual (4, result, "#1"); pdis1.Dispose (); cdis1.Dispose (); // disconnect scheduler.AdvanceBy (TimeSpan.FromMilliseconds (200)); // should be enough to raise interval event if it were active (which should *not*) Assert.AreEqual (4, result, "#2"); // Step 2: Without any *new* subscription, it does not result in events. var cdis2 = published.Connect (); scheduler.AdvanceBy (TimeSpan.FromMilliseconds (200)); // should be enough to receive some events Assert.AreEqual (4, result , "#3"); cdis2.Dispose (); // Step 3: with new subscription, it should result in events again. var pdis3 = published.Subscribe (i => result++); var cdis3 = published.Connect (); // without any *new* subscription, it does not result in events. scheduler.AdvanceBy (TimeSpan.FromMilliseconds (200)); // should be enough to receive some events Assert.AreEqual (8, result , "#3"); cdis3.Dispose (); pdis3.Dispose (); // This should not result in NRE (possibly because of the internal cleanup). Note that this is in reverse order to pdis1 }
public void Clock() { var scheduler = new HistoricalScheduler (); Assert.AreEqual (DateTimeOffset.MinValue, scheduler.Clock, "#1"); // default scheduler.AdvanceBy (TimeSpan.FromDays (1)); Assert.AreEqual (DateTimeOffset.MinValue.AddDays (1), scheduler.Clock, "#2"); scheduler.AdvanceTo (new DateTimeOffset (2012, 1, 1, 0, 0, 0, TimeSpan.Zero)); Assert.AreEqual (2012, scheduler.Clock.Year, "#3"); }
public void RecursiveActionTimeSpan2() { int i = 0; var scheduler = new HistoricalScheduler (); var span = TimeSpan.FromMilliseconds (50); scheduler.Schedule<object> (null, span, (object obj,Action<object,TimeSpan> a) => { i++; a (obj, span); }); scheduler.AdvanceBy (TimeSpan.FromSeconds (1)); Assert.AreEqual (20, i, "#1"); }
public void SetUp() { _tradeRepo = Substitute.For<ITradeRepository>(); _analyticsService = Substitute.For<IAnalyticsService>(); _executionService = Substitute.For<IExecutionService>(); _lastValueCache = Substitute.For<IPriceLastValueCache>(); _scheduler = new HistoricalScheduler(); _scheduler.AdvanceTo(DateTimeOffset.Now); _schedulerService = Substitute.For<ISchedulerService>(); _schedulerService.ThreadPool.Returns(_scheduler); }
public void AdvanceByRaisesEvent2() { // This is actually very complicated pattern of error, caused by all of: // - Concat() when it internally uses SerialDisposable instead of CompositeDisposable. // - Delay() with non-zero duration. // - Delay() with non-CurrentThreadScheduler. var scheduler = new HistoricalScheduler (); var o = Observable.Empty<int> (scheduler).Delay (TimeSpan.FromSeconds (1), scheduler); bool done = false; Observable.Range (0, 3).Concat (o).Subscribe (v => {}, () => done = true); scheduler.AdvanceBy (TimeSpan.FromSeconds (2)); Assert.IsTrue (done, "#1"); }
public void PublishLast() { var scheduler = new HistoricalScheduler (); var hot = Observable.Interval (TimeSpan.FromMilliseconds (20), scheduler).Skip (4).Take (2).PublishLast (); hot.Connect (); var observable = hot.Replay (); observable.Connect (); long result = 0; var dis = observable.Subscribe (i => result += i); scheduler.AdvanceBy (TimeSpan.FromSeconds (1)); Assert.AreEqual (5, result, "#1"); dis.Dispose (); var dis2 = observable.Subscribe (i => result += i); Assert.AreEqual (10, result, "#2"); dis2.Dispose (); }
public static void Subscribe_CallsTransitionNextQueuedItemCorrectNumberOfTimesOverMultipleElapsedIntervals() { var jobStorage = A.Fake<IDurableJobQueue<Incoming, Incoming>>(); var scheduler = new HistoricalScheduler(); var monitor = new DurableJobQueueMonitor<Incoming, Incoming>(jobStorage, 20, DurableJobQueueMonitor.DefaultPollingInterval, scheduler); var queuedItems = Enumerable.Repeat(Item.From(new Incoming() { Id = 1 }), 5) .Concat(new [] { Item.None<Incoming>() }) .Concat(Enumerable.Repeat(Item.From(new Incoming() { Id = 2 }), 5)) .Concat(new [] { Item.None<Incoming>() }).ToArray(); using (var subscription = monitor.Subscribe()) { A.CallTo(() => jobStorage.NextQueuedItem()).ReturnsNextFromSequence(queuedItems); scheduler.AdvanceBy(monitor.PollingInterval); scheduler.AdvanceBy(monitor.PollingInterval); A.CallTo(() => jobStorage.NextQueuedItem()).MustHaveHappened(Repeated.Exactly.Times(queuedItems.Length)); } }
public void Monitor_DoesNotPumpQueueWithZeroSubscribers() { var jobStorage = A.Fake<IDurableJobQueue<Incoming, Incoming>>(); var scheduler = new HistoricalScheduler(); var monitor = new DurableJobQueueMonitor<Incoming, Incoming>(jobStorage, 20, DurableJobQueueMonitor.DefaultPollingInterval, scheduler); A.CallTo(() => jobStorage.NextQueuedItem()).Returns(Item.From(new Incoming() { Id = 1 })); scheduler.AdvanceBy(monitor.PollingInterval.Add(monitor.PollingInterval)); A.CallTo(() => jobStorage.NextQueuedItem()).MustNotHaveHappened(); }
public void AdvanceTo() { var s = new HistoricalScheduler(); var list = new List <Timestamped <int> >(); s.Schedule(Time(0), () => list.Add(new Timestamped <int>(0, s.Now))); s.Schedule(Time(1), () => list.Add(new Timestamped <int>(1, s.Now))); s.Schedule(Time(2), () => list.Add(new Timestamped <int>(2, s.Now))); s.Schedule(Time(10), () => list.Add(new Timestamped <int>(10, s.Now))); s.Schedule(Time(11), () => list.Add(new Timestamped <int>(11, s.Now))); s.AdvanceTo(Time(8)); Assert.AreEqual(Time(8), s.Now); Assert.AreEqual(Time(8), s.Clock); list.AssertEqual( new Timestamped <int>(0, Time(0)), new Timestamped <int>(1, Time(1)), new Timestamped <int>(2, Time(2)) ); s.AdvanceTo(Time(8)); Assert.AreEqual(Time(8), s.Now); Assert.AreEqual(Time(8), s.Clock); list.AssertEqual( new Timestamped <int>(0, Time(0)), new Timestamped <int>(1, Time(1)), new Timestamped <int>(2, Time(2)) ); s.Schedule(Time(7), () => list.Add(new Timestamped <int>(7, s.Now))); s.Schedule(Time(8), () => list.Add(new Timestamped <int>(8, s.Now))); ReactiveAssert.Throws <ArgumentOutOfRangeException>(() => s.AdvanceTo(Time(4))); Assert.AreEqual(Time(8), s.Now); Assert.AreEqual(Time(8), s.Clock); list.AssertEqual( new Timestamped <int>(0, Time(0)), new Timestamped <int>(1, Time(1)), new Timestamped <int>(2, Time(2)) ); s.AdvanceTo(Time(10)); Assert.AreEqual(Time(10), s.Now); Assert.AreEqual(Time(10), s.Clock); list.AssertEqual( new Timestamped <int>(0, Time(0)), new Timestamped <int>(1, Time(1)), new Timestamped <int>(2, Time(2)), new Timestamped <int>(7, Time(8)), new Timestamped <int>(8, Time(8)), new Timestamped <int>(10, Time(10)) ); s.AdvanceTo(Time(100)); Assert.AreEqual(Time(100), s.Now); Assert.AreEqual(Time(100), s.Clock); list.AssertEqual( new Timestamped <int>(0, Time(0)), new Timestamped <int>(1, Time(1)), new Timestamped <int>(2, Time(2)), new Timestamped <int>(7, Time(8)), new Timestamped <int>(8, Time(8)), new Timestamped <int>(10, Time(10)), new Timestamped <int>(11, Time(11)) ); }
public void RefCount() { int side = 0; var scheduler = new HistoricalScheduler (); var source = Observable.Interval (TimeSpan.FromMilliseconds (50), scheduler).Do (i => side++); int result = 0; var published = source.Publish (); var connected = published.RefCount (); var cdis1 = connected.Subscribe (i => result++); scheduler.AdvanceBy (TimeSpan.FromMilliseconds (400)); Assert.IsTrue (result > 0, "#1"); cdis1.Dispose (); // also disconnects. int oldSide = side; scheduler.AdvanceBy (TimeSpan.FromMilliseconds (400)); Assert.AreEqual (oldSide, side, "#2"); // no advance in sequence var cdis2 = connected.Subscribe (i => result++); scheduler.AdvanceBy (TimeSpan.FromSeconds (1)); Assert.IsTrue (side > oldSide, "#3"); cdis2.Dispose (); }
public void Subscribe_TakesNoMoreThanMaximumSpecifiedItemsPerInterval() { int maxToSlurp = 3; var jobStorage = A.Fake<IDurableJobQueue<Incoming, Incoming>>(); A.CallTo(() => jobStorage.NextQueuedItem()).Returns(Item.From(new Incoming() { Id = 1 })); var scheduler = new HistoricalScheduler(); var monitor = new DurableJobQueueMonitor<Incoming, Incoming>(jobStorage, maxToSlurp, DurableJobQueueMonitor.DefaultPollingInterval, scheduler); var completion = new ManualResetEventSlim(false); List<Incoming> incomingItems = new List<Incoming>(); using (var subscription = monitor.Subscribe(publishedItem => { incomingItems.Add(publishedItem); if (incomingItems.Count >= maxToSlurp) { completion.Set(); } })) { scheduler.AdvanceBy(monitor.PollingInterval + TimeSpan.FromTicks(1)); completion.Wait(TimeSpan.FromSeconds(3)); Assert.Equal(maxToSlurp, incomingItems.Count); } }
public void Subscribe_ResumesInProperQueuePositionAfterReadingMaximumDuringInterval() { int maxToSlurp = 3; var jobStorage = A.Fake<IDurableJobQueue<Incoming, Incoming>>(); var scheduler = new HistoricalScheduler(); var monitor = new DurableJobQueueMonitor<Incoming, Incoming>(jobStorage, maxToSlurp, DurableJobQueueMonitor.DefaultPollingInterval, scheduler); List<Incoming> incomingItems = new List<Incoming>(); var queuedItems = Enumerable.Repeat(Item.From(new Incoming() { Id = 1 }), 3) .Concat(new [] { Item.From(new Incoming() { Id = 456 }), Item.From(new Incoming() { Id = 222 }), Item.From(new Incoming() { Id = 8714 }) }) .Concat(Enumerable.Repeat(Item.From(new Incoming() { Id = 5 }), 2)) .Concat(Enumerable.Repeat(Item.From(new Incoming() { Id = 2 }), 4)) .Concat(Enumerable.Repeat(Item.From(new Incoming() { Id = 3 }), 3)) .ToArray(); A.CallTo(() => jobStorage.NextQueuedItem()).ReturnsNextFromSequence(queuedItems); using (var subscription = monitor.Subscribe(publishedItem =>{ incomingItems.Add(publishedItem);})) { scheduler.AdvanceBy(monitor.PollingInterval); scheduler.AdvanceBy(monitor.PollingInterval); Assert.True(queuedItems.Take(maxToSlurp * 2) .Select(item => item.Value) .SequenceEqual(incomingItems, GenericEqualityComparer<Incoming>.ByAllMembers())); } }
public void Sleep_ArgumentChecking() { var s = new HistoricalScheduler(DateTimeOffset.Now); ReactiveAssert.Throws <ArgumentOutOfRangeException>(() => s.Sleep(TimeSpan.FromSeconds(-1))); }
/// <summary> /// Simulates the time of the given loglines on the timer with the given speed /// runs the simulation on a different thread so this method does not block /// </summary> /// <param name="timer"></param> /// <param name="lines"></param> private void SimulateLogLines(HistoricalScheduler scheduler, List<ApacheLogLine> logLines, long speed) { Task t1 = new Task(() => { var lastTime = logLines.First().Date; logLines.ForEach(logLine => { var totalSeconds = (logLine.Date - lastTime).TotalMilliseconds; if (totalSeconds < 0) totalSeconds = 0; //Sometimes it seems not all lines are in the correct order var interval = TimeSpan.FromMilliseconds(totalSeconds); var result = TimeSpan.FromMilliseconds(totalSeconds / (double)speed); lastTime = logLine.Date; Thread.Sleep(result); scheduler.AdvanceBy(interval); }); }); t1.Start(); }
public void Monitor_AwaitsFirstSubscriberBeforePublishing() { var jobStorage = A.Fake<IDurableJobQueue<Incoming, Incoming>>(); var scheduler = new HistoricalScheduler(); var monitor = new DurableJobQueueMonitor<Incoming, Incoming>(jobStorage, 20, DurableJobQueueMonitor.DefaultPollingInterval, scheduler); //X items + a null terminator per each elapsed interval var incomingItems = Enumerable.Repeat(Item.From(new Incoming() { Id = 2 }), 5) .Concat(new[] { Item.None<Incoming>(), Item.None<Incoming>() }).ToArray(); A.CallTo(() => jobStorage.NextQueuedItem()).ReturnsNextFromSequence(incomingItems); //advance the amount of time that would normally cause our queue to be totally flushed scheduler.AdvanceBy(monitor.PollingInterval.Add(monitor.PollingInterval)); using (var subscription = monitor.Subscribe()) { //and now that we have a subscriber, elapse enough time to publish the queue contents scheduler.AdvanceBy(monitor.PollingInterval); scheduler.AdvanceBy(monitor.PollingInterval); //our transition method should have been called X times based on the list of valid items + 1 time for the null on the first scheduled execution, then an additional time w/ null for the next scheduled execution A.CallTo(() => jobStorage.NextQueuedItem()).MustHaveHappened(Repeated.Exactly.Times(incomingItems.Length)); } }
public void TearDown() { this.game = null; this.scheduler = null; }
public void SetUp() { this.scheduler = new HistoricalScheduler(); scheduler.AdvanceTo(GameStartDateTimeOffset); this.game = new Okazuki.TenSecGame.Models.TenSecGame(scheduler); }
public void Monitor_PollsOnSpecifiedInterval(int minutes) { var jobStorage = A.Fake<IDurableJobQueue<Incoming, Incoming>>(); var scheduler = new HistoricalScheduler(); var interval = TimeSpan.FromMinutes(minutes); var monitor = new DurableJobQueueMonitor<Incoming, Incoming>(jobStorage, 20, interval, scheduler); using (var subscription = monitor.Subscribe()) { A.CallTo(() => jobStorage.NextQueuedItem()).Returns(Item.From(new Incoming() { Id = 1 })); //this is a little hacky, but give ourselves a 2 second timespan to make the call against our fake scheduler.AdvanceBy(interval - TimeSpan.FromSeconds(2)); A.CallTo(() => jobStorage.NextQueuedItem()).MustNotHaveHappened(); } }
public void AdvanceBy_ArgumentChecking() { var s = new HistoricalScheduler(); ReactiveAssert.Throws <ArgumentOutOfRangeException>(() => s.AdvanceBy(TimeSpan.FromSeconds(-1))); }