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); } }
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); } }
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."); } } }
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."); } }
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(); } } }
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(); } } }
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); } }
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); } }
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 )); } }
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(); }
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); } } }
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); }); }
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); }); } }
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); }); } }
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); }
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."); } }
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 )); }
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); } }