示例#1
0
        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 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
        }
示例#4
0
        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 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();
        }
示例#6
0
        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()));
            }
        }
示例#7
0
        public void Delay2()
        {
            // github issue #12
            var  scheduler = new HistoricalScheduler();
            var  source    = Observable.Interval(TimeSpan.FromSeconds(1), scheduler).Take(5).Timestamp();
            var  delayed   = source.Delay(TimeSpan.FromSeconds(4), scheduler).Timestamp();
            bool done      = false;

            delayed.Subscribe(item => Assert.IsTrue(item.Value.Timestamp < item.Timestamp, "not delayed"), () => done = true);
            scheduler.AdvanceBy(TimeSpan.FromSeconds(3));
            Assert.IsFalse(done, "#1");
            scheduler.AdvanceBy(TimeSpan.FromSeconds(10));
            Assert.IsTrue(done, "#2");
        }
示例#8
0
        public void GroupJoin()
        {
            var scheduler = new HistoricalScheduler();
            var source    = Observable.GroupJoin(
                Observable.Interval(TimeSpan.FromMilliseconds(500), scheduler).Take(10),
                Observable.Interval(TimeSpan.FromMilliseconds(800), scheduler).Delay(TimeSpan.FromSeconds(1), scheduler),
                l => Observable.Interval(TimeSpan.FromMilliseconds(1500), scheduler),
                r => Observable.Interval(TimeSpan.FromMilliseconds(1600), scheduler),
                (l, rob) => new { Left = l, Rights = rob }
                );
            bool done = false;

            bool [,] results = new bool [10, 10];
            bool [] groupDone = new bool [10];
            source.Subscribe(
                v => v.Rights.Subscribe(
                    r => results [v.Left, r] = true,
                    () => groupDone [v.Left] = true),
                () => done = true);
            scheduler.AdvanceBy(TimeSpan.FromSeconds(15));

            Assert.IsTrue(done, "#1");
            Assert.AreEqual(-1, Array.IndexOf(groupDone, false), "#2");
            int [] rstarts = new int [] { 0, 0, 0, 0, 0, 0, 1, 1, 2, 3 };
            int [] rends   = new int [] { 0, 0, 1, 2, 2, 3, 3, 4, 5, 5 };
            for (int l = 0; l < 10; l++)
            {
                for (int r = 0; r < 10; r++)
                {
                    Assert.AreEqual(rstarts [l] <= r && r <= rends [l], results [l, r], String.Format("({0}, {1})", l, r));
                }
            }
        }
示例#9
0
        public void GroupJoin2()
        {
            // almost identical to the previous one, but without delay. And I only test some corner case that could result in difference.
            var scheduler = new HistoricalScheduler();
            var source    = Observable.GroupJoin(
                Observable.Interval(TimeSpan.FromMilliseconds(500), scheduler).Take(10),
                Observable.Interval(TimeSpan.FromMilliseconds(800), scheduler),
                l => Observable.Interval(TimeSpan.FromMilliseconds(1500), scheduler),
                r => Observable.Interval(TimeSpan.FromMilliseconds(1600), scheduler),
                (l, rob) => new { Left = l, Rights = rob }
                );

            bool done = false;

            bool [,] results = new bool [10, 10];
            bool [] groupDone = new bool [10];
            source.Subscribe(
                v => v.Rights.Subscribe(
                    r => results [v.Left, r] = true,
                    () => groupDone [v.Left] = true),
                () => done = true);
            scheduler.AdvanceBy(TimeSpan.FromSeconds(15));

            Assert.IsTrue(done, "#1");
            // this value could be published *IF* unsubscription is
            // handled *after* 7 is published as a left value.
            // Rx does not publish this, likely means a right value
            // at the end moment of rightDuration is *not* published
            // ... so we do that too.
            Assert.IsFalse(results [7, 2], "#2");
        }
示例#10
0
        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);
            }
        }
示例#11
0
        public void Subscribe_PublishesExactSequenceOfItemsAsTheyArePulledFromDurableStorage()
        {
            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(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.Concat(new [] { Item.None <Incoming>() }).ToArray());

            using (var subscription = monitor.Subscribe(publishedItem => { incomingItems.Add(publishedItem); }))
            {
                scheduler.AdvanceBy(monitor.PollingInterval);

                Assert.True(queuedItems.Select(item => item.Value).SequenceEqual(incomingItems, GenericEqualityComparer <Incoming> .ByAllMembers()));
            }
        }
