4
4
"context"
5
5
"encoding/json"
6
6
"fmt"
7
+ "golang.org/x/exp/slices"
8
+ "golang.org/x/xerrors"
7
9
"net/http"
8
10
"net/http/httptest"
9
11
"net/url"
@@ -37,19 +39,24 @@ func TestMain(m *testing.M) {
37
39
}
38
40
39
41
// TestBasicNotificationRoundtrip enqueues a message to the store, waits for it to be acquired by a notifier,
40
- //and passes it off to a fake handler.
42
+ // passes it off to a fake handler, and ensures the results are synchronized to the store .
41
43
func TestBasicNotificationRoundtrip (t * testing.T ) {
42
44
t .Parallel ()
43
45
44
46
// SETUP
45
- ctx ,logger ,db := setupInMemory (t )
47
+ if ! dbtestutil .WillUsePostgres () {
48
+ t .Skip ("This test requires postgres; it relies on business-logic only implemented in the database" )
49
+ }
50
+
51
+ ctx ,logger ,db := setup (t )
46
52
method := database .NotificationMethodSmtp
47
53
48
54
// GIVEN: a manager with standard config but a faked dispatch handler
49
55
handler := & fakeHandler {}
50
-
56
+ interceptor := & bulkUpdateInterceptor { Store : db }
51
57
cfg := defaultNotificationsConfig (method )
52
- mgr ,err := notifications .NewManager (cfg ,db ,logger .Named ("manager" ))
58
+ cfg .RetryInterval = serpent .Duration (time .Hour )// Ensure retries don't interfere with the test
59
+ mgr ,err := notifications .NewManager (cfg ,interceptor ,logger .Named ("manager" ))
53
60
require .NoError (t ,err )
54
61
mgr .WithHandlers (map [database.NotificationMethod ]notifications.Handler {method :handler })
55
62
t .Cleanup (func () {
@@ -68,17 +75,33 @@ func TestBasicNotificationRoundtrip(t *testing.T) {
68
75
69
76
mgr .Run (ctx )
70
77
71
- // THEN: we expect that the handler will have received the notifications fordelivery
78
+ // THEN: we expect that the handler will have received the notifications fordispatch
72
79
require .Eventually (t ,func ()bool {
73
80
handler .mu .RLock ()
74
81
defer handler .mu .RUnlock ()
75
- return handler .succeeded == sid .String ()
76
- },testutil .WaitLong ,testutil .IntervalMedium )
82
+ return slices .Contains (handler .succeeded ,sid .String ())&&
83
+ slices .Contains (handler .failed ,fid .String ())
84
+ },testutil .WaitLong ,testutil .IntervalFast )
85
+
86
+ // THEN: we expect the store to be called with the updates of the earlier dispatches
77
87
require .Eventually (t ,func ()bool {
78
- handler .mu .RLock ()
79
- defer handler .mu .RUnlock ()
80
- return handler .failed == fid .String ()
81
- },testutil .WaitLong ,testutil .IntervalMedium )
88
+ return interceptor .sent .Load ()== 1 &&
89
+ interceptor .failed .Load ()== 1
90
+ },testutil .WaitShort ,testutil .IntervalFast )
91
+
92
+ // THEN: we verify that the store contains notifications in their expected state
93
+ success ,err := db .GetNotificationMessagesByStatus (ctx , database.GetNotificationMessagesByStatusParams {
94
+ Status :database .NotificationMessageStatusSent ,
95
+ Limit :10 ,
96
+ })
97
+ require .NoError (t ,err )
98
+ require .Len (t ,success ,1 )
99
+ failed ,err := db .GetNotificationMessagesByStatus (ctx , database.GetNotificationMessagesByStatusParams {
100
+ Status :database .NotificationMessageStatusTemporaryFailure ,
101
+ Limit :10 ,
102
+ })
103
+ require .NoError (t ,err )
104
+ require .Len (t ,failed ,1 )
82
105
}
83
106
84
107
func TestSMTPDispatch (t * testing.T ) {
@@ -517,8 +540,8 @@ func TestInvalidConfig(t *testing.T) {
517
540
type fakeHandler struct {
518
541
mu sync.RWMutex
519
542
520
- succeeded string
521
- failed string
543
+ succeeded [] string
544
+ failed [] string
522
545
}
523
546
524
547
func (f * fakeHandler )Dispatcher (payload types.MessagePayload ,_ ,_ string ) (dispatch.DeliveryFunc ,error ) {
@@ -527,11 +550,12 @@ func (f *fakeHandler) Dispatcher(payload types.MessagePayload, _, _ string) (dis
527
550
defer f .mu .Unlock ()
528
551
529
552
if payload .Labels ["type" ]== "success" {
530
- f .succeeded = msgID .String ()
531
- }else {
532
- f .failed = msgID .String ()
553
+ f .succeeded = append (f .succeeded ,msgID .String ())
554
+ return false ,nil
533
555
}
534
- return false ,nil
556
+
557
+ f .failed = append (f .failed ,msgID .String ())
558
+ return true ,xerrors .New ("oops" )
535
559
},nil
536
560
}
537
561