]> git.giacomolli.uk - onechat/blob - memory_delivery_test.go
Resume queued appends at their saved log ID
[onechat] / memory_delivery_test.go
1 package main
2
3 import (
4         "errors"
5         "testing"
6
7         "github.com/stretchr/testify/require"
8 )
9
10 func TestQueuedAppendResumesWithoutADuplicate(t *testing.T) {
11         dir := t.TempDir()
12         memory, err := openMemory(t.Context(), dir, newTestClock().Now, newFakeSummarizer(), discardLog())
13         require.NoError(t, err)
14
15         var saved *int
16
17         first, err := memory.AppendOnce("user", "Record the gate size.", nil, func(id int) error {
18                 saved = &id
19
20                 require.Equal(t, 0, memory.log.Len())
21
22                 return nil
23         })
24         require.NoError(t, err)
25         require.NoError(t, memory.Close())
26
27         memory, err = openMemory(t.Context(), dir, newTestClock().Now, newFakeSummarizer(), discardLog())
28         require.NoError(t, err)
29
30         defer func() {
31                 require.NoError(t, memory.Close())
32         }()
33
34         second, err := memory.AppendOnce("user", first.Text, saved, func(int) error {
35                 t.Fatal("a recorded message must not be prepared again")
36
37                 return nil
38         })
39         require.NoError(t, err)
40         require.Equal(t, first, second)
41         require.Equal(t, 1, memory.Len())
42 }
43
44 func TestQueuedAppendRetriesAnUnwrittenPreparedMessage(t *testing.T) {
45         memory, err := openMemory(t.Context(), t.TempDir(), newTestClock().Now, newFakeSummarizer(), discardLog())
46         require.NoError(t, err)
47
48         defer func() {
49                 require.NoError(t, memory.Close())
50         }()
51
52         failure := errors.New("fake queue write failure")
53
54         var saved *int
55
56         _, err = memory.AppendOnce("work", "[Garden] Check the gate.", nil, func(id int) error {
57                 saved = &id
58
59                 return failure
60         })
61         require.ErrorIs(t, err, failure)
62         require.Equal(t, 0, memory.Len())
63
64         message, err := memory.AppendOnce("work", "[Garden] Check the gate.", saved, func(id int) error {
65                 require.Equal(t, *saved, id)
66
67                 return nil
68         })
69         require.NoError(t, err)
70         require.Equal(t, 0, message.ID)
71         require.Equal(t, 1, memory.Len())
72 }
73
74 func TestQueuedAppendRefusesAnInvalidReceipt(t *testing.T) {
75         memory, err := openMemory(t.Context(), t.TempDir(), newTestClock().Now, newFakeSummarizer(), discardLog())
76         require.NoError(t, err)
77
78         defer func() {
79                 require.NoError(t, memory.Close())
80         }()
81
82         _, err = memory.Append("user", "Keep the original.")
83         require.NoError(t, err)
84
85         testCases := []struct {
86                 name  string
87                 id    int
88                 cause string
89         }{
90                 {
91                         name:  "receipt points to different text",
92                         id:    0,
93                         cause: "does not match",
94                 },
95                 {
96                         name:  "receipt skips a log position",
97                         id:    2,
98                         cause: "beyond the log",
99                 },
100                 {
101                         name:  "receipt has a negative position",
102                         id:    -1,
103                         cause: "read queued message",
104                 },
105         }
106         for _, tc := range testCases {
107                 t.Run(tc.name, func(t *testing.T) {
108                         _, err := memory.AppendOnce("user", "Other text.", &tc.id, func(int) error {
109                                 t.Fatal("an invalid receipt must not be prepared")
110
111                                 return nil
112                         })
113                         require.ErrorContains(t, err, tc.cause)
114                         require.Equal(t, 1, memory.Len())
115                 })
116         }
117 }