public void Change_ViaTimeSpan_DoesNotAllow_Negative_Timeout()
        {
            SimpleTimerHarness   harness = new SimpleTimerHarness();
            VersionedTimer <int> timer   = new VersionedTimer <int>(123, harness.Callback);

            using ( timer )
            {
                // Smallest negative possible.
                Assert2.Throws <ArgumentException>(() =>
                {
                    timer.Change(TimeSpan.FromTicks(-1), Timeout.InfiniteTimeSpan, 0);
                });

                // Edge case near -1 ms (a special value), low side.
                Assert2.Throws <ArgumentException>(() =>
                {
                    timer.Change(nearOneMsPlus, Timeout.InfiniteTimeSpan, 0);
                });

                // Edge case near -1 ms (a special value), high side.
                Assert2.Throws <ArgumentException>(() =>
                {
                    timer.Change(nearOneMsMinus, Timeout.InfiniteTimeSpan, 0);
                });

                // More negative.
                Assert2.Throws <ArgumentException>(() =>
                {
                    timer.Change(MSecs(-2), Timeout.InfiniteTimeSpan, 0);
                });
            }
        }
        public void RepeatedPostpone_MultiShot()
        {
            int count = 200;
            SimpleTimerHarness   harness = new SimpleTimerHarness();
            VersionedTimer <int> timer   = new VersionedTimer <int>(456, harness.Callback);

            using ( timer )
            {
                for (int i = 0; i < count; i++)
                {
                    timer.Change(1000, 100, i);

                    Thread.Sleep(50);
                }

                // Verify the timer fires repeatedly.
                for (int i = 0; i < 10; i++)
                {
                    harness.Wait();
                }

                timer.Change(Timeout.Infinite, Timeout.Infinite, 0);

                Assert.AreEqual(10, harness.Callbacks);
                Assert.AreEqual(456, harness.ObservedState);
                Assert.AreEqual(count - 1, harness.ObservedVersion);
            }
        }
        public void Change_ViaTimeSpan_Allows_Zero()
        {
            SimpleTimerHarness   harness = new SimpleTimerHarness();
            VersionedTimer <int> timer   = new VersionedTimer <int>(123, harness.Callback);

            using ( timer )
            {
                timer.Change(TimeSpan.Zero, Timeout.InfiniteTimeSpan, 1);
                timer.Change(TimeSpan.Zero, TimeSpan.Zero, 2);
            }
        }
Example #4
0
        public void Change_ViaInts_AllowsInfinite()
        {
            SimpleTimerHarness   harness = new SimpleTimerHarness();
            VersionedTimer <int> timer   = new VersionedTimer <int>(123, harness.Callback);

            using ( timer )
            {
                timer.Change(10, Timeout.Infinite, 0);
                timer.Change(Timeout.Infinite, Timeout.Infinite, 1);
            }
        }
Example #5
0
        public void VerifyDisposalNotify_Pending()
        {
            for (int i = 0; i < 100; i++)
            {
                VersionedTimer <int> timer;

                using (var disposeNotify = new AutoResetEvent(false))
                    using (var callbackCanContinue = new AutoResetEvent(false))
                        using (var callbackStarted = new AutoResetEvent(false))
                        {
                            VersionedTimerCallback <int> callback = (int state, long version) =>
                            {
                                callbackStarted.Set();
                                callbackCanContinue.WaitOne(10 * 1000);
                            };

                            timer = new VersionedTimer <int>(123, callback);

                            timer.Change(10, Timeout.Infinite, 0);

                            Assert.IsTrue(callbackStarted.WaitOne(5 * 1000), "Timer did not fire.");

                            timer.Dispose(disposeNotify);

                            callbackCanContinue.Set();

                            Assert.IsTrue(disposeNotify.WaitOne(5 * 1000), "Timer disposal notification did not fire.");
                        }
            }
        }
