test(daemon): pin atomic toast detach handoff
- commit
- dc2f115036009e7fbc0c4c49bb397564b20e5cf6
- author
- brice · · 2026-07-23 21:51 UTC
- parent
- 9e796e1
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +14 -3
M internal/usecase/daemon/notify_test.go +14 -3
| @@ -528,19 +528,30 @@ func TestNotifyRoutesToSessionClientOnly(t *testing.T) { | |||
| 528 | 528 | func TestNotifySessionScopedSerializesDetachThroughToastPublication(t *testing.T) { | |
| 529 | 529 | d, sess, ac, _ := newNoticeFixture(t, newNoticeClock()) | |
| 530 | 530 | ||
| 531 | - | selected := make(chan struct{}) | |
| 531 | + | selected := make(chan bool, 1) | |
| 532 | 532 | releasePublication := make(chan struct{}) | |
| 533 | 533 | d.notices.beforeSessionDelivery = func() { | |
| 534 | - | close(selected) | |
| 534 | + | unlocked := d.notices.routingMu.TryLock() | |
| 535 | + | if unlocked { | |
| 536 | + | d.notices.routingMu.Unlock() | |
| 537 | + | } | |
| 538 | + | selected <- !unlocked | |
| 535 | 539 | <-releasePublication | |
| 536 | 540 | } | |
| 541 | + | t.Cleanup(func() { | |
| 542 | + | select { | |
| 543 | + | case <-releasePublication: | |
| 544 | + | default: | |
| 545 | + | close(releasePublication) | |
| 546 | + | } | |
| 547 | + | }) | |
| 537 | 548 | ||
| 538 | 549 | notifyDone := make(chan struct{}) | |
| 539 | 550 | go func() { | |
| 540 | 551 | d.notify(sess, domain.NoticeInfo, domain.NoticeUser, "hello", nil) | |
| 541 | 552 | close(notifyDone) | |
| 542 | 553 | }() | |
| 543 | - | <-selected | |
| 554 | + | require.True(t, <-selected, "routingMu must remain held from attachment selection through toast publication") | |
| 544 | 555 | ||
| 545 | 556 | detachStarted := make(chan struct{}) | |
| 546 | 557 | detachDone := make(chan bool, 1) | |
| @@ -528,19 +528,30 @@ func TestNotifyRoutesToSessionClientOnly(t *testing.T) { | |||||
| 528 | func TestNotifySessionScopedSerializesDetachThroughToastPublication(t *testing.T) { | 528 | func TestNotifySessionScopedSerializesDetachThroughToastPublication(t *testing.T) { | ||
| 529 | d, sess, ac, _ := newNoticeFixture(t, newNoticeClock()) | 529 | d, sess, ac, _ := newNoticeFixture(t, newNoticeClock()) | ||
| 530 | 530 | ||||
| 531 | - | selected := make(chan struct{}) | 531 | + | selected := make(chan bool, 1) |
| 532 | releasePublication := make(chan struct{}) | 532 | releasePublication := make(chan struct{}) | ||
| 533 | d.notices.beforeSessionDelivery = func() { | 533 | d.notices.beforeSessionDelivery = func() { | ||
| 534 | - | close(selected) | 534 | + | unlocked := d.notices.routingMu.TryLock() |
| 535 | + | if unlocked { | |||
| 536 | + | d.notices.routingMu.Unlock() | |||
| 537 | + | } | |||
| 538 | + | selected <- !unlocked | |||
| 535 | <-releasePublication | 539 | <-releasePublication | ||
| 536 | } | 540 | } | ||
| 541 | + | t.Cleanup(func() { | |||
| 542 | + | select { | |||
| 543 | + | case <-releasePublication: | |||
| 544 | + | default: | |||
| 545 | + | close(releasePublication) | |||
| 546 | + | } | |||
| 547 | + | }) | |||
| 537 | 548 | ||||
| 538 | notifyDone := make(chan struct{}) | 549 | notifyDone := make(chan struct{}) | ||
| 539 | go func() { | 550 | go func() { | ||
| 540 | d.notify(sess, domain.NoticeInfo, domain.NoticeUser, "hello", nil) | 551 | d.notify(sess, domain.NoticeInfo, domain.NoticeUser, "hello", nil) | ||
| 541 | close(notifyDone) | 552 | close(notifyDone) | ||
| 542 | }() | 553 | }() | ||
| 543 | - | <-selected | 554 | + | require.True(t, <-selected, "routingMu must remain held from attachment selection through toast publication") |
| 544 | 555 | ||||
| 545 | detachStarted := make(chan struct{}) | 556 | detachStarted := make(chan struct{}) | ||
| 546 | detachDone := make(chan bool, 1) | 557 | detachDone := make(chan bool, 1) | ||