carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package console
2
3import (
4 "context"
5 "testing"
6 "time"
7
8 "github.com/carlosframework/platform/internal/mail"
9)
10
11func mailRows(t *testing.T, s *Store, table string) int {
12 t.Helper()
13 var n int
14 if err := s.db.QueryRow(`SELECT COUNT(*) FROM ` + table).Scan(&n); err != nil {
15 t.Fatal(err)
16 }
17 return n
18}
19
20// Gated, every mail-table writer goes through withMailAppSQL: with no
21// account row and no bound mutation runner there is no permit to be had, so
22// each refuses and nothing lands. None of them reaches a raw statement.
23func TestMailSQLWritersRefuseWithoutPermit(t *testing.T) {
24 s := openGatedStore(t)
25 ctx := gateCtx(t)
26 now := time.Date(2026, 10, 7, 12, 0, 0, 0, time.UTC)
27 ev := mail.Event{Type: mail.EventBounce, MessageID: "m1", At: now}
28
29 if err := s.RecordMailEvent(ctx, "bab", "titogo", mail.SenderAppID, "2026-10-07", mail.EventSend); err == nil {
30 t.Fatal("RecordMailEvent wrote without a permit")
31 }
32 if err := s.SetMailEventHook(ctx, "bab", "titogo", "/mail/events", "a@b", now); err == nil {
33 t.Fatal("SetMailEventHook wrote without a permit")
34 }
35 if _, err := s.DeleteMailEventHook(ctx, "bab", "titogo", now); err == nil {
36 t.Fatal("DeleteMailEventHook wrote without a permit")
37 }
38 if err := s.EnqueueMailEventDelivery(ctx, "bab", "titogo", "n1", []byte(`{}`), now); err == nil {
39 t.Fatal("EnqueueMailEventDelivery wrote without a permit")
40 }
41 if err := s.abandonMailEventDeliveries(ctx, "bab", "titogo", "x", now); err == nil {
42 t.Fatal("abandonMailEventDeliveries wrote without a permit")
43 }
44 if err := s.recordMailEventAttempt(ctx, mailEventDelivery{ID: 1, Account: "bab", App: "titogo"}, 200, "", now); err == nil {
45 t.Fatal("recordMailEventAttempt wrote without a permit")
46 }
47 h := mailEventHookRow{Account: "bab", App: "titogo", MailEventHook: MailEventHook{FailingSince: now.Add(-time.Hour)}}
48 if err := s.clearMailEventFailing(ctx, h); err == nil {
49 t.Fatal("clearMailEventFailing wrote without a permit")
50 }
51 if _, err := s.noteMailEventTurn(ctx, h, true, "", now); err == nil {
52 t.Fatal("noteMailEventTurn wrote without a permit")
53 }
54 _ = s.RecordMailMessageEvent(ctx, "bab", "titogo", "n1", ev, true, now)
55 for _, table := range mailAppTables {
56 if n := mailRows(t, s, table); n != 0 {
57 t.Fatalf("%s holds %d rows written without a permit", table, n)
58 }
59 }
60 // An invalid name is refused before any lookup.
61 if err := s.withMailAppSQL(ctx, "BAB", "titogo", "sql.test", func(*Store) error { return nil }); err == nil {
62 t.Fatal("invalid sqid accepted")
63 }
64 if err := s.withMailAppSQL(ctx, "bab", "", "sql.test", func(*Store) error { return nil }); err == nil {
65 t.Fatal("empty app accepted")
66 }
67}
68
69// Flag-off (no gate) the writers behave exactly as before.
70func TestMailSQLWritersUnchangedFlagOff(t *testing.T) {
71 s := openTestStore(t)
72 ctx := context.Background()
73 now := time.Date(2026, 10, 7, 12, 0, 0, 0, time.UTC)
74 if err := s.SetMailEventHook(ctx, "bab", "titogo", "/mail/events", "a@b", now); err != nil {
75 t.Fatal(err)
76 }
77 h, err := s.MailEventHookFor(ctx, "bab", "titogo")
78 if err != nil || h == nil || h.Path != "/mail/events" {
79 t.Fatalf("hook: %+v %v", h, err)
80 }
81 if err := s.RecordMailEvent(ctx, "bab", "titogo", "", "2026-10-07", mail.EventSend); err != nil {
82 t.Fatal(err)
83 }
84 c, err := s.MailCounts(ctx, "bab", "titogo", "", "2026-10-07")
85 if err != nil || c.Sends != 1 {
86 t.Fatalf("counts: %+v %v", c, err)
87 }
88 if err := s.EnqueueMailEventDelivery(ctx, "bab", "titogo", "n1", []byte(`{}`), now); err != nil {
89 t.Fatal(err)
90 }
91 rows, err := s.dueMailEventDeliveriesFor(ctx, "bab", "titogo", now, 5)
92 if err != nil || len(rows) != 1 {
93 t.Fatalf("due: %v %v", rows, err)
94 }
95 // An attempt names its row's own app: a row id with another app's
96 // names updates nothing.
97 forged := rows[0]
98 forged.App = "other"
99 if err := s.recordMailEventAttempt(ctx, forged, 200, "", now); err != nil {
100 t.Fatal(err)
101 }
102 if st, err := s.MailEventPushStatusFor(ctx, "bab", "titogo", now.Add(-time.Hour)); err != nil || st.Delivered != 0 || st.Pending != 1 {
103 t.Fatalf("forged attempt landed: %+v %v", st, err)
104 }
105 if err := s.recordMailEventAttempt(ctx, rows[0], 200, "", now); err != nil {
106 t.Fatal(err)
107 }
108 if st, err := s.MailEventPushStatusFor(ctx, "bab", "titogo", now.Add(-time.Hour)); err != nil || st.Delivered != 1 {
109 t.Fatalf("attempt: %+v %v", st, err)
110 }
111 was, err := s.DeleteMailEventHook(ctx, "bab", "titogo", now)
112 if err != nil || !was {
113 t.Fatalf("delete: %v %v", was, err)
114 }
115}
116