示例#12
0
        public void Throttle2()
        {
            var subject   = new Subject <string> ();
            var scheduler = new HistoricalScheduler();
            var input     = (from text in subject select text).Throttle(TimeSpan.FromSeconds(0.5), scheduler).Timestamp(scheduler);
            var sw        = new StringWriter();

            input.Subscribe(
                v => sw.WriteLine("THR: {0} at {1:ss.fff} timer:{2:ss.fff}", v.Value, v.Timestamp, scheduler.Now),
                () => sw.WriteLine("THR: completed: {0:ss.fff}", scheduler.Now));

            int [] vals = { 100, 600, 300, 600, 400, 900, 500, 800 };
            for (int i = 0; i < 10; i++)
            {
                var val = vals [i % vals.Length];
                scheduler.AdvanceBy(TimeSpan.FromMilliseconds(val));
                subject.OnNext(val.ToString());
            }
            subject.OnCompleted();
            string expected = @"THR: 100 at 00.600 timer:00.600
THR: 300 at 01.500 timer:01.500
THR: 400 at 02.500 timer:02.500
THR: 900 at 03.400 timer:03.400
THR: 500 at 03.900 timer:03.900
THR: 100 at 04.800 timer:04.800
THR: 600 at 04.900 timer:04.900
THR: completed: 04.900
".Replace("\r\n", "\n");

            Assert.AreEqual(expected, sw.ToString().Replace("\r\n", "\n"), "#1");
        }
        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 No_Nested_AdvanceBy()
        {
            var s = new HistoricalScheduler();

            s.Schedule(() => s.AdvanceBy(TimeSpan.FromSeconds(1)));

            ReactiveAssert.Throws <InvalidOperationException>(() => s.Start());
        }
示例#15
0
 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 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");
 }
示例#17
0
        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");
        }
示例#18
0
        public void TimeoutOutOfTime()
        {
            var    scheduler = new HistoricalScheduler();
            var    source    = Observable.Interval(TimeSpan.FromSeconds(1), scheduler).Take(2).Timeout(TimeSpan.FromSeconds(1), scheduler);
            string s         = null;

            source.Subscribe(v => s += v, ex => s += "error:" + ex.GetType(), () => s += "done");
            scheduler.AdvanceBy(TimeSpan.FromSeconds(5));
            Assert.AreEqual("error:System.TimeoutException", s, "#1");
        }
示例#19
0
        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");
        }
示例#20
0
        public void Amb()
        {
            var scheduler = new HistoricalScheduler();
            var s1        = Observable.Range(1, 3).Delay(TimeSpan.FromMilliseconds(500), scheduler);
            var s2        = Observable.Range(4, 3);
            var e         = s1.Amb(s2).ToEnumerable().ToArray();

            scheduler.AdvanceBy(TimeSpan.FromSeconds(1));
            Assert.AreEqual(new int [] { 4, 5, 6 }, e, "#1");
        }
示例#21
0
        IEnumerable <IObservable <long> > IntervalSelectTakeDoEnumerable(HistoricalScheduler scheduler, List <string> l, TextWriter sw)
        {
            DateTimeOffset start = scheduler.Now;

            for (int i = 0; i < 5; i++)
            {
                int x = i;
                scheduler.AdvanceBy(TimeSpan.FromMilliseconds(150));
                yield return(Observable.Interval(TimeSpan.FromMilliseconds(100), scheduler)
#if false
                             .Select(v => x * 10 + v).Take(5)
#else
                             // FIXME: this select should work, but it does not give expected "i" or "x" values, likely due to some mcs bug regarding local variable volatility...
                             // ... So I used out-of-scope value comparison here.
                             .Select(v => (long)((scheduler.Now - start).TotalMilliseconds / 20) + v).Take(5)
#endif
                             .Do(v => l.Add(String.Format("{0:ss.fff}: {1} {2}", scheduler.Now, i, v)), () => sw.WriteLine()));

                scheduler.AdvanceBy(TimeSpan.FromMilliseconds(50));
            }
        }
示例#22
0
        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));
            }
        }
