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