X-Git-Url: http://git.giacomolli.uk/onechat/blobdiff_plain/feda522eba3e2a27c91741c77d0d01f1840c0004..0a98ccb67c3df55c0fe6d76b45afcbaa58c2eda1:/view_test.go
diff --git a/view_test.go b/view_test.go
index 2900860..56abdd6 100644
--- a/view_test.go
+++ b/view_test.go
@@ -8,12 +8,12 @@ import (
"github.com/stretchr/testify/require"
)
-func TestViewMergesInTheOrderOfTaelinsPush(t *testing.T) {
- tree := builtTree{}
+func TestViewMergesInTheOrderOfTheRollbackPush(t *testing.T) {
+ tree := ViewBuiltTree{}
view := newView(0, 0)
- var states *pushEntry
+ var states *ViewPushEntry
for tick := range 20001 {
- states = push(tick, states)
+ states = viewPush(tick, states)
starts := states.starts()
view.high = len(starts)
view.low = len(starts)
@@ -30,7 +30,7 @@ func TestViewMergesInTheOrderOfTaelinsPush(t *testing.T) {
}
func TestViewMergesInOneBatchFromHighToLow(t *testing.T) {
- tree := builtTree{}
+ tree := ViewBuiltTree{}
view := newView(10, 5)
sizes := make([]int, 0, 20)
for range 20 {
@@ -43,8 +43,8 @@ func TestViewMergesInOneBatchFromHighToLow(t *testing.T) {
}
func TestViewMergesOnlyBuiltParents(t *testing.T) {
- tree := partTree{
- sizes: map[nodeKey]int{
+ tree := ViewPartTree{
+ sizes: map[NodeKey]int{
{0, 0}: 1,
{0, 1}: 1,
{0, 2}: 1,
@@ -60,64 +60,64 @@ func TestViewMergesOnlyBuiltParents(t *testing.T) {
require.NoError(t, err)
}
- require.Equal(t, []nodeKey{{0, 0}, {0, 1}, {0, 2}, {0, 3}}, view.lines)
+ require.Equal(t, []NodeKey{{0, 0}, {0, 1}, {0, 2}, {0, 3}}, view.lines)
require.True(t, view.merging)
- tree.sizes[nodeKey{1, 0}] = 1
+ tree.sizes[NodeKey{1, 0}] = 1
_, err := view.Append(tree)
require.NoError(t, err)
- require.Equal(t, []nodeKey{{1, 0}, {0, 2}, {0, 3}, {0, 4}}, view.lines)
+ require.Equal(t, []NodeKey{{1, 0}, {0, 2}, {0, 3}, {0, 4}}, view.lines)
require.True(t, view.merging)
- tree.sizes[nodeKey{1, 1}] = 1
- tree.sizes[nodeKey{1, 2}] = 1
- tree.sizes[nodeKey{2, 0}] = 1
+ tree.sizes[NodeKey{1, 1}] = 1
+ tree.sizes[NodeKey{1, 2}] = 1
+ tree.sizes[NodeKey{2, 0}] = 1
_, err = view.Append(tree)
require.NoError(t, err)
- require.Equal(t, []nodeKey{{2, 0}, {1, 2}}, view.lines)
+ require.Equal(t, []NodeKey{{2, 0}, {1, 2}}, view.lines)
require.False(t, view.merging)
}
func TestViewRendersPendingLinesWithoutTheirMessage(t *testing.T) {
- tree := partTree{
- sizes: map[nodeKey]int{
+ tree := ViewPartTree{
+ sizes: map[NodeKey]int{
{0, 0}: 3,
{0, 1}: 3,
{1, 0}: 7,
},
}
- view, err := restoreView(viewState{
+ view, err := restoreView(ViewState{
Lines: [][2]int{{1, 0}, {0, 2}},
- }, chatHigh, chatLow, tree)
+ }, viewChatHigh, viewChatLow, tree)
require.NoError(t, err)
- require.Equal(t, "\n0+2|aaa aaa\n2+1|"+pending+"\n", view.Render())
- require.Equal(t, 7+len(pending), view.Size())
+ require.Equal(t, "\n0+2|aaa aaa\n2+1|"+viewPending+"\n", view.Render())
+ require.Equal(t, 7+len(viewPending), view.Size())
}
func TestViewCoarsenTakesTheCoarserLines(t *testing.T) {
- view, err := restoreView(viewState{
+ view, err := restoreView(ViewState{
Lines: [][2]int{{1, 0}, {0, 2}, {0, 3}, {0, 4}, {0, 5}},
- }, 100, 100, builtTree{})
+ }, 100, 100, ViewBuiltTree{})
require.NoError(t, err)
- other, err := restoreView(viewState{
+ other, err := restoreView(ViewState{
Lines: [][2]int{{0, 0}, {0, 1}, {1, 1}, {0, 4}, {0, 5}},
- }, 100, 100, builtTree{})
+ }, 100, 100, ViewBuiltTree{})
require.NoError(t, err)
- require.NoError(t, view.Coarsen(other, builtTree{}))
- require.Equal(t, []nodeKey{{1, 0}, {1, 1}, {0, 4}, {0, 5}}, view.lines)
+ require.NoError(t, view.Coarsen(other, ViewBuiltTree{}))
+ require.Equal(t, []NodeKey{{1, 0}, {1, 1}, {0, 4}, {0, 5}}, view.lines)
view.low = 2
- require.NoError(t, view.Coarsen(other, builtTree{}))
- require.Equal(t, []nodeKey{{2, 0}, {1, 2}}, view.lines)
+ require.NoError(t, view.Coarsen(other, ViewBuiltTree{}))
+ require.Equal(t, []NodeKey{{2, 0}, {1, 2}}, view.lines)
require.False(t, view.merging)
}
func TestViewContextStopsAtTheFirstPendingLine(t *testing.T) {
- tree := partTree{
- sizes: map[nodeKey]int{
+ tree := ViewPartTree{
+ sizes: map[NodeKey]int{
{0, 0}: 1,
{0, 1}: 1,
{1, 0}: 1,
@@ -125,7 +125,7 @@ func TestViewContextStopsAtTheFirstPendingLine(t *testing.T) {
},
}
- view, err := restoreView(viewState{
+ view, err := restoreView(ViewState{
Lines: [][2]int{{1, 0}, {0, 2}, {0, 3}},
}, 100, 100, tree)
require.NoError(t, err)
@@ -135,44 +135,34 @@ func TestViewContextStopsAtTheFirstPendingLine(t *testing.T) {
}
func TestRestoreViewRejectsAGap(t *testing.T) {
- _, err := restoreView(viewState{
+ _, err := restoreView(ViewState{
Lines: [][2]int{{0, 0}, {0, 2}},
- }, chatHigh, chatLow, builtTree{})
+ }, viewChatHigh, viewChatLow, ViewBuiltTree{})
require.ErrorContains(t, err, "does not start at message 1")
}
-// pushEntry is one entry of Taelin's rollback state list, newest first. Under
-// push alone, life stays 0, so the entry leaves it out.
-type pushEntry struct {
- keep bool
- state int
- older *pushEntry
-}
+// ViewBuiltTree is a tree with each node built, with 1 byte of text.
+type ViewBuiltTree struct{}
-// push is the push of rollback_state_list.js.
-func push(state int, states *pushEntry) *pushEntry {
- if states == nil {
- return &pushEntry{
- state: state,
- }
- }
+func (ViewBuiltTree) Built(level, index int) (bool, error) {
+ return true, nil
+}
- if !states.keep {
- return &pushEntry{
- keep: true,
- state: states.state,
- older: states.older,
- }
- }
+func (ViewBuiltTree) Node(level, index int) (Node, bool, error) {
+ return treeTestNode(level, index, "a"), true, nil
+}
- return &pushEntry{
- state: state,
- older: push(states.state, states.older),
- }
+// ViewPushEntry is one entry of the rollback state list of the reference
+// design, newest first. Under push alone, life stays 0, so the entry leaves it
+// out.
+type ViewPushEntry struct {
+ keep bool
+ state int
+ older *ViewPushEntry
}
// starts returns the states of the list, oldest first.
-func (e *pushEntry) starts() []int {
+func (e *ViewPushEntry) starts() []int {
var starts []int
for entry := e; entry != nil; entry = entry.older {
starts = append(starts, entry.state)
@@ -183,29 +173,18 @@ func (e *pushEntry) starts() []int {
return starts
}
-// builtTree is a tree with each node built, with 1 byte of text.
-type builtTree struct{}
-
-func (builtTree) Built(level, index int) (bool, error) {
- return true, nil
-}
-
-func (builtTree) Node(level, index int) (Node, bool, error) {
- return testNode(level, index, "a"), true, nil
+// ViewPartTree is a tree with the built nodes of its sizes.
+type ViewPartTree struct {
+ sizes map[NodeKey]int
}
-// partTree is a tree with the built nodes of its sizes.
-type partTree struct {
- sizes map[nodeKey]int
-}
-
-func (p partTree) Built(level, index int) (bool, error) {
- _, built := p.sizes[nodeKey{level, index}]
+func (p ViewPartTree) Built(level, index int) (bool, error) {
+ _, built := p.sizes[NodeKey{level, index}]
return built, nil
}
-func (p partTree) Node(level, index int) (Node, bool, error) {
- size, built := p.sizes[nodeKey{level, index}]
+func (p ViewPartTree) Node(level, index int) (Node, bool, error) {
+ size, built := p.sizes[NodeKey{level, index}]
if !built {
return Node{}, false, nil
}
@@ -215,5 +194,31 @@ func (p partTree) Node(level, index int) (Node, bool, error) {
text = "aaa\naaa"
}
- return testNode(level, index, text), true, nil
+ return treeTestNode(level, index, text), true, nil
+}
+
+// viewPush adds state to the newest end of states and returns the new list. An
+// empty list gets one entry. When the newest entry is not kept, it becomes kept
+// with its own state, and state is dropped. When it is kept, state becomes a
+// new newest entry, and the state of the old newest entry goes to the older
+// entries by the same push.
+func viewPush(state int, states *ViewPushEntry) *ViewPushEntry {
+ if states == nil {
+ return &ViewPushEntry{
+ state: state,
+ }
+ }
+
+ if !states.keep {
+ return &ViewPushEntry{
+ keep: true,
+ state: states.state,
+ older: states.older,
+ }
+ }
+
+ return &ViewPushEntry{
+ state: state,
+ older: viewPush(states.state, states.older),
+ }
}