Example #6
0
        public void DisposeFromCallback()
        {
            for (int i = 0; i < 100; i++)
            {
                AutoResetEvent       timerDone = new AutoResetEvent(false);
                VersionedTimer <int> timer     = null;
                bool failed = false;

                VersionedTimerCallback <int> callback = (int state, long version) =>
                {
                    try
                    {
                        timer.Dispose();
                        timerDone.Set();
                    }
                    catch
                    {
                        failed = true;
                        throw;
                    }
                };

                timer = new VersionedTimer <int>(123, callback);

                timer.Change(10, Timeout.Infinite, 1);

                Assert.IsTrue(timerDone.WaitOne(5 * 1000), "Timer did not fire");
                Assert.IsFalse(failed, "Timer crashed during callback.");
            }
        }
Example #7
0
        public void SimpleParallel()
        {
            var harness = new ParallelTimerObserver();
            var timers  = new List <VersionedTimer <int> >();
            int expectedParallelism;
            int dummy;

            ThreadPool.GetMinThreads(out expectedParallelism, out dummy);
            harness.SetExpectedParallelism(expectedParallelism);

            for (int i = 0; i < expectedParallelism; i++)
            {
                var timer = new VersionedTimer <int>(0, harness.Callback);
                timers.Add(timer);
            }

            try
            {
                foreach (var timer in timers)
                {
                    timer.Change(50, Timeout.Infinite, 0);
                }

                Assert.IsTrue(harness.Wait(5000), "Timers failed to fire.");
            }
            finally
            {
                harness.EnsureReleased();

                foreach (var timer in timers)
                {
                    timer.Dispose();
                }
            }
        }
Example #8
0
        public void DisposeDuringCallbackFromUser()
        {
            for (int i = 0; i < 100; i++)
            {
                VersionedTimer <int> timer;

                using (var callbackCanContinue = new AutoResetEvent(false))
                    using (var callbackStarted = new AutoResetEvent(false))
                    {
                        VersionedTimerCallback <int> callback = (int state, long version) =>
                        {
                            callbackStarted.Set();
                            callbackCanContinue.WaitOne(10 * 1000);
                        };

                        timer = new VersionedTimer <int>(0, callback);
                        timer.Change(10, Timeout.Infinite, 1);

                        Assert.IsTrue(callbackStarted.WaitOne(5 * 1000), "Timer never fired.");

                        timer.Dispose();

                        callbackCanContinue.Set();
                    }
            }
        }
Example #9
0
        public void Change_ViaInts_SingleShot_AllowsPositive()
        {
            SimpleTimerHarness   harness = new SimpleTimerHarness();
            VersionedTimer <int> timer   = new VersionedTimer <int>(123, harness.Callback);

            using ( timer )
            {
                timer.Change(100, Timeout.Infinite, 1);
                timer.Change(200, Timeout.Infinite, 2);

                for (int i = 1; i <= 100; i++)
                {
                    timer.Change(100 + i, Timeout.Infinite, 1);
                }

                timer.Change(int.MaxValue, Timeout.Infinite, 1);
            }
        }
Example #10
0
        public void Change_ViaTimeSpan_MultiShot_Allows_Positive()
        {
            SimpleTimerHarness   harness = new SimpleTimerHarness();
            VersionedTimer <int> timer   = new VersionedTimer <int>(123, harness.Callback);

            using ( timer )
            {
                timer.Change(MSecs(100), MSecs(100), 1);
                timer.Change(MSecs(100), MSecs(200), 1);

                for (int i = 1; i <= 100; i++)
                {
                    timer.Change(MSecs(100), MSecs(100 + i), 1);
                }

                timer.Change(MSecs(100), MSecs(int.MaxValue), 1);
            }
        }
