Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f24cb5c

Browse files
authored
fix: prevent test flakiness (coder#14467)
Signed-off-by: Danny Kopping <[email protected]>
1 parent c597c92 commit f24cb5c

File tree

1 file changed

+24
-16
lines changed

1 file changed

+24
-16
lines changed

coderd/notifications/notifications_test.go

+24-16
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ func TestNotifierPaused(t *testing.T) {
576576
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
577577
_, _, api := coderdtest.NewWithAPI(t, nil)
578578

579-
// Prepare the test
579+
// Prepare the test.
580580
handler := &fakeHandler{}
581581
method := database.NotificationMethodSmtp
582582
user := createSampleUser(t, api.Database)
@@ -593,32 +593,39 @@ func TestNotifierPaused(t *testing.T) {
593593
enq, err := notifications.NewStoreEnqueuer(cfg, api.Database, defaultHelpers(), api.Logger.Named("enqueuer"), quartz.NewReal())
594594
require.NoError(t, err)
595595

596-
mgr.Run(ctx)
597-
598596
// Pause the notifier.
599597
settingsJSON, err := json.Marshal(&codersdk.NotificationsSettings{NotifierPaused: true})
600598
require.NoError(t, err)
601599
err = api.Database.UpsertNotificationsSettings(ctx, string(settingsJSON))
602600
require.NoError(t, err)
603601

602+
// Start the manager so that notifications are processed, except it will be paused at this point.
603+
// If it is started before pausing, there's a TOCTOU possibility between checking whether the notifier is paused or
604+
// not, and processing the messages (see notifier.run).
605+
mgr.Run(ctx)
606+
604607
// Notifier is paused, enqueue the next message.
605608
sid, err := enq.Enqueue(ctx, user.ID, notifications.TemplateWorkspaceDeleted, map[string]string{"type": "success", "i": "1"}, "test")
606609
require.NoError(t, err)
607610

608-
// Sleep for a few fetch intervals to be sure we aren't getting false-positives in the next step.
609-
// TODO: use quartz instead.
610-
time.Sleep(fetchInterval * 5)
611-
612611
// Ensure we have a pending message and it's the expected one.
612+
pendingMessages, err := api.Database.GetNotificationMessagesByStatus(ctx, database.GetNotificationMessagesByStatusParams{
613+
Status: database.NotificationMessageStatusPending,
614+
Limit: 10,
615+
})
616+
require.NoError(t, err)
617+
require.Len(t, pendingMessages, 1)
618+
require.Equal(t, pendingMessages[0].ID.String(), sid.String())
619+
620+
// Wait a few fetch intervals to be sure that no new notifications are being sent.
621+
// TODO: use quartz instead.
622+
// nolint:gocritic // These magic numbers are fine.
613623
require.Eventually(t, func() bool {
614-
pendingMessages, err := api.Database.GetNotificationMessagesByStatus(ctx, database.GetNotificationMessagesByStatusParams{
615-
Status: database.NotificationMessageStatusPending,
616-
Limit: 10,
617-
})
618-
assert.NoError(t, err)
619-
return len(pendingMessages) == 1 &&
620-
pendingMessages[0].ID.String() == sid.String()
621-
}, testutil.WaitShort, testutil.IntervalFast)
624+
handler.mu.RLock()
625+
defer handler.mu.RUnlock()
626+
627+
return len(handler.succeeded)+len(handler.failed) == 0
628+
}, fetchInterval*5, testutil.IntervalFast)
622629

623630
// Unpause the notifier.
624631
settingsJSON, err = json.Marshal(&codersdk.NotificationsSettings{NotifierPaused: false})
@@ -627,11 +634,12 @@ func TestNotifierPaused(t *testing.T) {
627634
require.NoError(t, err)
628635

629636
// Notifier is running again, message should be dequeued.
637+
// nolint:gocritic // These magic numbers are fine.
630638
require.Eventually(t, func() bool {
631639
handler.mu.RLock()
632640
defer handler.mu.RUnlock()
633641
return slices.Contains(handler.succeeded, sid.String())
634-
}, testutil.WaitShort, testutil.IntervalFast)
642+
}, fetchInterval*5, testutil.IntervalFast)
635643
}
636644

637645
//go:embed events.go

0 commit comments

Comments
 (0)