public void ShouldHandleBlockingAtTheEndOfGrantedInterval()
        {
            var indicator = false;

            using (var master = new MasterTimeSource {
                Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true
            })
                using (var timeSlave = new SlaveTimeSource()
                {
                    Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true
                })
                    using (var timeSink = new MoreComplicatedTimeSink("A"))
                    {
                        var testerThread = new TestThread(() =>
                        {
                            this.Trace();
                            timeSink.ExecuteOnDispatcherThread((ts, ti) =>
                            {
                                this.Trace();
                                Assert.AreEqual(10, ti.Ticks);

                                ts.TimeHandle.ReportBackAndBreak(TimeInterval.Empty);
                            });

                            this.Trace();
                            // here we sleep to make sure that master won't go further
                            Thread.Sleep(5000);

                            this.Trace();
                            Assert.AreEqual(10, master.ElapsedVirtualTime.Ticks);
                            Assert.AreEqual(10, timeSlave.ElapsedVirtualTime.Ticks);
                            indicator = true;

                            this.Trace();
                            timeSink.ExecuteOnDispatcherThread((ts, ti) =>
                            {
                                this.Trace();
                                Assert.AreEqual(0, ti.Ticks);
                                ts.TimeHandle.ReportBackAndContinue(TimeInterval.Empty);
                            });

                            timeSink.ExecuteOnDispatcherThread((ts, ti) =>
                            {
                                this.Trace();
                                Assert.AreEqual(10, ti.Ticks);
                                ts.TimeHandle.ReportBackAndContinue(TimeInterval.Empty);
                            });
                        })
                        {
                            Name = "tester thread"
                        };
                        testerThread.Start();

                        master.RegisterSink(timeSlave);
                        timeSlave.RegisterSink(timeSink);

                        // just to pass the first syncpoint
                        master.Run(1);
                        testerThread.CheckExceptions();

                        this.Trace();
                        master.Run(1);
                        testerThread.CheckExceptions();
                        this.Trace();
                        Assert.IsTrue(indicator);
                        Assert.AreEqual(10, master.ElapsedVirtualTime.Ticks);
                        Assert.AreEqual(10, timeSlave.ElapsedVirtualTime.Ticks);

                        master.Run(1);
                        Assert.AreEqual(20, master.ElapsedVirtualTime.Ticks);
                        Assert.AreEqual(20, timeSlave.ElapsedVirtualTime.Ticks);
                        testerThread.CheckExceptions();
                    }
        }
        public void ShouldUpdateExecutedTimeAfterBlocking()
        {
            var indicator        = false;
            var firstTime        = true;
            var threadToSinkSync = new ManualResetEvent(false);
            var sinkToThreadSync = new ManualResetEvent(false);

            using (var master = new MasterTimeSource {
                Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true
            })
                using (var timeSlave = new SlaveTimeSource()
                {
                    Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true
                })
                {
                    var timeSink = new SimpleTimeSink(1.0, (sts, th, ti) =>
                    {
                        if (firstTime)
                        {
                            Assert.AreEqual(10, ti.Ticks);
                            firstTime    = false;
                            var timeUsed = TimeInterval.FromTicks(ti.Ticks / 2);
                            var timeLeft = ti - timeUsed;

                            sts.ElapsedVirtualTime += timeUsed;

                            th.ReportBackAndBreak(timeLeft);
                            sinkToThreadSync.Set();
                            threadToSinkSync.WaitOne();
                        }
                        else
                        {
                            Assert.AreEqual(5, ti.Ticks);
                            sts.ElapsedVirtualTime += ti;
                            th.ReportBackAndContinue(TimeInterval.Empty);
                        }

                        return(false);
                    });

                    var testerThread = new TestThread(() =>
                    {
                        // wait for the pause
                        sinkToThreadSync.WaitOne();

                        // here we sleep to make sure that master won't go further
                        Thread.Sleep(5000);

                        Assert.AreEqual(5, master.ElapsedVirtualTime.Ticks);
                        Assert.AreEqual(5, timeSlave.ElapsedVirtualTime.Ticks);
                        indicator = true;

                        threadToSinkSync.Set();
                    });
                    testerThread.Start();

                    master.RegisterSink(timeSlave);
                    timeSlave.RegisterSink(timeSink);

                    // just to pass the first syncpoint
                    master.Run(1);
                    testerThread.CheckExceptions();

                    master.Run(1);
                    Assert.IsTrue(indicator);
                    testerThread.CheckExceptions();

                    Assert.AreEqual(10, master.ElapsedVirtualTime.Ticks);
                    Assert.AreEqual(10, timeSlave.ElapsedVirtualTime.Ticks);
                    Assert.AreEqual(10, timeSink.ElapsedVirtualTime.Ticks);
                }
        }