Example #11
0
        public void MultiShot()
        {
            SimpleTimerHarness harness = new SimpleTimerHarness();
            Stopwatch          watch   = new Stopwatch();

            watch.Start();
            watch.Reset();

            using (var timer = new VersionedTimer <int>(123, harness.Callback))
            {
                harness.ExpectDelays(75, 150);
                timer.Change(75, 150, 1);
                watch.Start();

                Thread.Sleep(75 + 150 * 4);

                for (int i = 1; i <= 5; i++)
                {
                    Assert.IsTrue(harness.Wait(), string.Format("Timer period #{0} never fired.", i));
                }

                timer.Change(Timeout.Infinite, Timeout.Infinite, 2);
                watch.Stop();

                TimeSpan elapsed = watch.Elapsed;

                int numFirings = (int)((elapsed.TotalMilliseconds - 75.0) / 150.0) + 1;

                Assert.AreEqual(123, harness.ObservedState, 123, "Timer fired with wrong state.");
                Assert.AreEqual(1, harness.ObservedVersion, "Timer fired with wrong version.");
                Assert.AreEqual(numFirings, harness.Callbacks, "Timer fired wrong number of times.");
                Assert.AreEqual(0, harness.TimeoutError.TotalMilliseconds, 30, "Timer timeout was inaccurate.");
                Assert.AreEqual(0, harness.PeriodErrors.Average(x => x.TotalMilliseconds), 30, "Timer period was inaccurate.");
                Assert.AreEqual(0, harness.PeriodErrors.Max(x => x.TotalMilliseconds), 30, "Timer period was inaccurate.");

                Trace.WriteLine(string.Format(
                                    "{0} callbacks occurred in {1:0.000} ms.",
                                    harness.Callbacks, elapsed.TotalMilliseconds
                                    ));
            }
        }
Example #12
0
        public void Dispose_AllowsMultipleDisposes()
        {
            SimpleTimerHarness   harness = new SimpleTimerHarness();
            VersionedTimer <int> timer   = new VersionedTimer <int>(123, harness.Callback);

            timer.Change(10, Timeout.Infinite, 0);

            Assert.IsTrue(harness.Wait(), "Timer did not fire.");

            timer.Dispose();
            timer.Dispose();
        }
Example #13
0
        public void DisposeAfterDisableMultiShot()
        {
            for (int i = 0; i < 100; i++)
            {
                VersionedTimer <int> timer;
                SimpleTimerHarness   harness = new SimpleTimerHarness();

                timer = new VersionedTimer <int>(123, harness.Callback);

                using ( timer )
                {
                    timer.Change(10, 10, 0);

                    Assert.IsTrue(harness.Wait(), "Timer did not fire.");
                    Assert.IsTrue(harness.Wait(), "Timer did not fire.");
                    Assert.IsTrue(harness.Wait(), "Timer did not fire.");

                    timer.Change(Timeout.Infinite, Timeout.Infinite, 0);
                }
            }
        }
Example #14
0
        public void VerifyObjectDisposedException()
        {
            VersionedTimer <int> timer;
            SimpleTimerHarness   harness = new SimpleTimerHarness();

            timer = new VersionedTimer <int>(123, harness.Callback);

            try
            {
                timer.Change(10, Timeout.Infinite, 0);
                Assert.IsTrue(harness.Wait(), "Timer did not fire.");
            }
            finally
            {
                timer.Dispose();
            }

            Assert2.Throws <ObjectDisposedException>(() =>
            {
                timer.Change(100, 100, 1);
            });
        }
Example #15
0
        public void Change_ViaTimeSpan_DoesNotAllow_ExcessiveSpan()
        {
            SimpleTimerHarness   harness = new SimpleTimerHarness();
            VersionedTimer <int> timer   = new VersionedTimer <int>(123, harness.Callback);

            using ( timer )
            {
                Assert2.Throws <ArgumentException>(() =>
                {
                    timer.Change(excessiveSpan, Timeout.InfiniteTimeSpan, 0);
                });

                Assert2.Throws <ArgumentException>(() =>
                {
                    timer.Change(TimeSpan.Zero, excessiveSpan, 0);
                });

                Assert2.Throws <ArgumentException>(() =>
                {
                    timer.Change(excessiveSpan, excessiveSpan, 0);
                });
            }
        }