示例#23
0
        public void WindowTimeSpans2()
        {
            var scheduler = new HistoricalScheduler();
            var interval  = TimeSpan.FromMilliseconds(100);
            var span      = TimeSpan.FromMilliseconds(500);
            var shift     = TimeSpan.FromMilliseconds(300);
            var total     = TimeSpan.FromMilliseconds(1500);

            var sw = new StringWriter()
            {
                NewLine = "\n"
            };
            var sources = Observable.Interval(interval, scheduler).Take(15).Window(span, shift, scheduler);
            int windows = 0;

            bool [] windowDone = new bool [6];
            sources.Subscribe(source => {
                int w = windows++;
                source.Subscribe(v => sw.WriteLine("{0:ss.fff} {1} [{2}]", scheduler.Now, v, w), () => windowDone [w] = true);
            }, () => sw.WriteLine("done"));
            scheduler.AdvanceBy(total);

            string expected = @"00.100 0 [0]
				00.200 1 [0]
				00.300 2 [0]
				00.300 2 [1]
				00.400 3 [0]
				00.400 3 [1]
				00.500 4 [1]
				00.600 5 [1]
				00.600 5 [2]
				00.700 6 [1]
				00.700 6 [2]
				00.800 7 [2]
				00.900 8 [2]
				00.900 8 [3]
				01.000 9 [2]
				01.000 9 [3]
				01.100 10 [3]
				01.200 11 [3]
				01.200 11 [4]
				01.300 12 [3]
				01.300 12 [4]
				01.400 13 [4]
				01.500 14 [4]
				01.500 14 [5]
				done
				"                .Replace("\t", "").Replace("\r", "");

            Assert.AreEqual(expected, sw.ToString(), "#1");
            Assert.AreEqual(-1, Array.IndexOf(windowDone, false), "#2");
        }
示例#24
0
        public void Throttle()
        {
            var  scheduler = new HistoricalScheduler();
            var  source    = Observable.Range(1, 3).Concat(Observable.Return(2).Delay(TimeSpan.FromMilliseconds(100), scheduler)).Throttle(TimeSpan.FromMilliseconds(50), scheduler);
            bool done      = false;
            var  l         = new List <int> ();
            var  dis       = source.Subscribe(v => l.Add(v), () => done = true);

            scheduler.AdvanceBy(TimeSpan.FromSeconds(1));
            Assert.IsTrue(done, "#1");
            Assert.AreEqual(new int [] { 3, 2 }, l.ToArray(), "#2");
            dis.Dispose();
        }
 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 async Task DoesntSaveDraftForNonEditingComment()
        {
            var scheduler = new HistoricalScheduler();
            var drafts    = Substitute.For <IMessageDraftStore>();
            var target    = CreateTarget(drafts: drafts, scheduler: scheduler);

            await target.AddPlaceholder(false);

            target.Comments[0].Body = "Edited comment.";

            scheduler.AdvanceBy(TimeSpan.FromSeconds(1));

            await drafts.DidNotReceiveWithAnyArgs().UpdateDraft <CommentDraft>(null, null, null);
        }
示例#27
0
        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");
        }
示例#28
0
        public void SelectManyObservable()
        {
            var scheduler = new HistoricalScheduler();
            Func <int, IObservable <int> > f = x => Observable.Return(x).Delay(TimeSpan.FromSeconds(1), scheduler);
            var  source = Observable.Range(0, 5).SelectMany(n => f(n));
            var  l      = new List <int> ();
            bool done   = false;
            var  dis    = source.Subscribe(v => l.Add(v), () => done = true);

            Assert.IsFalse(done, "#1");
            scheduler.AdvanceBy(TimeSpan.FromSeconds(1));
            Assert.AreEqual(new int [] { 0, 1, 2, 3, 4 }, l.ToArray(), "#2");
            Assert.IsTrue(done, "#3");
        }
示例#29
0
        [Test]         // some practical test
        public void IntervalSelectTakeDo()
        {
            var scheduler = new HistoricalScheduler();
            var l         = new List <string> ();
            var sw        = new StringWriter()
            {
                NewLine = "\n"
            };

            foreach (var o in IntervalSelectTakeDoEnumerable(scheduler, l, TextWriter.Null))
            {
                o.Subscribe(v => {});                  // dummy
            }
            scheduler.AdvanceBy(TimeSpan.FromSeconds(3));
            l.Sort();
            foreach (var s in l)
            {
                sw.WriteLine(s);
            }

            string expected = @"00.250: 1 12
				00.350: 1 18
				00.450: 2 22
				00.450: 2 24
				00.550: 2 28
				00.550: 2 30
				00.650: 3 32
				00.650: 3 34
				00.650: 3 36
				00.750: 3 38
				00.750: 3 40
				00.850: 4 42
				00.850: 4 44
				00.850: 4 46
				00.950: 4 48
				00.950: 4 50
				01.050: 5 52
				01.050: 5 54
				01.050: 5 56
				01.150: 5 58
				01.150: 5 60
				01.250: 5 64
				01.250: 5 66
				01.350: 5 70
				01.450: 5 76
				"                .Replace("\r", "").Replace("\t", "");

            Assert.AreEqual(expected, sw.ToString(), "#1");
        }
示例#30
0
        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();
        }
