test(daemon): make coordinator lifecycle red deterministic
- commit
- 4eb20a0cb9d60b292e6b936da780589373be9cb9
- author
- brice · · 2026-07-11 14:59 UTC
- parent
- 7a79ec3
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +77 -39
M internal/usecase/daemon/render_coordinator_test.go +77 -39
| @@ -61,13 +61,16 @@ func (h *coordinatorHarness) armedTimers(t *testing.T) []*signalTimer { | |||
| 61 | 61 | } | |
| 62 | 62 | } | |
| 63 | 63 | ||
| 64 | + | // Coordinator calls and fake-clock advancement are synchronous test steps. | |
| 65 | + | // These helpers deliberately never wait on wall time: a missing event is a | |
| 66 | + | // deterministic contract failure, not a slow behavior to poll for. | |
| 64 | 67 | func awaitWake(t *testing.T, ch chan renderWake) renderWake { | |
| 65 | 68 | t.Helper() | |
| 66 | 69 | select { | |
| 67 | 70 | case w := <-ch: | |
| 68 | 71 | return w | |
| 69 | - | case <-time.After(2 * time.Second): | |
| 70 | - | t.Fatal("timed out waiting for a coordinator wake") | |
| 72 | + | default: | |
| 73 | + | t.Fatal("coordinator did not synchronously publish a wake after fake-clock advancement") | |
| 71 | 74 | return renderWake{} | |
| 72 | 75 | } | |
| 73 | 76 | } | |
| @@ -77,7 +80,7 @@ func requireNoWake(t *testing.T, ch chan renderWake) { | |||
| 77 | 80 | select { | |
| 78 | 81 | case w := <-ch: | |
| 79 | 82 | t.Fatalf("unexpected coordinator wake: %+v", w) | |
| 80 | - | case <-time.After(50 * time.Millisecond): | |
| 83 | + | default: | |
| 81 | 84 | } | |
| 82 | 85 | } | |
| 83 | 86 | ||
| @@ -86,8 +89,8 @@ func awaitInvalidation(t *testing.T, ch chan renderInvalidation) renderInvalidat | |||
| 86 | 89 | select { | |
| 87 | 90 | case inv := <-ch: | |
| 88 | 91 | return inv | |
| 89 | - | case <-time.After(2 * time.Second): | |
| 90 | - | t.Fatal("timed out waiting for a coordinator invalidation") | |
| 92 | + | default: | |
| 93 | + | t.Fatal("producer did not synchronously publish a coordinator invalidation") | |
| 91 | 94 | return renderInvalidation{} | |
| 92 | 95 | } | |
| 93 | 96 | } | |
| @@ -97,7 +100,7 @@ func requireNoInvalidation(t *testing.T, ch chan renderInvalidation) { | |||
| 97 | 100 | select { | |
| 98 | 101 | case inv := <-ch: | |
| 99 | 102 | t.Fatalf("unexpected coordinator invalidation: %+v", inv) | |
| 100 | - | case <-time.After(50 * time.Millisecond): | |
| 103 | + | default: | |
| 101 | 104 | } | |
| 102 | 105 | } | |
| 103 | 106 | ||
| @@ -106,12 +109,21 @@ func awaitScheduledTimer(t *testing.T, clk *signalClock) *signalTimer { | |||
| 106 | 109 | select { | |
| 107 | 110 | case tm := <-clk.timers: | |
| 108 | 111 | return tm | |
| 109 | - | case <-time.After(2 * time.Second): | |
| 110 | - | t.Fatal("timed out waiting for a scheduled timer") | |
| 112 | + | default: | |
| 113 | + | t.Fatal("coordinator did not synchronously arm a fake-clock timer") | |
| 111 | 114 | return nil | |
| 112 | 115 | } | |
| 113 | 116 | } | |
| 114 | 117 | ||
| 118 | + | func requireNoCoordinatorOutputFrame(t *testing.T, sends chan ports.Frame) { | |
| 119 | + | t.Helper() | |
| 120 | + | select { | |
| 121 | + | case frame := <-sends: | |
| 122 | + | t.Fatalf("unexpected output frame: %+v", frame) | |
| 123 | + | default: | |
| 124 | + | } | |
| 125 | + | } | |
| 126 | + | ||
| 115 | 127 | // --- wake coalescing and deadlines -------------------------------------------- | |
| 116 | 128 | ||
| 117 | 129 | func TestRenderCoordinatorCoalescesWakesUnderOneDeadline(t *testing.T) { | |
| @@ -387,32 +399,58 @@ func TestRenderCoordinatorResizeMetadata(t *testing.T) { | |||
| 387 | 399 | }, | |
| 388 | 400 | }, | |
| 389 | 401 | { | |
| 390 | - | name: "a displaced attachment cannot overwrite current metadata", | |
| 402 | + | name: "stale resize callbacks preserve latest metadata through lifecycle transitions", | |
| 391 | 403 | run: func(t *testing.T, rc *renderCoordinator, owner, replacement *attachedClient) { | |
| 392 | - | require.Equal(t, uint64(1), rc.recordResizeRequest(sz(120, 40), owner)) | |
| 393 | - | rc.noteReplace(owner, replacement) | |
| 394 | - | rc.attach(replacement) | |
| 395 | - | ||
| 396 | - | require.Zero(t, rc.recordResizeRequest(sz(80, 20), owner), | |
| 397 | - | "a stale attachment must not advance the resize epoch") | |
| 398 | - | snap := rc.resizeSnapshot() | |
| 399 | - | require.Equal(t, sz(120, 40), snap.size) | |
| 400 | - | require.Equal(t, uint64(1), snap.epoch) | |
| 401 | - | ||
| 402 | - | require.Equal(t, uint64(2), rc.recordResizeRequest(sz(100, 50), replacement)) | |
| 403 | - | snap = rc.resizeSnapshot() | |
| 404 | - | require.Equal(t, sz(100, 50), snap.size) | |
| 405 | - | require.Same(t, replacement, snap.source) | |
| 406 | - | }, | |
| 407 | - | }, | |
| 408 | - | { | |
| 409 | - | name: "detach cannot erase committed metadata", | |
| 410 | - | run: func(t *testing.T, rc *renderCoordinator, owner, _ *attachedClient) { | |
| 411 | - | require.Equal(t, uint64(1), rc.recordResizeRequest(sz(120, 40), owner)) | |
| 412 | - | rc.noteDetach(owner) | |
| 413 | - | snap := rc.resizeSnapshot() | |
| 414 | - | require.Equal(t, sz(120, 40), snap.size) | |
| 415 | - | require.Equal(t, uint64(1), snap.epoch) | |
| 404 | + | type lifecycleCase struct { | |
| 405 | + | name string | |
| 406 | + | installNew bool | |
| 407 | + | } | |
| 408 | + | for _, tc := range []lifecycleCase{ | |
| 409 | + | {name: "detach"}, | |
| 410 | + | {name: "park"}, | |
| 411 | + | {name: "session teardown"}, | |
| 412 | + | {name: "replacement", installNew: true}, | |
| 413 | + | } { | |
| 414 | + | t.Run(tc.name, func(t *testing.T) { | |
| 415 | + | h := newCoordinatorHarness(t) | |
| 416 | + | staleOwner := &attachedClient{} | |
| 417 | + | freshOwner := &attachedClient{} | |
| 418 | + | h.rc.attach(staleOwner) | |
| 419 | + | require.Equal(t, uint64(1), h.rc.recordResizeRequest(sz(120, 40), staleOwner)) | |
| 420 | + | ||
| 421 | + | // This models a retained PR #71 callback which captured the old | |
| 422 | + | // attachment before lifecycle ownership changed. | |
| 423 | + | staleCallback := func() uint64 { | |
| 424 | + | return h.rc.recordResizeRequest(sz(80, 20), staleOwner) | |
| 425 | + | } | |
| 426 | + | ||
| 427 | + | switch tc.name { | |
| 428 | + | case "detach": | |
| 429 | + | h.rc.noteDetach(staleOwner) | |
| 430 | + | case "park": | |
| 431 | + | h.rc.notePark(staleOwner) | |
| 432 | + | case "session teardown": | |
| 433 | + | h.rc.noteSessionTeardown() | |
| 434 | + | case "replacement": | |
| 435 | + | h.rc.noteReplace(staleOwner, freshOwner) | |
| 436 | + | h.rc.attach(freshOwner) | |
| 437 | + | require.Equal(t, uint64(2), h.rc.recordResizeRequest(sz(100, 50), freshOwner)) | |
| 438 | + | } | |
| 439 | + | ||
| 440 | + | require.Zero(t, staleCallback(), "stale callback must not advance the resize epoch") | |
| 441 | + | snap := h.rc.resizeSnapshot() | |
| 442 | + | if tc.installNew { | |
| 443 | + | require.Equal(t, sz(100, 50), snap.size) | |
| 444 | + | require.Equal(t, uint64(2), snap.epoch) | |
| 445 | + | require.Same(t, freshOwner, snap.source) | |
| 446 | + | return | |
| 447 | + | } | |
| 448 | + | require.Equal(t, sz(120, 40), snap.size) | |
| 449 | + | require.Equal(t, uint64(1), snap.epoch) | |
| 450 | + | require.Same(t, staleOwner, snap.source, | |
| 451 | + | "the stale callback must not replace the recorded attachment identity") | |
| 452 | + | }) | |
| 453 | + | } | |
| 416 | 454 | }, | |
| 417 | 455 | }, | |
| 418 | 456 | } | |
| @@ -573,7 +611,7 @@ func TestProducerInvalidations(t *testing.T) { | |||
| 573 | 611 | ||
| 574 | 612 | awaitInvalidation(t, invs) | |
| 575 | 613 | requireNoInvalidation(t, invs) | |
| 576 | - | requireNoOutputFrame(t, sends) | |
| 614 | + | requireNoCoordinatorOutputFrame(t, sends) | |
| 577 | 615 | }) | |
| 578 | 616 | } | |
| 579 | 617 | } | |
| @@ -626,13 +664,13 @@ func TestRenderCoordinatorRetainsPR71ResizeDispatch(t *testing.T) { | |||
| 626 | 664 | "the coordinator must record the latest requested resize before delegating") | |
| 627 | 665 | require.Same(t, ac, snap.source) | |
| 628 | 666 | require.Equal(t, uint64(1), snap.epoch) | |
| 629 | - | requireNoOutputFrame(t, sends) | |
| 667 | + | requireNoCoordinatorOutputFrame(t, sends) | |
| 630 | 668 | ||
| 631 | 669 | timer.ch <- time.Time{} | |
| 632 | 670 | inv := awaitInvalidation(t, invs) | |
| 633 | 671 | require.True(t, inv.reset, "the resize dispatch must request a full-redraw invalidation") | |
| 634 | 672 | requireNoInvalidation(t, invs) | |
| 635 | - | requireNoOutputFrame(t, sends) | |
| 673 | + | requireNoCoordinatorOutputFrame(t, sends) | |
| 636 | 674 | }) | |
| 637 | 675 | ||
| 638 | 676 | t.Run("stale generations stay rejected", func(t *testing.T) { | |
| @@ -647,13 +685,13 @@ func TestRenderCoordinatorRetainsPR71ResizeDispatch(t *testing.T) { | |||
| 647 | 685 | ||
| 648 | 686 | first.ch <- time.Time{} | |
| 649 | 687 | requireNoInvalidation(t, invs) | |
| 650 | - | requireNoOutputFrame(t, sends) | |
| 688 | + | requireNoCoordinatorOutputFrame(t, sends) | |
| 651 | 689 | ||
| 652 | 690 | latest.ch <- time.Time{} | |
| 653 | 691 | inv := awaitInvalidation(t, invs) | |
| 654 | 692 | require.True(t, inv.reset) | |
| 655 | 693 | requireNoInvalidation(t, invs) | |
| 656 | - | requireNoOutputFrame(t, sends) | |
| 694 | + | requireNoCoordinatorOutputFrame(t, sends) | |
| 657 | 695 | require.Equal(t, domain.Size{Cols: 120, Rows: 24}, sess.renderCoordinator().resizeSnapshot().size) | |
| 658 | 696 | }) | |
| 659 | 697 | ||
| @@ -666,6 +704,6 @@ func TestRenderCoordinatorRetainsPR71ResizeDispatch(t *testing.T) { | |||
| 666 | 704 | ||
| 667 | 705 | timer.ch <- time.Time{} | |
| 668 | 706 | requireNoInvalidation(t, invs) | |
| 669 | - | requireNoOutputFrame(t, sends) | |
| 707 | + | requireNoCoordinatorOutputFrame(t, sends) | |
| 670 | 708 | }) | |
| 671 | 709 | } | |
| @@ -61,13 +61,16 @@ func (h *coordinatorHarness) armedTimers(t *testing.T) []*signalTimer { | |||||
| 61 | } | 61 | } | ||
| 62 | } | 62 | } | ||
| 63 | 63 | ||||
| 64 | + | // Coordinator calls and fake-clock advancement are synchronous test steps. | |||
| 65 | + | // These helpers deliberately never wait on wall time: a missing event is a | |||
| 66 | + | // deterministic contract failure, not a slow behavior to poll for. | |||
| 64 | func awaitWake(t *testing.T, ch chan renderWake) renderWake { | 67 | func awaitWake(t *testing.T, ch chan renderWake) renderWake { | ||
| 65 | t.Helper() | 68 | t.Helper() | ||
| 66 | select { | 69 | select { | ||
| 67 | case w := <-ch: | 70 | case w := <-ch: | ||
| 68 | return w | 71 | return w | ||
| 69 | - | case <-time.After(2 * time.Second): | 72 | + | default: |
| 70 | - | t.Fatal("timed out waiting for a coordinator wake") | 73 | + | t.Fatal("coordinator did not synchronously publish a wake after fake-clock advancement") |
| 71 | return renderWake{} | 74 | return renderWake{} | ||
| 72 | } | 75 | } | ||
| 73 | } | 76 | } | ||
| @@ -77,7 +80,7 @@ func requireNoWake(t *testing.T, ch chan renderWake) { | |||||
| 77 | select { | 80 | select { | ||
| 78 | case w := <-ch: | 81 | case w := <-ch: | ||
| 79 | t.Fatalf("unexpected coordinator wake: %+v", w) | 82 | t.Fatalf("unexpected coordinator wake: %+v", w) | ||
| 80 | - | case <-time.After(50 * time.Millisecond): | 83 | + | default: |
| 81 | } | 84 | } | ||
| 82 | } | 85 | } | ||
| 83 | 86 | ||||
| @@ -86,8 +89,8 @@ func awaitInvalidation(t *testing.T, ch chan renderInvalidation) renderInvalidat | |||||
| 86 | select { | 89 | select { | ||
| 87 | case inv := <-ch: | 90 | case inv := <-ch: | ||
| 88 | return inv | 91 | return inv | ||
| 89 | - | case <-time.After(2 * time.Second): | 92 | + | default: |
| 90 | - | t.Fatal("timed out waiting for a coordinator invalidation") | 93 | + | t.Fatal("producer did not synchronously publish a coordinator invalidation") |
| 91 | return renderInvalidation{} | 94 | return renderInvalidation{} | ||
| 92 | } | 95 | } | ||
| 93 | } | 96 | } | ||
| @@ -97,7 +100,7 @@ func requireNoInvalidation(t *testing.T, ch chan renderInvalidation) { | |||||
| 97 | select { | 100 | select { | ||
| 98 | case inv := <-ch: | 101 | case inv := <-ch: | ||
| 99 | t.Fatalf("unexpected coordinator invalidation: %+v", inv) | 102 | t.Fatalf("unexpected coordinator invalidation: %+v", inv) | ||
| 100 | - | case <-time.After(50 * time.Millisecond): | 103 | + | default: |
| 101 | } | 104 | } | ||
| 102 | } | 105 | } | ||
| 103 | 106 | ||||
| @@ -106,12 +109,21 @@ func awaitScheduledTimer(t *testing.T, clk *signalClock) *signalTimer { | |||||
| 106 | select { | 109 | select { | ||
| 107 | case tm := <-clk.timers: | 110 | case tm := <-clk.timers: | ||
| 108 | return tm | 111 | return tm | ||
| 109 | - | case <-time.After(2 * time.Second): | 112 | + | default: |
| 110 | - | t.Fatal("timed out waiting for a scheduled timer") | 113 | + | t.Fatal("coordinator did not synchronously arm a fake-clock timer") |
| 111 | return nil | 114 | return nil | ||
| 112 | } | 115 | } | ||
| 113 | } | 116 | } | ||
| 114 | 117 | ||||
| 118 | + | func requireNoCoordinatorOutputFrame(t *testing.T, sends chan ports.Frame) { | |||
| 119 | + | t.Helper() | |||
| 120 | + | select { | |||
| 121 | + | case frame := <-sends: | |||
| 122 | + | t.Fatalf("unexpected output frame: %+v", frame) | |||
| 123 | + | default: | |||
| 124 | + | } | |||
| 125 | + | } | |||
| 126 | + | ||||
| 115 | // --- wake coalescing and deadlines -------------------------------------------- | 127 | // --- wake coalescing and deadlines -------------------------------------------- | ||
| 116 | 128 | ||||
| 117 | func TestRenderCoordinatorCoalescesWakesUnderOneDeadline(t *testing.T) { | 129 | func TestRenderCoordinatorCoalescesWakesUnderOneDeadline(t *testing.T) { | ||
| @@ -387,32 +399,58 @@ func TestRenderCoordinatorResizeMetadata(t *testing.T) { | |||||
| 387 | }, | 399 | }, | ||
| 388 | }, | 400 | }, | ||
| 389 | { | 401 | { | ||
| 390 | - | name: "a displaced attachment cannot overwrite current metadata", | 402 | + | name: "stale resize callbacks preserve latest metadata through lifecycle transitions", |
| 391 | run: func(t *testing.T, rc *renderCoordinator, owner, replacement *attachedClient) { | 403 | run: func(t *testing.T, rc *renderCoordinator, owner, replacement *attachedClient) { | ||
| 392 | - | require.Equal(t, uint64(1), rc.recordResizeRequest(sz(120, 40), owner)) | 404 | + | type lifecycleCase struct { |
| 393 | - | rc.noteReplace(owner, replacement) | 405 | + | name string |
| 394 | - | rc.attach(replacement) | 406 | + | installNew bool |
| 395 | - | 407 | + | } | |
| 396 | - | require.Zero(t, rc.recordResizeRequest(sz(80, 20), owner), | 408 | + | for _, tc := range []lifecycleCase{ |
| 397 | - | "a stale attachment must not advance the resize epoch") | 409 | + | {name: "detach"}, |
| 398 | - | snap := rc.resizeSnapshot() | 410 | + | {name: "park"}, |
| 399 | - | require.Equal(t, sz(120, 40), snap.size) | 411 | + | {name: "session teardown"}, |
| 400 | - | require.Equal(t, uint64(1), snap.epoch) | 412 | + | {name: "replacement", installNew: true}, |
| 401 | - | 413 | + | } { | |
| 402 | - | require.Equal(t, uint64(2), rc.recordResizeRequest(sz(100, 50), replacement)) | 414 | + | t.Run(tc.name, func(t *testing.T) { |
| 403 | - | snap = rc.resizeSnapshot() | 415 | + | h := newCoordinatorHarness(t) |
| 404 | - | require.Equal(t, sz(100, 50), snap.size) | 416 | + | staleOwner := &attachedClient{} |
| 405 | - | require.Same(t, replacement, snap.source) | 417 | + | freshOwner := &attachedClient{} |
| 406 | - | }, | 418 | + | h.rc.attach(staleOwner) |
| 407 | - | }, | 419 | + | require.Equal(t, uint64(1), h.rc.recordResizeRequest(sz(120, 40), staleOwner)) |
| 408 | - | { | 420 | + | |
| 409 | - | name: "detach cannot erase committed metadata", | 421 | + | // This models a retained PR #71 callback which captured the old |
| 410 | - | run: func(t *testing.T, rc *renderCoordinator, owner, _ *attachedClient) { | 422 | + | // attachment before lifecycle ownership changed. |
| 411 | - | require.Equal(t, uint64(1), rc.recordResizeRequest(sz(120, 40), owner)) | 423 | + | staleCallback := func() uint64 { |
| 412 | - | rc.noteDetach(owner) | 424 | + | return h.rc.recordResizeRequest(sz(80, 20), staleOwner) |
| 413 | - | snap := rc.resizeSnapshot() | 425 | + | } |
| 414 | - | require.Equal(t, sz(120, 40), snap.size) | 426 | + | |
| 415 | - | require.Equal(t, uint64(1), snap.epoch) | 427 | + | switch tc.name { |
| 428 | + | case "detach": | |||
| 429 | + | h.rc.noteDetach(staleOwner) | |||
| 430 | + | case "park": | |||
| 431 | + | h.rc.notePark(staleOwner) | |||
| 432 | + | case "session teardown": | |||
| 433 | + | h.rc.noteSessionTeardown() | |||
| 434 | + | case "replacement": | |||
| 435 | + | h.rc.noteReplace(staleOwner, freshOwner) | |||
| 436 | + | h.rc.attach(freshOwner) | |||
| 437 | + | require.Equal(t, uint64(2), h.rc.recordResizeRequest(sz(100, 50), freshOwner)) | |||
| 438 | + | } | |||
| 439 | + | ||||
| 440 | + | require.Zero(t, staleCallback(), "stale callback must not advance the resize epoch") | |||
| 441 | + | snap := h.rc.resizeSnapshot() | |||
| 442 | + | if tc.installNew { | |||
| 443 | + | require.Equal(t, sz(100, 50), snap.size) | |||
| 444 | + | require.Equal(t, uint64(2), snap.epoch) | |||
| 445 | + | require.Same(t, freshOwner, snap.source) | |||
| 446 | + | return | |||
| 447 | + | } | |||
| 448 | + | require.Equal(t, sz(120, 40), snap.size) | |||
| 449 | + | require.Equal(t, uint64(1), snap.epoch) | |||
| 450 | + | require.Same(t, staleOwner, snap.source, | |||
| 451 | + | "the stale callback must not replace the recorded attachment identity") | |||
| 452 | + | }) | |||
| 453 | + | } | |||
| 416 | }, | 454 | }, | ||
| 417 | }, | 455 | }, | ||
| 418 | } | 456 | } | ||
| @@ -573,7 +611,7 @@ func TestProducerInvalidations(t *testing.T) { | |||||
| 573 | 611 | ||||
| 574 | awaitInvalidation(t, invs) | 612 | awaitInvalidation(t, invs) | ||
| 575 | requireNoInvalidation(t, invs) | 613 | requireNoInvalidation(t, invs) | ||
| 576 | - | requireNoOutputFrame(t, sends) | 614 | + | requireNoCoordinatorOutputFrame(t, sends) |
| 577 | }) | 615 | }) | ||
| 578 | } | 616 | } | ||
| 579 | } | 617 | } | ||
| @@ -626,13 +664,13 @@ func TestRenderCoordinatorRetainsPR71ResizeDispatch(t *testing.T) { | |||||
| 626 | "the coordinator must record the latest requested resize before delegating") | 664 | "the coordinator must record the latest requested resize before delegating") | ||
| 627 | require.Same(t, ac, snap.source) | 665 | require.Same(t, ac, snap.source) | ||
| 628 | require.Equal(t, uint64(1), snap.epoch) | 666 | require.Equal(t, uint64(1), snap.epoch) | ||
| 629 | - | requireNoOutputFrame(t, sends) | 667 | + | requireNoCoordinatorOutputFrame(t, sends) |
| 630 | 668 | ||||
| 631 | timer.ch <- time.Time{} | 669 | timer.ch <- time.Time{} | ||
| 632 | inv := awaitInvalidation(t, invs) | 670 | inv := awaitInvalidation(t, invs) | ||
| 633 | require.True(t, inv.reset, "the resize dispatch must request a full-redraw invalidation") | 671 | require.True(t, inv.reset, "the resize dispatch must request a full-redraw invalidation") | ||
| 634 | requireNoInvalidation(t, invs) | 672 | requireNoInvalidation(t, invs) | ||
| 635 | - | requireNoOutputFrame(t, sends) | 673 | + | requireNoCoordinatorOutputFrame(t, sends) |
| 636 | }) | 674 | }) | ||
| 637 | 675 | ||||
| 638 | t.Run("stale generations stay rejected", func(t *testing.T) { | 676 | t.Run("stale generations stay rejected", func(t *testing.T) { | ||
| @@ -647,13 +685,13 @@ func TestRenderCoordinatorRetainsPR71ResizeDispatch(t *testing.T) { | |||||
| 647 | 685 | ||||
| 648 | first.ch <- time.Time{} | 686 | first.ch <- time.Time{} | ||
| 649 | requireNoInvalidation(t, invs) | 687 | requireNoInvalidation(t, invs) | ||
| 650 | - | requireNoOutputFrame(t, sends) | 688 | + | requireNoCoordinatorOutputFrame(t, sends) |
| 651 | 689 | ||||
| 652 | latest.ch <- time.Time{} | 690 | latest.ch <- time.Time{} | ||
| 653 | inv := awaitInvalidation(t, invs) | 691 | inv := awaitInvalidation(t, invs) | ||
| 654 | require.True(t, inv.reset) | 692 | require.True(t, inv.reset) | ||
| 655 | requireNoInvalidation(t, invs) | 693 | requireNoInvalidation(t, invs) | ||
| 656 | - | requireNoOutputFrame(t, sends) | 694 | + | requireNoCoordinatorOutputFrame(t, sends) |
| 657 | require.Equal(t, domain.Size{Cols: 120, Rows: 24}, sess.renderCoordinator().resizeSnapshot().size) | 695 | require.Equal(t, domain.Size{Cols: 120, Rows: 24}, sess.renderCoordinator().resizeSnapshot().size) | ||
| 658 | }) | 696 | }) | ||
| 659 | 697 | ||||
| @@ -666,6 +704,6 @@ func TestRenderCoordinatorRetainsPR71ResizeDispatch(t *testing.T) { | |||||
| 666 | 704 | ||||
| 667 | timer.ch <- time.Time{} | 705 | timer.ch <- time.Time{} | ||
| 668 | requireNoInvalidation(t, invs) | 706 | requireNoInvalidation(t, invs) | ||
| 669 | - | requireNoOutputFrame(t, sends) | 707 | + | requireNoCoordinatorOutputFrame(t, sends) |
| 670 | }) | 708 | }) | ||
| 671 | } | 709 | } | ||