Example #16
0
        public void Change_ViaInts_DoesNotAllowNegative_Period()
        {
            SimpleTimerHarness   harness = new SimpleTimerHarness();
            VersionedTimer <int> timer   = new VersionedTimer <int>(123, harness.Callback);

            using ( timer )
            {
                Assert2.Throws <ArgumentException>(() =>
                {
                    timer.Change(0, -2, 0);
                });

                Assert2.Throws <ArgumentException>(() =>
                {
                    timer.Change(0, -3, 0);
                });

                Assert2.Throws <ArgumentException>(() =>
                {
                    timer.Change(0, int.MinValue, 0);
                });
            }
        }
Example #17
0
        public void DisposeWhilePending()
        {
            SimpleTimerHarness harness = new SimpleTimerHarness();

            for (int i = 0; i < 1000; i++)
            {
                VersionedTimer <int> timer;

                timer = new VersionedTimer <int>(123, harness.Callback);

                timer.Change(1000, Timeout.Infinite, 1);

                timer.Dispose();
            }

            Thread.Sleep(1500);

            Assert.AreEqual(harness.Callbacks, 0);
        }
Example #18
0
        public void SingleShot()
        {
            SimpleTimerHarness harness = new SimpleTimerHarness();

            using (var timer = new VersionedTimer <int>(123, harness.Callback))
            {
                harness.ExpectDelays(100, Timeout.Infinite);
                timer.Change(100, Timeout.Infinite, 1);

                // Give the timer some rope to hang itself by if it's accidentally going to fire
                // multiple times.
                Thread.Sleep(500);

                Assert.IsTrue(harness.Wait(), "Timer never fired.");
                Assert.AreEqual(123, harness.ObservedState, "Timer fired with wrong state.");
                Assert.AreEqual(1, harness.ObservedVersion, "Timer fired with wrong version.");
                Assert.AreEqual(1, harness.Callbacks, "Timer fired wrong number of times.");
                Assert.AreEqual(0, harness.TimeoutError.TotalMilliseconds, 30, "Timer timeout was inaccurate.");
            }
        }
Example #19
0
        public void DemonstrateUnreliableRecall()
        {
            int sleepTime   = 15;
            var timer       = new VersionedTimer <int>(0, Callback);
            var runtime     = Stopwatch.StartNew();
            var sleepPhaser = new SleepPhaser(sleepTime, -1.5, 1.5, 0.05);

            bool foundRepro;

            for (long ver = 0; ; ver++)
            {
                sleepPhaser.Sleep();

                lock (this)
                {
                    foundRepro = this.reproduced;
                    timer.Change(sleepTime, Timeout.Infinite, ver);
                    this.currentVer = ver;
                }

                if (foundRepro)
                {
                    break;
                }
                else if (runtime.ElapsedMilliseconds > 2 * 60 * 1000)
                {
                    break;
                }
            }

            Assert.IsTrue(reproduced, "Failed to reproduce the unreliable recall.");

            Trace.WriteLine(string.Format(
                                "Reproduced after {0} versions, using sleep phase of {1:0.0} ms vs expected timeout of {2} ms",
                                this.currentVer,
                                sleepPhaser.Current,
                                sleepTime
                                ));
        }
Example #20
0
        public void Change_ViaTimeSpan_SingleShot_Allows_Positive()
        {
            SimpleTimerHarness   harness = new SimpleTimerHarness();
            VersionedTimer <int> timer   = new VersionedTimer <int>(123, harness.Callback);

            using ( timer )
            {
                timer.Change(MSecs(100), Timeout.InfiniteTimeSpan, 1);
                timer.Change(MSecs(200), Timeout.InfiniteTimeSpan, 1);

                for (int i = 1; i <= 100; i++)
                {
                    timer.Change(MSecs(100 + i), Timeout.InfiniteTimeSpan, 1);
                }

                timer.Change(MSecs(int.MaxValue), Timeout.InfiniteTimeSpan, 1);

                timer.Change(VTimeout.MaxTimeout, Timeout.InfiniteTimeSpan, 1);
                timer.Change(TimeSpan.Zero, VTimeout.MaxTimeout, 1);
                timer.Change(VTimeout.MaxTimeout, VTimeout.MaxTimeout, 1);
            }
        }