示例#31
0
        public void Delay()
        {
            var  scheduler = new HistoricalScheduler();
            var  source    = Observable.Return(2).Delay(TimeSpan.FromMilliseconds(50), scheduler).Materialize();
            var  l         = new List <NotificationKind> ();
            bool done      = false;

            source.Subscribe(v => l.Add(v.Kind), () => done = true);
            scheduler.AdvanceBy(TimeSpan.FromMilliseconds(50));
            Assert.IsTrue(done, "#2");
            Assert.AreEqual(new NotificationKind [] {
                NotificationKind.OnNext,
                NotificationKind.OnCompleted
            }, l.ToArray(), "#3");
        }
        static void Main()
        {
            var scheduler    = new HistoricalScheduler();
            var interval     = TimeSpan.FromSeconds(0.75);
            var subscription =
                Observable.Interval(interval, scheduler)
                .TimeInterval(scheduler)
                .Scan(TimeSpan.Zero, (acc, cur) => acc + cur.Interval)
                .Subscribe(DrawBall);

            scheduler.AdvanceBy(TimeSpan.FromSeconds(5));
            subscription.Dispose();
            Console.WriteLine("Press any key...");
            Console.ReadKey(true);
        }
        public void CancelQueuedAndWaitForExecutingJobsToComplete_WaitsOnJobs()
        {
            var scheduler = new HistoricalScheduler();
            var queue     = _monitoredJobQueueFactory(new HistoricalScheduler(), _durableQueueFactory);

            foreach (var input in _fixture.CreateMany <TInput>(30))
            {
                queue.AddJob(input);
            }

            scheduler.AdvanceBy(TimeSpan.FromSeconds(30));
            queue.CancelQueuedAndWaitForExecutingJobsToComplete(TimeSpan.FromSeconds(5));

            Assert.True(queue.RunningCount == 0 && queue.QueuedCount == 0);
        }
示例#34
0
        public void GroupJoinRightSequenceError()
        {
            var scheduler = new HistoricalScheduler();
            var source    = Observable.GroupJoin(
                Observable.Interval(TimeSpan.FromMilliseconds(800), scheduler).Delay(TimeSpan.FromSeconds(1), scheduler),
                Observable.Throw <int> (new SystemException()),
                l => Observable.Interval(TimeSpan.FromMilliseconds(1500), scheduler),
                r => Observable.Interval(TimeSpan.FromMilliseconds(1600), scheduler),
                (l, rob) => new { Left = l, Rights = rob }
                );
            string s = null;

            source.Subscribe(v => s += v, ex => s += "error:" + ex.GetType(), () => s += "done");
            scheduler.AdvanceBy(TimeSpan.FromSeconds(15));
            Assert.AreEqual("error:System.SystemException", s, "#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 ();
 }
示例#36
0
        public void GroupJoinRightDurationError()
        {
            var scheduler = new HistoricalScheduler();
            var source    = Observable.GroupJoin(
                Observable.Interval(TimeSpan.FromMilliseconds(500), scheduler).Delay(TimeSpan.FromSeconds(1), scheduler),
                Observable.Interval(TimeSpan.FromMilliseconds(800), scheduler).Delay(TimeSpan.FromSeconds(1), scheduler),
                l => Observable.Interval(TimeSpan.FromMilliseconds(1600), scheduler),
                r => Observable.Throw <int> (new SystemException()),
                (l, rob) => new { Left = l, Rights = rob }
                );
            string s = null;

            source.Subscribe(v => {}, ex => s += "error:" + ex.GetType(), () => s += "done");
            scheduler.AdvanceBy(TimeSpan.FromSeconds(15));
            // LAMESPEC: shouldn't this also raise OnError() ? GroupByUntil() does so.
            Assert.AreEqual("error:System.SystemException", s, "#1");
        }
        public async Task Updates_Draft_When_Body_Changes()
        {
            var scheduler  = new HistoricalScheduler();
            var draftStore = Substitute.For <IMessageDraftStore>();
            var target     = CreateTarget(draftStore: draftStore, timerScheduler: scheduler);

            await InitializeAsync(target);

            target.Body = "Body changed.";

            await draftStore.DidNotReceiveWithAnyArgs().UpdateDraft <PullRequestReviewDraft>(null, null, null);

            scheduler.AdvanceBy(TimeSpan.FromSeconds(1));

            await draftStore.Received().UpdateDraft(
                "pr-review|https://github.com/owner/repo|5",
                string.Empty,
                Arg.Is <PullRequestReviewDraft>(x => x.Body == "Body changed."));
        }
        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 ();
        }
示例#39
0
        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));
            }
        }
 /// <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();
 }
示例#41
0
        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);
            }
        }
示例#42
0
        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()));
            }
        }
示例#43
0
        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();
            }
        }
示例#44
0
        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();
        }