1 //
2 // Copyright (c) 2010-2018 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using System.Collections.Generic;
9 using System.Threading;
10 using Antmicro.Renode.Time;
11 using Antmicro.Renode.UnitTests.Utilities;
12 using NUnit.Framework;
13 
14 namespace UnitTests
15 {
16     [TestFixture]
17     public class TimeHandleTests
18     {
19         [SetUp]
SetUp()20         public void SetUp()
21         {
22             tsource = new MockTimeSource();
23             var mockSink = new MockTimeSink();
24             handle = new TimeHandle(tsource, mockSink);
25             mockSink.TimeHandle = handle;
26             tester = new ThreadSyncTester();
27 
28             sourceThread = tester.ObtainThread("source");
29             sinkThread = tester.ObtainThread("sink");
30             externalThread = tester.ObtainThread("external");
31 
32             interval = TimeInterval.FromTicks(1000);
33 
34             SetSourceSideActiveOnExternal(true);
35         }
36 
37         [TearDown]
TearDown()38         public void TearDown()
39         {
40             Assert.IsTrue(tester.ExecutionFinished, "Did you forget to call `Finish`?");
41             tester.Dispose();
42         }
43 
44         [Test]
ShouldHandleProgressIncludingResiduum()45         public void ShouldHandleProgressIncludingResiduum()
46         {
47             GrantOnSource();
48 
49             RequestOnSink().ShouldFinish();
50             ContinueOnSink(TimeInterval.FromTicks(100));
51 
52             WaitOnSource().ShouldFinish();
53             GrantOnSource();
54 
55             RequestOnSink().ShouldFinish();
56             // report progress: a granted quantum + residuum from the previous run
57             ReportProgressOnSink(TimeInterval.FromTicks(1100));
58             ContinueOnSink();
59 
60             WaitOnSource().ShouldFinish();
61             Finish();
62         }
63 
64         [Test]
WaitShouldNotBlockIfThereWasNoRequest()65         public void WaitShouldNotBlockIfThereWasNoRequest()
66         {
67             GrantOnSource();
68             WaitOnSource().ShouldFinish();
69             // we expect 'WaitUntilDone' to finish with false if sink has not interacted with the handle yet
70             ShouldWaitReturn(false, false, TimeInterval.Empty);
71             Finish();
72         }
73 
74         [Test]
RequestShouldBlockWaitingForGrant()75         public void RequestShouldBlockWaitingForGrant()
76         {
77             var r = RequestOnSink().ShouldBlock();
78             GrantOnSource();
79             r.ShouldFinish();
80             ShouldRequestReturn(true, interval);
81             Finish();
82         }
83 
84         [Test]
WaitShouldBlockWaitingForReport()85         public void WaitShouldBlockWaitingForReport()
86         {
87             var r = RequestOnSink().ShouldBlock();
88             GrantOnSource();
89             r.ShouldFinish();
90             ShouldRequestReturn(true, interval);
91             WaitOnSource().ShouldBlock();
92             Finish();
93         }
94 
95         [Test]
WaitShouldBlockWaitingForReport2()96         public void  WaitShouldBlockWaitingForReport2()
97         {
98             GrantOnSource();
99             RequestOnSink().ShouldFinish();
100             ShouldRequestReturn(true, interval);
101             WaitOnSource().ShouldBlock();
102             Finish();
103         }
104 
105         [Test]
HandleShouldNotBeReadyForNewTimeGrantAfterDispose()106         public void HandleShouldNotBeReadyForNewTimeGrantAfterDispose()
107         {
108             DisposeOnExternal();
109             Assert.IsFalse(handle.IsReadyForNewTimeGrant);
110             Finish();
111         }
112 
113 #if DEBUG
114 // those tests assume DebugHelper.Assert to throw an exception; asserts are supported in debug mode only, so it would fail in non-debug mode
115 
116         [Test]
ShouldNotAllowToGrantTimeAfterDispose()117         public void ShouldNotAllowToGrantTimeAfterDispose()
118         {
119             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
120             {
121                 DisposeOnExternal();
122                 GrantOnSource();
123                 Finish();
124             });
125         }
126 
127         [Test]
ShouldNotAllowToGrantTwiceInARow()128         public void ShouldNotAllowToGrantTwiceInARow()
129         {
130             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
131             {
132                 GrantOnSource();
133                 GrantOnSource();
134                 Finish();
135             });
136         }
137 
138         [Test]
ShouldNotAllowToWaitBeforeGranting()139         public void ShouldNotAllowToWaitBeforeGranting()
140         {
141             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
142             {
143                 WaitOnSource().ShouldBlock(); // this should block here is a hack not to finish this test too soon
144                 Finish();
145             });
146         }
147 
148         [Test]
ShouldNotAllowToGrantTimeToBlockedHandle()149         public void ShouldNotAllowToGrantTimeToBlockedHandle()
150         {
151             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
152             {
153                 GrantOnSource();
154                 RequestOnSink();
155                 BreakOnSink();
156                 WaitOnSource();
157                 GrantOnSource().ShouldBlock(); // this is illegal; sink must call UnblockHandle (as a result of RequestTimeInterval) first!
158                 Finish();
159             });
160         }
161 
162         [Test]
ShouldNotAllowToCallWaitTwiceAfterReportingContinue()163         public void ShouldNotAllowToCallWaitTwiceAfterReportingContinue()
164         {
165             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
166             {
167                 GrantOnSource();
168                 RequestOnSink();
169                 ContinueOnSink();
170                 WaitOnSource();
171                 WaitOnSource().ShouldBlock(); // this should block here is a hack not to finish this test too soon
172                 Finish();
173             });
174         }
175 
176         [Test]
ShouldNotAllowToCallGrantAfterReportingBreak()177         public void ShouldNotAllowToCallGrantAfterReportingBreak()
178         {
179             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
180             {
181                 GrantOnSource();
182                 RequestOnSink();
183                 BreakOnSink();
184                 WaitOnSource();
185                 GrantOnSource();
186                 Finish();
187             });
188         }
189 
190         [Test]
ShouldNotAllowToRequestTwiceInARow()191         public void ShouldNotAllowToRequestTwiceInARow()
192         {
193             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
194             {
195                 GrantOnSource();
196                 RequestOnSink();
197                 RequestOnSink().ShouldBlock(); // this should block here is a hack not to finish this test too soon
198                 Finish();
199             });
200         }
201 
202         [Test]
ShouldNotAllowToReportContinueBeforeRequesting()203         public void ShouldNotAllowToReportContinueBeforeRequesting()
204         {
205             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
206             {
207                 ContinueOnSink();
208                 Finish();
209             });
210         }
211 
212         [Test]
ShouldNotAllowToReportBreakBeforeRequesting()213         public void ShouldNotAllowToReportBreakBeforeRequesting()
214         {
215             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
216             {
217                 BreakOnSink();
218                 Finish();
219             });
220         }
221 
222         [Test]
ShouldNotAllowToReportBreakTwiceInARow()223         public void ShouldNotAllowToReportBreakTwiceInARow()
224         {
225             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
226             {
227                 GrantOnSource();
228                 RequestOnSink();
229                 BreakOnSink();
230                 BreakOnSink();
231                 Finish();
232             });
233         }
234 
235         [Test]
ShouldNotAllowToReportContinueTwiceInARow()236         public void ShouldNotAllowToReportContinueTwiceInARow()
237         {
238             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
239             {
240                 GrantOnSource();
241                 RequestOnSink();
242                 ContinueOnSink();
243                 ContinueOnSink();
244                 Finish();
245             });
246         }
247 
248         [Test]
ShouldNotAllowToReportContinueAfterBreak()249         public void ShouldNotAllowToReportContinueAfterBreak()
250         {
251             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
252             {
253                 GrantOnSource();
254                 RequestOnSink();
255                 BreakOnSink();
256                 ContinueOnSink();
257                 Finish();
258             });
259         }
260 
261         [Test]
ShouldNotAllowToReportBreakAfterContinue()262         public void ShouldNotAllowToReportBreakAfterContinue()
263         {
264             Assert.Throws<Antmicro.Renode.Debugging.AssertionException>(() =>
265             {
266                 GrantOnSource();
267                 RequestOnSink();
268                 ContinueOnSink();
269                 BreakOnSink();
270                 Finish();
271             });
272         }
273 #endif
274 
275         [Test]
RequestShouldReturnDifferentValuesDependingOnSideEnabledState2()276         public void RequestShouldReturnDifferentValuesDependingOnSideEnabledState2()
277         {
278             var r = RequestOnSink().ShouldBlock();
279             SetSourceSideActiveOnExternal(false);
280             r.ShouldFinish();
281             RequestOnSink().ShouldFinish(Tuple.Create(false, TimeInterval.Empty));
282             SetSourceSideActiveOnExternal(true);
283             r = RequestOnSink().ShouldBlock();
284             GrantOnSource();
285             r.ShouldFinish();
286             WaitOnSource().ShouldBlock();
287             Finish();
288 
289             ShouldRequestReturn(true, interval);
290         }
291 
292         [Test]
GratingShouldFinishRequestAfterReEnablingSourceSide()293         public void GratingShouldFinishRequestAfterReEnablingSourceSide()
294         {
295             SetSourceSideActiveOnExternal(false);
296             SetSourceSideActiveOnExternal(true);
297             var r = RequestOnSink().ShouldBlock();
298             GrantOnSource();
299             r.ShouldFinish();
300             Finish();
301 
302             ShouldRequestReturn(true, interval);
303         }
304 
305         [Test]
DisablingHanldeSinkSideShouldFinishRequest()306         public void DisablingHanldeSinkSideShouldFinishRequest()
307         {
308             var r = RequestOnSink().ShouldBlock();
309             SetEnabledOnExternal(false).ShouldFinish();
310             r.ShouldFinish();
311             Finish();
312 
313             ShouldRequestReturn(false, TimeInterval.Empty);
314         }
315 
316         [Test]
DisablingHanldeSourceSideShouldFinishRequest()317         public void DisablingHanldeSourceSideShouldFinishRequest()
318         {
319             var r = RequestOnSink().ShouldBlock();
320             SetSourceSideActiveOnExternal(false);
321             r.ShouldFinish();
322             Finish();
323 
324             ShouldRequestReturn(false, TimeInterval.Empty);
325         }
326 
327         [Test]
RequestShouldNotBlockOnDisabledHandle()328         public void RequestShouldNotBlockOnDisabledHandle()
329         {
330             SetEnabledOnExternal(false).ShouldFinish();
331             RequestOnSink().ShouldFinish();
332             Finish();
333 
334             ShouldRequestReturn(false, TimeInterval.Empty);
335         }
336 
337         [Test]
BreakingShouldFinishWaiting3()338         public void BreakingShouldFinishWaiting3()
339         {
340             GrantOnSource();
341             WaitOnSource().ShouldFinish(Tuple.Create(false, false, TimeInterval.Empty));
342             var r = RequestOnSink().ShouldBlock();
343             UnblockOnSource();
344             r.ShouldFinish(Tuple.Create(true, interval));
345             var w = WaitOnSource().ShouldBlock();
346             BreakOnSink();
347             w.ShouldFinish(Tuple.Create(false, true, interval));
348             Finish();
349         }
350 
351         [Test]
BreakingShouldFinishWaiting2()352         public void BreakingShouldFinishWaiting2()
353         {
354             var r = RequestOnSink().ShouldBlock();
355             GrantOnSource();
356             r.ShouldFinish();
357             var w = WaitOnSource().ShouldBlock();
358             BreakOnSink();
359             w.ShouldFinish();
360             Finish();
361 
362             ShouldRequestReturn(true, interval);
363             ShouldWaitReturn(false, false, interval);
364         }
365 
366         [Test]
BreakingShouldFinishWaiting()367         public void BreakingShouldFinishWaiting()
368         {
369             GrantOnSource();
370             RequestOnSink().ShouldFinish();
371             var w = WaitOnSource().ShouldBlock();
372             BreakOnSink();
373             w.ShouldFinish();
374             Finish();
375 
376             ShouldRequestReturn(true, interval);
377             ShouldWaitReturn(false, false, interval);
378         }
379 
380         [Test]
ContinueShouldFinishWaiting()381         public void ContinueShouldFinishWaiting()
382         {
383             GrantOnSource();
384             WaitOnSource().ShouldFinish(Tuple.Create(false, false, TimeInterval.Empty));
385             var r = RequestOnSink().ShouldBlock();
386             UnblockOnSource();
387             r.ShouldFinish(Tuple.Create(true, interval));
388             var w = WaitOnSource().ShouldBlock();
389             ContinueOnSink();
390             w.ShouldFinish(Tuple.Create(true, true, interval));
391             Finish();
392         }
393 
394         [Test]
ContinueShouldFinishWaiting2()395         public void ContinueShouldFinishWaiting2()
396         {
397             var r = RequestOnSink().ShouldBlock();
398             GrantOnSource();
399             r.ShouldFinish();
400             var w = WaitOnSource().ShouldBlock();
401             ContinueOnSink();
402             w.ShouldFinish();
403             Finish();
404 
405             ShouldRequestReturn(true, interval);
406             ShouldWaitReturn(true, false, interval);
407         }
408 
409         [Test]
ContinueShouldFinishWaiting3()410         public void ContinueShouldFinishWaiting3()
411         {
412             GrantOnSource();
413             RequestOnSink().ShouldFinish();
414             var w = WaitOnSource().ShouldBlock();
415             ContinueOnSink();
416             w.ShouldFinish();
417             Finish();
418 
419             ShouldRequestReturn(true, interval);
420             ShouldWaitReturn(true, false, interval);
421         }
422 
423         [Test]
WaitShouldNotBlockAfterContinue()424         public void WaitShouldNotBlockAfterContinue()
425         {
426             GrantOnSource();
427             RequestOnSink().ShouldFinish();
428             ContinueOnSink();
429             WaitOnSource().ShouldFinish();
430             Finish();
431 
432             ShouldRequestReturn(true, interval);
433             ShouldWaitReturn(true, false, interval);
434         }
435 
436         [Test]
WaitShouldNotBlockAfterContinue2()437         public void WaitShouldNotBlockAfterContinue2()
438         {
439             var r = RequestOnSink().ShouldBlock();
440             GrantOnSource();
441             r.ShouldFinish();
442             ContinueOnSink();
443             WaitOnSource().ShouldFinish();
444             Finish();
445 
446             ShouldRequestReturn(true, interval);
447             ShouldWaitReturn(true, false, interval);
448         }
449 
450         [Test]
WaitShouldNotBlockAfterBreak()451         public void WaitShouldNotBlockAfterBreak()
452         {
453             GrantOnSource();
454             RequestOnSink().ShouldFinish();
455             BreakOnSink();
456             WaitOnSource().ShouldFinish();
457             Finish();
458 
459             ShouldRequestReturn(true, interval);
460             ShouldWaitReturn(false, false, interval);
461         }
462 
463         [Test]
WaitShouldNotBlockAfterBreak2()464         public void WaitShouldNotBlockAfterBreak2()
465         {
466             var r = RequestOnSink().ShouldBlock();
467             GrantOnSource();
468             r.ShouldFinish();
469             BreakOnSink();
470             WaitOnSource().ShouldFinish();
471             Finish();
472 
473             ShouldRequestReturn(true, interval);
474             ShouldWaitReturn(false, false, interval);
475         }
476 
477         [Test]
WaitShouldNotBlockOnDisabledHandle()478         public void WaitShouldNotBlockOnDisabledHandle()
479         {
480             var r = RequestOnSink().ShouldBlock();
481             SetEnabledOnExternal(false).ShouldFinish();
482             r.ShouldFinish();
483             GrantOnSource();
484             WaitOnSource().ShouldFinish();
485             Finish();
486 
487             ShouldRequestReturn(false, TimeInterval.Empty);
488             ShouldWaitReturn(true, false, interval);
489         }
490 
491         [Test]
RequestSholdNotBlockAfterGrantOnReEnabledHandle()492         public void RequestSholdNotBlockAfterGrantOnReEnabledHandle()
493         {
494             SetSourceSideActiveOnExternal(false);
495             SetSourceSideActiveOnExternal(true);
496             GrantOnSource();
497             RequestOnSink().ShouldFinish();
498             Finish();
499 
500             ShouldRequestReturn(true, interval);
501         }
502 
503         [Test]
RequestAfterBreakShouldBlockWaitingForUnblock()504         public void RequestAfterBreakShouldBlockWaitingForUnblock()
505         {
506             var r = RequestOnSink().ShouldBlock();
507             GrantOnSource();
508             r.ShouldFinish(Tuple.Create(true, interval));
509             BreakOnSink();
510             WaitOnSource().ShouldFinish(Tuple.Create(false, false, interval));
511             RequestOnSink().ShouldBlock();
512             Finish();
513         }
514 
515         [Test]
ShouldUnblockHandle()516         public void ShouldUnblockHandle()
517         {
518             var r = RequestOnSink().ShouldBlock();
519             GrantOnSource();
520             r.ShouldFinish(Tuple.Create(true, interval));
521             BreakOnSink();
522             WaitOnSource().ShouldFinish(Tuple.Create(false, false, interval));
523             r = RequestOnSink().ShouldBlock();
524             UnblockOnSource().ShouldFinish();
525             r.ShouldFinish(Tuple.Create(true, TimeInterval.Empty));
526             Finish();
527         }
528 
529         [Test]
SecondWaitShouldReturnEmptyIntervalOnBlockingHandle()530         public void SecondWaitShouldReturnEmptyIntervalOnBlockingHandle()
531         {
532             GrantOnSource();
533             RequestOnSink().ShouldFinish();
534             BreakOnSink();
535             WaitOnSource().ShouldFinish(Tuple.Create(false, false, interval));
536             WaitOnSource().ShouldFinish(Tuple.Create(false, false, TimeInterval.Empty));
537             Finish();
538         }
539 
540         [Test]
WaitShouldNotBlockAfterGrantingOnReEnabledHandleS()541         public void WaitShouldNotBlockAfterGrantingOnReEnabledHandleS()
542         {
543             SetEnabledOnExternal(false).ShouldFinish();
544             SetEnabledOnExternal(true).ShouldFinish();
545             GrantOnSource();
546             WaitOnSource().ShouldFinish();
547             Finish();
548 
549             ShouldWaitReturn(false, false, TimeInterval.Empty);
550         }
551 
552         [Test]
DisableSinkSideShouldBlockOnLatchedHandle()553         public void DisableSinkSideShouldBlockOnLatchedHandle()
554         {
555             var r = RequestOnSink().ShouldBlock();
556             SetSourceSideActiveOnExternal(false);
557             r.ShouldFinish();
558             SetSourceSideActiveOnExternal(true);
559 
560             SetEnabledOnExternal(false).ShouldFinish();
561             LatchOnSource();
562             GrantOnSource();
563             var s = SetEnabledOnExternal(true).ShouldBlock();
564             WaitOnSource().ShouldFinish();
565             UnlatchOnSource();
566             s.ShouldFinish();
567             Finish();
568 
569             ShouldWaitReturn(true, false, interval);
570         }
571 
572         [Test]
ShouldHandleDisablingBlockedHandle()573         public void ShouldHandleDisablingBlockedHandle()
574         {
575             GrantOnSource().ShouldFinish();
576             RequestOnSink().ShouldFinish();
577             BreakOnSink(TimeInterval.FromTicks(500)).ShouldFinish();
578             WaitOnSource().ShouldFinish(Tuple.Create(false, false, TimeInterval.FromTicks(500)));
579 
580             // here we disable a blocked handle - it should report back the rest of a quant
581             SetEnabledOnExternal(false).ShouldFinish();
582             WaitOnSource().ShouldFinish(Tuple.Create(true, false, TimeInterval.FromTicks(500)));
583 
584             // now it should automatically report all the quant
585             GrantOnSource().ShouldFinish();
586             WaitOnSource().ShouldFinish(Tuple.Create(true, false, TimeInterval.FromTicks(1000)));
587 
588             // here we re-enable the handle - it should *not remember* that it was blocked before disabling
589             SetEnabledOnExternal(true).ShouldFinish();
590             GrantOnSource().ShouldFinish();
591             RequestOnSink().ShouldFinish();
592             ContinueOnSink().ShouldFinish();
593             WaitOnSource().ShouldFinish(Tuple.Create(true, false, TimeInterval.FromTicks(1000)));
594 
595             Finish();
596         }
597 
GrantOnSource()598         private ThreadSyncTester.ExecutionResult GrantOnSource()
599         {
600             // granting should never block
601             return tester.Execute(sourceThread, () => { handle.GrantTimeInterval(interval); return null; }, "Grant").ShouldFinish();
602         }
603 
UnblockOnSource()604         private ThreadSyncTester.ExecutionResult UnblockOnSource()
605         {
606             // unblocking should never block
607             return tester.Execute(sourceThread, () => { var r = handle.UnblockHandle(); return r; }, "Unblock").ShouldFinish();
608         }
609 
WaitOnSource()610         private ThreadSyncTester.ExecutionResult WaitOnSource()
611         {
612             // it may block or not
613             waitResult = tester.Execute(sourceThread, () => { var r = handle.WaitUntilDone(out var ti); return Tuple.Create(r.IsDone, r.IsUnblockedRecently, ti); }, "Wait");
614             return waitResult;
615         }
616 
RequestOnSink()617         private ThreadSyncTester.ExecutionResult RequestOnSink()
618         {
619             // it may block or not
620             requestResult = tester.Execute(sinkThread, () => { var r = handle.RequestTimeInterval(out var i); return Tuple.Create(r, i);}, "Request");
621             return requestResult;
622         }
623 
ReportProgressOnSink(TimeInterval p)624         private ThreadSyncTester.ExecutionResult ReportProgressOnSink(TimeInterval p)
625         {
626             return tester.Execute(sinkThread, () => { handle.ReportProgress(p); return null;}, "ReportProgress").ShouldFinish();
627         }
628 
DisposeOnExternal()629         private ThreadSyncTester.ExecutionResult DisposeOnExternal()
630         {
631             // dispose should never block
632             return tester.Execute(externalThread, () => { handle.Dispose(); return null; }, "Dispose").ShouldFinish();
633         }
634 
SetSourceSideActiveOnExternal(bool value)635         private ThreadSyncTester.ExecutionResult SetSourceSideActiveOnExternal(bool value)
636         {
637             // this should never block
638             return tester.Execute(externalThread, () => { handle.SourceSideActive = value; return null; }, "SourceSideActive").ShouldFinish();
639         }
640 
SetEnabledOnExternal(bool value)641         private ThreadSyncTester.ExecutionResult SetEnabledOnExternal(bool value)
642         {
643             // this one can block!
644             return tester.Execute(externalThread, (Func<object>)(() => { handle.Enabled = value; return null; }), "Enabled");
645         }
646 
647         private ThreadSyncTester.ExecutionResult BreakOnSink(TimeInterval? i = null)
648         {
649             // this should never block
650             return tester.Execute(sinkThread, () => { handle.ReportBackAndBreak(i ?? TimeInterval.Empty); return null; }, "Break").ShouldFinish();
651         }
652 
653         private ThreadSyncTester.ExecutionResult ContinueOnSink(TimeInterval? i = null)
654         {
655             // this should never block
656             return tester.Execute(sinkThread, () => { handle.ReportBackAndContinue(i ?? TimeInterval.Empty); return null; }, "Continue").ShouldFinish();
657         }
658 
LatchOnSource()659         private ThreadSyncTester.ExecutionResult LatchOnSource()
660         {
661             // this should never block
662             return tester.Execute(sourceThread, () => { handle.Latch(); return null; }, "Latch").ShouldFinish();
663         }
664 
UnlatchOnSource()665         private ThreadSyncTester.ExecutionResult UnlatchOnSource()
666         {
667             // this should never block
668             return tester.Execute(sourceThread, () => { handle.Unlatch(); return null; }, "Unlatch").ShouldFinish();
669         }
670 
ShouldWaitReturn(bool result, bool isActivatedRecently, TimeInterval interval)671         private void ShouldWaitReturn(bool result, bool isActivatedRecently, TimeInterval interval)
672         {
673             Assert.AreEqual(Tuple.Create(result, isActivatedRecently, interval), waitResult.Result, "wait result");
674         }
675 
ShouldRequestReturn(bool result, TimeInterval interval)676         private void ShouldRequestReturn(bool result, TimeInterval interval)
677         {
678             Assert.AreEqual(Tuple.Create(result, interval), requestResult.Result, "request result");
679         }
680 
Finish()681         private void Finish()
682         {
683             tester.Finish();
684         }
685 
686         private MockTimeSource tsource;
687         private ThreadSyncTester tester;
688         private TimeHandle handle;
689         private ThreadSyncTester.TestThread sourceThread;
690         private ThreadSyncTester.TestThread sinkThread;
691         private ThreadSyncTester.TestThread externalThread;
692         private TimeInterval interval;
693         private ThreadSyncTester.ExecutionResult waitResult;
694         private ThreadSyncTester.ExecutionResult requestResult;
695 
696         private class MockTimeSource : ITimeSource, ITimeDomain
697         {
698             public TimeInterval Quantum { get; set; }
699 
700             public ITimeDomain Domain => this;
701 
702             public TimeInterval NearestSyncPoint => ElapsedVirtualTime + Quantum;
703 
704             public TimeInterval ElapsedVirtualTime { get; set; }
705 
RegisterSink(ITimeSink sink)706             public void RegisterSink(ITimeSink sink)
707             {
708                 throw new NotImplementedException();
709             }
710 
ReportHandleActive()711             public void ReportHandleActive()
712             {
713             }
714 
ReportTimeProgress()715             public void ReportTimeProgress()
716             {
717             }
718         }
719 
720         private class MockTimeSink : ITimeSink
721         {
722             public TimeHandle TimeHandle { get; set; }
723         }
724     }
725 }
726