1package vt
2
3import (
4 "testing"
5
6 renderer "github.com/bnema/vev-vt/core"
7 "github.com/stretchr/testify/require"
8)
9
10func TestHistorySnapshotViewDoesNotSealTailAndCopiesIt(t *testing.T) {
11 history := NewHistory(HistoryConfig{MaxRows: 8, ChunkRows: 2})
12 requireHistoryAppend(t, history, historyRow("AAAA"))
13 requireHistoryAppend(t, history, historyRow("BBBB"))
14 requireHistoryAppend(t, history, historyRow("CCCC"))
15 sealed := history.View().Chunk(0)
16
17 view := history.SnapshotView()
18 if got, want := view.ChunkCount(), 1; got != want {
19 t.Fatalf("sealed chunks = %d, want %d", got, want)
20 }
21 if view.Chunk(0) != sealed {
22 t.Fatal("snapshot copied an immutable sealed chunk")
23 }
24 if got, want := len(history.tail), 1; got != want {
25 t.Fatalf("live tail rows = %d, want %d; snapshot sealed it", got, want)
26 }
27 history.tail[0][0].Rune = 'X'
28 if got, want := rowText(view.Tail().Row(0)), "CCCC"; got != want {
29 t.Fatalf("snapshot tail = %q, want %q", got, want)
30 }
31 if got, want := view.Len(), 3; got != want {
32 t.Fatalf("snapshot rows = %d, want %d", got, want)
33 }
34 if got, want := view.Cells(), 12; got != want {
35 t.Fatalf("snapshot cells = %d, want %d", got, want)
36 }
37 wantID := view.Tail().RowID(0)
38 history.tailIDs[0] = 99
39 if got := view.Tail().RowID(0); got != wantID {
40 t.Fatalf("snapshot tail ID = %d after live mutation, want %d", got, wantID)
41 }
42
43 tail, err := MarshalHistoryTail(view)
44 require.NoError(t, err)
45 decoded, err := UnmarshalHistory(tail)
46 require.NoError(t, err)
47 require.Equal(t, []string{"CCCC"}, historyViewTexts(decoded))
48}
49
50func TestHistoryFromBlobsNormalizesFullTailBeforeAppend(t *testing.T) {
51 fullTail, err := MarshalHistory(HistoryView{
52 chunks: []*HistoryChunk{{rows: [][]renderer.Cell{historyRow("AAAA"), historyRow("BBBB")}, rowIDs: []RowID{1, 2}}},
53 rows: 2,
54 nextRowID: 3,
55 })
56 require.NoError(t, err)
57
58 restored, err := HistoryFromBlobs(HistoryConfig{MaxRows: 4, ChunkRows: 2}, nil, fullTail)
59 require.NoError(t, err)
60 requireHistoryAppend(t, restored, historyRow("CCCC"))
61
62 require.Equal(t, []string{"AAAA", "BBBB", "CCCC"}, historyViewTexts(restored.View()))
63 require.Len(t, restored.chunks, 1, "a full restored tail must become sealed")
64 require.Len(t, restored.tail, 1, "the appended row must be the mutable tail")
65}
66
67func TestHistoryFromBlobsRestoresCellAccountingAndEvictsToBothBudgets(t *testing.T) {
68 history := NewHistory(HistoryConfig{MaxRows: 4, MaxCells: 10, ChunkRows: 2})
69 for _, text := range []string{"a", "b", "cc"} {
70 requireHistoryAppend(t, history, historyRow(text))
71 }
72 view := history.SnapshotView()
73 sealed := make([][]byte, view.ChunkCount())
74 for i := range sealed {
75 var err error
76 sealed[i], err = MarshalHistoryChunk(view.Chunk(i))
77 require.NoError(t, err)
78 }
79 tail, err := MarshalHistoryTail(view)
80 require.NoError(t, err)
81
82 restored, err := HistoryFromBlobs(HistoryConfig{MaxRows: 4, MaxCells: 2, ChunkRows: 2}, sealed, tail)
83 require.NoError(t, err)
84 require.Equal(t, []string{"cc"}, historyViewTexts(restored.View()))
85 require.Equal(t, 2, restored.Cells())
86}