package main import ( "errors" "testing" "github.com/stretchr/testify/require" ) func TestQueuedAppendResumesWithoutADuplicate(t *testing.T) { dir := t.TempDir() memory, err := openMemory(t.Context(), dir, newTestClock().Now, newFakeSummarizer(), discardLog()) require.NoError(t, err) var saved *int first, err := memory.AppendOnce("user", "Record the gate size.", nil, func(id int) error { saved = &id require.Equal(t, 0, memory.log.Len()) return nil }) require.NoError(t, err) require.NoError(t, memory.Close()) memory, err = openMemory(t.Context(), dir, newTestClock().Now, newFakeSummarizer(), discardLog()) require.NoError(t, err) defer func() { require.NoError(t, memory.Close()) }() second, err := memory.AppendOnce("user", first.Text, saved, func(int) error { t.Fatal("a recorded message must not be prepared again") return nil }) require.NoError(t, err) require.Equal(t, first, second) require.Equal(t, 1, memory.Len()) } func TestQueuedAppendRetriesAnUnwrittenPreparedMessage(t *testing.T) { memory, err := openMemory(t.Context(), t.TempDir(), newTestClock().Now, newFakeSummarizer(), discardLog()) require.NoError(t, err) defer func() { require.NoError(t, memory.Close()) }() failure := errors.New("fake queue write failure") var saved *int _, err = memory.AppendOnce("work", "[Garden] Check the gate.", nil, func(id int) error { saved = &id return failure }) require.ErrorIs(t, err, failure) require.Equal(t, 0, memory.Len()) message, err := memory.AppendOnce("work", "[Garden] Check the gate.", saved, func(id int) error { require.Equal(t, *saved, id) return nil }) require.NoError(t, err) require.Equal(t, 0, message.ID) require.Equal(t, 1, memory.Len()) } func TestQueuedAppendRefusesAnInvalidReceipt(t *testing.T) { memory, err := openMemory(t.Context(), t.TempDir(), newTestClock().Now, newFakeSummarizer(), discardLog()) require.NoError(t, err) defer func() { require.NoError(t, memory.Close()) }() _, err = memory.Append("user", "Keep the original.") require.NoError(t, err) testCases := []struct { name string id int cause string }{ { name: "receipt points to different text", id: 0, cause: "does not match", }, { name: "receipt skips a log position", id: 2, cause: "beyond the log", }, { name: "receipt has a negative position", id: -1, cause: "read queued message", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { _, err := memory.AppendOnce("user", "Other text.", &tc.id, func(int) error { t.Fatal("an invalid receipt must not be prepared") return nil }) require.ErrorContains(t, err, tc.cause) require.Equal(t, 1, memory.Len()) }) } }