8 "github.com/stretchr/testify/require"
11 func TestViewMergesInTheOrderOfTheRollbackPush(t *testing.T) {
12 tree := ViewBuiltTree{}
14 var states *ViewPushEntry
15 for tick := range 20001 {
16 states = viewPush(tick, states)
17 starts := states.starts()
18 view.high = len(starts)
19 view.low = len(starts)
20 _, err := view.Append(tree)
21 require.NoError(t, err)
23 lines := make([]int, len(view.lines))
24 for n, line := range view.lines {
25 lines[n] = line.index << line.level
28 require.Equal(t, starts, lines, "t=%d", tick)
32 func TestViewMergesInOneBatchFromHighToLow(t *testing.T) {
33 tree := ViewBuiltTree{}
34 view := newView(10, 5)
35 sizes := make([]int, 0, 20)
37 _, err := view.Append(tree)
38 require.NoError(t, err)
39 sizes = append(sizes, view.Size())
42 require.Equal(t, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 5, 6, 7, 8, 9, 10, 5, 6, 7, 8}, sizes)
45 func TestViewMergesOnlyBuiltParents(t *testing.T) {
47 sizes: map[NodeKey]int{
59 _, err := view.Append(tree)
60 require.NoError(t, err)
63 require.Equal(t, []NodeKey{{0, 0}, {0, 1}, {0, 2}, {0, 3}}, view.lines)
64 require.True(t, view.merging)
66 tree.sizes[NodeKey{1, 0}] = 1
67 _, err := view.Append(tree)
68 require.NoError(t, err)
69 require.Equal(t, []NodeKey{{1, 0}, {0, 2}, {0, 3}, {0, 4}}, view.lines)
70 require.True(t, view.merging)
72 tree.sizes[NodeKey{1, 1}] = 1
73 tree.sizes[NodeKey{1, 2}] = 1
74 tree.sizes[NodeKey{2, 0}] = 1
75 _, err = view.Append(tree)
76 require.NoError(t, err)
77 require.Equal(t, []NodeKey{{2, 0}, {1, 2}}, view.lines)
78 require.False(t, view.merging)
81 func TestViewRendersPendingLinesWithoutTheirMessage(t *testing.T) {
83 sizes: map[NodeKey]int{
90 view, err := restoreView(ViewState{
91 Lines: [][2]int{{1, 0}, {0, 2}},
92 }, viewChatHigh, viewChatLow, tree)
93 require.NoError(t, err)
94 require.Equal(t, "<chat>\n0+2|aaa aaa\n2+1|"+viewPending+"\n</chat>", view.Render())
95 require.Equal(t, 7+len(viewPending), view.Size())
98 func TestViewCoarsenTakesTheCoarserLines(t *testing.T) {
99 view, err := restoreView(ViewState{
100 Lines: [][2]int{{1, 0}, {0, 2}, {0, 3}, {0, 4}, {0, 5}},
101 }, 100, 100, ViewBuiltTree{})
102 require.NoError(t, err)
104 other, err := restoreView(ViewState{
105 Lines: [][2]int{{0, 0}, {0, 1}, {1, 1}, {0, 4}, {0, 5}},
106 }, 100, 100, ViewBuiltTree{})
107 require.NoError(t, err)
109 require.NoError(t, view.Coarsen(other, ViewBuiltTree{}))
110 require.Equal(t, []NodeKey{{1, 0}, {1, 1}, {0, 4}, {0, 5}}, view.lines)
113 require.NoError(t, view.Coarsen(other, ViewBuiltTree{}))
114 require.Equal(t, []NodeKey{{2, 0}, {1, 2}}, view.lines)
115 require.False(t, view.merging)
118 func TestViewContextStopsAtTheFirstPendingLine(t *testing.T) {
119 tree := ViewPartTree{
120 sizes: map[NodeKey]int{
128 view, err := restoreView(ViewState{
129 Lines: [][2]int{{1, 0}, {0, 2}, {0, 3}},
131 require.NoError(t, err)
132 require.Equal(t, "<chat>\n</chat>", view.Context(0))
133 require.Equal(t, "<chat>\n0+2|a\n</chat>", view.Context(2))
134 require.Equal(t, "<chat>\n0+2|a\n</chat>", view.Context(3))
137 func TestRestoreViewRejectsAGap(t *testing.T) {
138 _, err := restoreView(ViewState{
139 Lines: [][2]int{{0, 0}, {0, 2}},
140 }, viewChatHigh, viewChatLow, ViewBuiltTree{})
141 require.ErrorContains(t, err, "does not start at message 1")
144 // ViewBuiltTree is a tree with each node built, with 1 byte of text.
145 type ViewBuiltTree struct{}
147 func (ViewBuiltTree) Built(level, index int) (bool, error) {
151 func (ViewBuiltTree) Node(level, index int) (Node, bool, error) {
152 return treeTestNode(level, index, "a"), true, nil
155 // ViewPushEntry is one entry of the rollback state list of the reference
156 // design, newest first. Under push alone, life stays 0, so the entry leaves it
158 type ViewPushEntry struct {
164 // starts returns the states of the list, oldest first.
165 func (e *ViewPushEntry) starts() []int {
167 for entry := e; entry != nil; entry = entry.older {
168 starts = append(starts, entry.state)
171 slices.Reverse(starts)
176 // ViewPartTree is a tree with the built nodes of its sizes.
177 type ViewPartTree struct {
178 sizes map[NodeKey]int
181 func (p ViewPartTree) Built(level, index int) (bool, error) {
182 _, built := p.sizes[NodeKey{level, index}]
186 func (p ViewPartTree) Node(level, index int) (Node, bool, error) {
187 size, built := p.sizes[NodeKey{level, index}]
189 return Node{}, false, nil
192 text := strings.Repeat("a", size)
197 return treeTestNode(level, index, text), true, nil
200 // viewPush is the push of rollback_state_list.js.
201 func viewPush(state int, states *ViewPushEntry) *ViewPushEntry {
203 return &ViewPushEntry{
209 return &ViewPushEntry{
216 return &ViewPushEntry{
218 older: viewPush(states.state, states.older),