From d043d58ab6b635e0301be88a03dd5fd7632408be Mon Sep 17 00:00:00 2001
From: Jeounghui
Date: Tue, 30 Jan 2024 16:06:10 +0900
Subject: [PATCH 1/6] Add merge concurrency test
---
test/integration/tree_concurrency_test.go | 48 ++++++++++++++++++++++-
test/integration/tree_test.go | 4 +-
2 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/test/integration/tree_concurrency_test.go b/test/integration/tree_concurrency_test.go
index b62e41706..2fda715b5 100644
--- a/test/integration/tree_concurrency_test.go
+++ b/test/integration/tree_concurrency_test.go
@@ -30,6 +30,24 @@ import (
"github.com/yorkie-team/yorkie/test/helper"
)
+func parseSimpleXML(s string) []string {
+ res := []string{}
+ for i := 0; i < len(s); i++ {
+ now := ``
+ if s[i] == '<' {
+ for i < len(s) && s[i] != '>' {
+ now += string(s[i])
+ i++
+ }
+ now += string(s[i])
+ } else {
+ now += string(s[i])
+ }
+ res = append(res, now)
+ }
+ return res
+}
+
type testResult struct {
flag bool
resultDesc string
@@ -77,6 +95,20 @@ func makeTwoRanges(from1, mid1, to1 int, from2, mid2, to2 int, desc string) twoR
return twoRangesType{[2]rangeWithMiddleType{range0, range1}, desc}
}
+func getMergeRange(xml string, interval rangeType) rangeType {
+ content := parseSimpleXML(xml)
+ st, ed := -1, -1
+ for i := interval.from + 1; i <= interval.to; i++ {
+ if st == -1 && len(content[i]) >= 2 && content[i][0] == '<' && content[i][1] == '/' {
+ st = i - 1
+ }
+ if len(content[i]) >= 2 && content[i][0] == '<' && content[i][1] != '/' {
+ ed = i
+ }
+ }
+ return rangeType{st, ed}
+}
+
type styleOpCode int
type editOpCode int
@@ -89,6 +121,7 @@ const (
const (
EditUndefined editOpCode = iota
EditUpdate
+ MergeUpdate
)
type operationInterface interface {
@@ -138,7 +171,15 @@ func (op editOperationType) run(t *testing.T, doc *document.Document, user int,
from, to := interval.from, interval.to
assert.NoError(t, doc.Update(func(root *json.Object, p *presence.Presence) error {
- root.GetTree("t").Edit(from, to, op.content, op.splitLevel)
+ if op.op == EditUpdate {
+ root.GetTree("t").Edit(from, to, op.content, op.splitLevel)
+ } else if op.op == MergeUpdate {
+ mergeInterval := getMergeRange(root.GetTree("t").ToXML(), interval)
+ from, to = mergeInterval.from, mergeInterval.to
+ if from != -1 && to != -1 && from < to {
+ root.GetTree("t").Edit(mergeInterval.from, mergeInterval.to, op.content, op.splitLevel)
+ }
+ }
return nil
}))
}
@@ -247,6 +288,7 @@ func TestTreeConcurrencyEditEdit(t *testing.T) {
editOperationType{RangeBack, EditUpdate, elementNode1, 0, `insertElementBack`},
editOperationType{RangeAll, EditUpdate, elementNode1, 0, `replaceElement`},
editOperationType{RangeAll, EditUpdate, nil, 0, `delete`},
+ editOperationType{RangeAll, MergeUpdate, nil, 0, `merge`},
}
editOperations2 := []operationInterface{
@@ -259,6 +301,7 @@ func TestTreeConcurrencyEditEdit(t *testing.T) {
editOperationType{RangeBack, EditUpdate, elementNode2, 0, `insertElementBack`},
editOperationType{RangeAll, EditUpdate, elementNode2, 0, `replaceElement`},
editOperationType{RangeAll, EditUpdate, nil, 0, `delete`},
+ editOperationType{RangeAll, MergeUpdate, nil, 0, `merge`},
}
RunTestTreeConcurrency("concurrently-edit-edit-test", t, initialState, initialXML, ranges, editOperations1, editOperations2)
@@ -326,6 +369,8 @@ func TestTreeConcurrencyEditStyle(t *testing.T) {
ranges := []twoRangesType{
// equal: b
- b
makeTwoRanges(3, 3, 6, 3, -1, 6, `equal`),
+ // equal multiple: a
b
c
- a
b
c
+ makeTwoRanges(0, 3, 9, 0, 3, 9, `equal multiple`),
// A contains B: a
b
c
- b
makeTwoRanges(0, 3, 9, 3, -1, 6, `A contains B`),
// B contains A: b
- a
b
c
@@ -344,6 +389,7 @@ func TestTreeConcurrencyEditStyle(t *testing.T) {
editOperationType{RangeBack, EditUpdate, content, 0, `insertBack`},
editOperationType{RangeAll, EditUpdate, nil, 0, `delete`},
editOperationType{RangeAll, EditUpdate, content, 0, `replace`},
+ editOperationType{RangeAll, MergeUpdate, nil, 0, `merge`},
}
styleOperations := []operationInterface{
diff --git a/test/integration/tree_test.go b/test/integration/tree_test.go
index 38df94629..5afb68c8d 100644
--- a/test/integration/tree_test.go
+++ b/test/integration/tree_test.go
@@ -1343,7 +1343,7 @@ func TestTree(t *testing.T) {
assert.Equal(t, "a
b
", d1.Root().GetTree("t").ToXML())
})
- t.Run("contained-split-and-split-at-diffrent-positions-on-the-same-node", func(t *testing.T) {
+ t.Run("contained-split-and-split-at-different-positions-on-the-same-node", func(t *testing.T) {
ctx := context.Background()
d1 := document.New(helper.TestDocKey(t))
assert.NoError(t, c1.Attach(ctx, d1))
@@ -2623,7 +2623,7 @@ func TestTree(t *testing.T) {
assert.Equal(t, "a
b
", d1.Root().GetTree("t").ToXML())
})
- t.Run("side-by-side-split-and-delete", func(t *testing.T) {
+ t.Run("side-by-side-split-and-merge", func(t *testing.T) {
ctx := context.Background()
d1 := document.New(helper.TestDocKey(t))
assert.NoError(t, c1.Attach(ctx, d1))
From 7e167cf1dc4441d942e87702cf45d688f8293ea5 Mon Sep 17 00:00:00 2001
From: Jeounghui
Date: Wed, 31 Jan 2024 15:02:45 +0900
Subject: [PATCH 2/6] Add split edit test, split style test
---
test/integration/tree_concurrency_test.go | 81 +++++++++++++++++++++--
1 file changed, 77 insertions(+), 4 deletions(-)
diff --git a/test/integration/tree_concurrency_test.go b/test/integration/tree_concurrency_test.go
index 2fda715b5..540344642 100644
--- a/test/integration/tree_concurrency_test.go
+++ b/test/integration/tree_concurrency_test.go
@@ -61,6 +61,8 @@ const (
RangeMiddle
RangeBack
RangeAll
+ RangeOneQuarter
+ RangeThreeQuarter
)
type rangeType struct {
@@ -77,14 +79,22 @@ type twoRangesType struct {
}
func getRange(ranges twoRangesType, selector rangeSelector, user int) rangeType {
+ interval := ranges.ranges[user]
+ from, mid, to := interval.from, interval.mid, interval.to
if selector == RangeFront {
- return rangeType{ranges.ranges[user].from, ranges.ranges[user].from}
+ return rangeType{from, from}
} else if selector == RangeMiddle {
- return rangeType{ranges.ranges[user].mid, ranges.ranges[user].mid}
+ return rangeType{mid, mid}
} else if selector == RangeBack {
- return rangeType{ranges.ranges[user].to, ranges.ranges[user].to}
+ return rangeType{to, to}
} else if selector == RangeAll {
- return rangeType{ranges.ranges[user].from, ranges.ranges[user].to}
+ return rangeType{from, to}
+ } else if selector == RangeOneQuarter {
+ pos := (from + mid) / 2
+ return rangeType{pos, pos}
+ } else if selector == RangeThreeQuarter {
+ pos := (mid + to) / 2
+ return rangeType{pos, pos}
}
return rangeType{-1, -1}
}
@@ -122,6 +132,7 @@ const (
EditUndefined editOpCode = iota
EditUpdate
MergeUpdate
+ SplitUpdate
)
type operationInterface interface {
@@ -179,6 +190,10 @@ func (op editOperationType) run(t *testing.T, doc *document.Document, user int,
if from != -1 && to != -1 && from < to {
root.GetTree("t").Edit(mergeInterval.from, mergeInterval.to, op.content, op.splitLevel)
}
+ } else if op.op == SplitUpdate {
+ assert.NotEqual(t, 0, op.splitLevel)
+ assert.Equal(t, from, to)
+ root.GetTree("t").Edit(from, to, op.content, op.splitLevel)
}
return nil
}))
@@ -307,6 +322,64 @@ func TestTreeConcurrencyEditEdit(t *testing.T) {
RunTestTreeConcurrency("concurrently-edit-edit-test", t, initialState, initialXML, ranges, editOperations1, editOperations2)
}
+func TestTreeConcurrencySplitEdit(t *testing.T) {
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+ //
a b c d
e f g h
i j k l
+
+ initialState := json.TreeNode{
+ Type: "root",
+ Children: []json.TreeNode{
+ {Type: "p", Children: []json.TreeNode{
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "abcd"}}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "efgh"}}},
+ }},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ijkl"}}},
+ },
+ }
+ initialXML := `abcd
efgh
ijkl
`
+
+ content := &json.TreeNode{Type: "i", Children: []json.TreeNode{}}
+
+ ranges := []twoRangesType{
+ // equal: ab'cd
+ makeTwoRanges(1, 4, 7, 2, 4, 6, `equal`),
+ // A contains B: ab'cd
- bc
+ makeTwoRanges(1, 4, 7, 3, 4, 5, `A contains B`),
+ // B contains A: ab'cd
- abcd
efgh
+ makeTwoRanges(1, 4, 7, 1, 7, 13, `B contains A`),
+ // left node(text): ab'cd
- ab
+ makeTwoRanges(1, 4, 7, 2, 3, 4, `left node(text)`),
+ // right node(text): ab'cd
- cd
+ makeTwoRanges(1, 4, 7, 4, 5, 6, `right node(text)`),
+ // left node(element): abcd
'efgh
- abcd
+ makeTwoRanges(1, 7, 13, 1, 4, 7, `left node(element)`),
+ // right node(element): abcd
'efgh
- efgh
+ makeTwoRanges(1, 7, 13, 7, 10, 13, `right node(element)`),
+ // A -> B: ab'cd
- efgh
+ makeTwoRanges(1, 4, 7, 7, 10, 13, `A -> B`),
+ // B -> A: ef'gh
- abcd
+ makeTwoRanges(7, 10, 13, 1, 4, 7, `B -> A`),
+ }
+
+ splitOperations := []operationInterface{
+ editOperationType{RangeMiddle, SplitUpdate, nil, 1, `split-1`},
+ editOperationType{RangeMiddle, SplitUpdate, nil, 1, `split-2`},
+ }
+
+ editOperations := []operationInterface{
+ editOperationType{RangeFront, EditUpdate, content, 0, `insertFront`},
+ editOperationType{RangeMiddle, EditUpdate, content, 0, `insertMiddle`},
+ editOperationType{RangeBack, EditUpdate, content, 0, `insertBack`},
+ editOperationType{RangeAll, EditUpdate, content, 0, "replace"},
+ editOperationType{RangeAll, EditUpdate, nil, 0, `delete`},
+ editOperationType{RangeAll, MergeUpdate, nil, 0, `merge`},
+ styleOperationType{RangeAll, StyleSet, "bold", "aa", `style`},
+ styleOperationType{RangeAll, StyleRemove, "bold", "", `remove-style`},
+ }
+
+ RunTestTreeConcurrency("concurrently-split-edit-test", t, initialState, initialXML, ranges, splitOperations, editOperations)
+}
+
func TestTreeConcurrencyStyleStyle(t *testing.T) {
// 0 1 2 3 4 5 6 7 8 9
// a
b
c
From dae401caed537900f80f2d34d12acb5cb8334054 Mon Sep 17 00:00:00 2001
From: Jeounghui
Date: Wed, 31 Jan 2024 15:17:14 +0900
Subject: [PATCH 3/6] Fix style test to recognize remove style error
---
test/integration/tree_concurrency_test.go | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/test/integration/tree_concurrency_test.go b/test/integration/tree_concurrency_test.go
index 540344642..04735b279 100644
--- a/test/integration/tree_concurrency_test.go
+++ b/test/integration/tree_concurrency_test.go
@@ -330,13 +330,13 @@ func TestTreeConcurrencySplitEdit(t *testing.T) {
Type: "root",
Children: []json.TreeNode{
{Type: "p", Children: []json.TreeNode{
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "abcd"}}},
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "efgh"}}},
- }},
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ijkl"}}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "abcd"}}, Attributes: map[string]string{"italic": "true"}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "efgh"}}, Attributes: map[string]string{"italic": "true"}},
+ }, Attributes: map[string]string{"italic": "true"}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ijkl"}}, Attributes: map[string]string{"italic": "true"}},
},
}
- initialXML := `abcd
efgh
ijkl
`
+ initialXML := `abcd
efgh
ijkl
`
content := &json.TreeNode{Type: "i", Children: []json.TreeNode{}}
@@ -374,7 +374,7 @@ func TestTreeConcurrencySplitEdit(t *testing.T) {
editOperationType{RangeAll, EditUpdate, nil, 0, `delete`},
editOperationType{RangeAll, MergeUpdate, nil, 0, `merge`},
styleOperationType{RangeAll, StyleSet, "bold", "aa", `style`},
- styleOperationType{RangeAll, StyleRemove, "bold", "", `remove-style`},
+ styleOperationType{RangeAll, StyleRemove, "italic", "", `remove-style`},
}
RunTestTreeConcurrency("concurrently-split-edit-test", t, initialState, initialXML, ranges, splitOperations, editOperations)
@@ -430,12 +430,12 @@ func TestTreeConcurrencyEditStyle(t *testing.T) {
initialState := json.TreeNode{
Type: "root",
Children: []json.TreeNode{
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "a"}}},
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "b"}}},
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "c"}}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "a"}}, Attributes: map[string]string{"color": "red"}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "b"}}, Attributes: map[string]string{"color": "red"}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "c"}}, Attributes: map[string]string{"color": "red"}},
},
}
- initialXML := `a
b
c
`
+ initialXML := `a
b
c
`
content := &json.TreeNode{Type: "p", Attributes: map[string]string{"italic": "true"}, Children: []json.TreeNode{{Type: "text", Value: `d`}}}
@@ -466,7 +466,7 @@ func TestTreeConcurrencyEditStyle(t *testing.T) {
}
styleOperations := []operationInterface{
- styleOperationType{RangeAll, StyleRemove, "bold", "", `remove-bold`},
+ styleOperationType{RangeAll, StyleRemove, "color", "", `remove-bold`},
styleOperationType{RangeAll, StyleSet, "bold", "aa", `set-bold-aa`},
}
From 0774d372d08709de2bfd80ab7f60f2a439334979 Mon Sep 17 00:00:00 2001
From: Jeounghui
Date: Wed, 31 Jan 2024 15:57:37 +0900
Subject: [PATCH 4/6] Add split split test for splitLevel = 1
---
test/integration/tree_concurrency_test.go | 47 ++++++++++++++++++++++-
1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/test/integration/tree_concurrency_test.go b/test/integration/tree_concurrency_test.go
index 04735b279..e43d75702 100644
--- a/test/integration/tree_concurrency_test.go
+++ b/test/integration/tree_concurrency_test.go
@@ -90,7 +90,7 @@ func getRange(ranges twoRangesType, selector rangeSelector, user int) rangeType
} else if selector == RangeAll {
return rangeType{from, to}
} else if selector == RangeOneQuarter {
- pos := (from + mid) / 2
+ pos := (from + mid + 1) / 2
return rangeType{pos, pos}
} else if selector == RangeThreeQuarter {
pos := (mid + to) / 2
@@ -322,6 +322,50 @@ func TestTreeConcurrencyEditEdit(t *testing.T) {
RunTestTreeConcurrency("concurrently-edit-edit-test", t, initialState, initialXML, ranges, editOperations1, editOperations2)
}
+// TODO(justiceHui): add split test for splitLevel > 1
+func TestTreeConcurrencySplitSplit(t *testing.T) {
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
+ //
a b c d
e f g h
i j k l
+
+ initialState := json.TreeNode{
+ Type: "root",
+ Children: []json.TreeNode{
+ {
+ Type: "p", Children: []json.TreeNode{
+ {Type: "p", Children: []json.TreeNode{
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "abcd"}}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "efgh"}}},
+ }},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ijkl"}}},
+ },
+ },
+ },
+ }
+ initialXML := `abcd
efgh
ijkl
`
+
+ ranges := []twoRangesType{
+ // equal-single-element: abcd
+ makeTwoRanges(2, 5, 8, 2, 5, 8, `equal-single`),
+ // equal-multiple-element: abcd
efgh
+ makeTwoRanges(2, 8, 14, 2, 8, 14, `equal-multiple`),
+ // A contains B same level: abcd
efgh
- efgh
+ makeTwoRanges(2, 8, 14, 8, 11, 14, `A contains B same level`),
+ // A contains B multiple level: abcd
efgh
ijkl
- efgh
+ makeTwoRanges(1, 15, 21, 8, 11, 14, `A contains B multiple level`),
+ // side by side
+ makeTwoRanges(2, 5, 8, 8, 11, 14, `B is next to A`),
+ }
+
+ splitOperations := []operationInterface{
+ editOperationType{RangeFront, SplitUpdate, nil, 1, `split-front-1`},
+ editOperationType{RangeOneQuarter, SplitUpdate, nil, 1, `split-one-quarter-1`},
+ editOperationType{RangeThreeQuarter, SplitUpdate, nil, 1, `split-three-quarter-1`},
+ editOperationType{RangeBack, SplitUpdate, nil, 1, `split-back-1`},
+ }
+
+ RunTestTreeConcurrency("concurrently-split-split-test", t, initialState, initialXML, ranges, splitOperations, splitOperations)
+}
+
func TestTreeConcurrencySplitEdit(t *testing.T) {
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
//
a b c d
e f g h
i j k l
@@ -363,7 +407,6 @@ func TestTreeConcurrencySplitEdit(t *testing.T) {
splitOperations := []operationInterface{
editOperationType{RangeMiddle, SplitUpdate, nil, 1, `split-1`},
- editOperationType{RangeMiddle, SplitUpdate, nil, 1, `split-2`},
}
editOperations := []operationInterface{
From fb9c6c4bee00995688b4499d4af56c97c8fc681e Mon Sep 17 00:00:00 2001
From: Jeounghui
Date: Wed, 31 Jan 2024 16:16:48 +0900
Subject: [PATCH 5/6] Add split edit test for splitLevel = 2
---
test/integration/tree_concurrency_test.go | 53 ++++++++++++-----------
1 file changed, 27 insertions(+), 26 deletions(-)
diff --git a/test/integration/tree_concurrency_test.go b/test/integration/tree_concurrency_test.go
index e43d75702..9a921a009 100644
--- a/test/integration/tree_concurrency_test.go
+++ b/test/integration/tree_concurrency_test.go
@@ -324,21 +324,19 @@ func TestTreeConcurrencyEditEdit(t *testing.T) {
// TODO(justiceHui): add split test for splitLevel > 1
func TestTreeConcurrencySplitSplit(t *testing.T) {
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
//
a b c d
e f g h
i j k l
initialState := json.TreeNode{
Type: "root",
Children: []json.TreeNode{
- {
- Type: "p", Children: []json.TreeNode{
- {Type: "p", Children: []json.TreeNode{
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "abcd"}}},
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "efgh"}}},
- }},
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ijkl"}}},
- },
- },
+ {Type: "p", Children: []json.TreeNode{
+ {Type: "p", Children: []json.TreeNode{
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "abcd"}}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "efgh"}}},
+ }},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ijkl"}}},
+ }},
},
}
initialXML := `abcd
efgh
ijkl
`
@@ -367,46 +365,49 @@ func TestTreeConcurrencySplitSplit(t *testing.T) {
}
func TestTreeConcurrencySplitEdit(t *testing.T) {
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
- //
a b c d
e f g h
i j k l
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
+ //
a b c d
e f g h
i j k l
initialState := json.TreeNode{
Type: "root",
Children: []json.TreeNode{
{Type: "p", Children: []json.TreeNode{
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "abcd"}}, Attributes: map[string]string{"italic": "true"}},
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "efgh"}}, Attributes: map[string]string{"italic": "true"}},
- }, Attributes: map[string]string{"italic": "true"}},
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ijkl"}}, Attributes: map[string]string{"italic": "true"}},
+ {Type: "p", Children: []json.TreeNode{
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "abcd"}}, Attributes: map[string]string{"italic": "true"}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "efgh"}}, Attributes: map[string]string{"italic": "true"}},
+ }, Attributes: map[string]string{"italic": "true"}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ijkl"}}, Attributes: map[string]string{"italic": "true"}},
+ }},
},
}
- initialXML := `abcd
efgh
ijkl
`
+ initialXML := `abcd
efgh
ijkl
`
content := &json.TreeNode{Type: "i", Children: []json.TreeNode{}}
ranges := []twoRangesType{
// equal: ab'cd
- makeTwoRanges(1, 4, 7, 2, 4, 6, `equal`),
+ makeTwoRanges(2, 5, 8, 2, 5, 8, `equal`),
// A contains B: ab'cd
- bc
- makeTwoRanges(1, 4, 7, 3, 4, 5, `A contains B`),
+ makeTwoRanges(2, 5, 8, 4, 5, 6, `A contains B`),
// B contains A: ab'cd
- abcd
efgh
- makeTwoRanges(1, 4, 7, 1, 7, 13, `B contains A`),
+ makeTwoRanges(2, 5, 8, 2, 8, 14, `B contains A`),
// left node(text): ab'cd
- ab
- makeTwoRanges(1, 4, 7, 2, 3, 4, `left node(text)`),
+ makeTwoRanges(2, 5, 8, 3, 4, 5, `left node(text)`),
// right node(text): ab'cd
- cd
- makeTwoRanges(1, 4, 7, 4, 5, 6, `right node(text)`),
+ makeTwoRanges(2, 5, 8, 5, 6, 7, `right node(text)`),
// left node(element): abcd
'efgh
- abcd
- makeTwoRanges(1, 7, 13, 1, 4, 7, `left node(element)`),
+ makeTwoRanges(2, 8, 14, 2, 5, 8, `left node(element)`),
// right node(element): abcd
'efgh
- efgh
- makeTwoRanges(1, 7, 13, 7, 10, 13, `right node(element)`),
+ makeTwoRanges(2, 8, 14, 8, 11, 14, `right node(element)`),
// A -> B: ab'cd
- efgh
- makeTwoRanges(1, 4, 7, 7, 10, 13, `A -> B`),
+ makeTwoRanges(2, 5, 8, 8, 11, 14, `A -> B`),
// B -> A: ef'gh
- abcd
- makeTwoRanges(7, 10, 13, 1, 4, 7, `B -> A`),
+ makeTwoRanges(8, 11, 14, 2, 5, 8, `B -> A`),
}
splitOperations := []operationInterface{
editOperationType{RangeMiddle, SplitUpdate, nil, 1, `split-1`},
+ editOperationType{RangeMiddle, SplitUpdate, nil, 2, `split-2`},
}
editOperations := []operationInterface{
From 13914477380e3fcf42519412b2dc043f463e62f0 Mon Sep 17 00:00:00 2001
From: Jeounghui
Date: Wed, 31 Jan 2024 16:36:00 +0900
Subject: [PATCH 6/6] Add split split test for splitLevel = 2
---
test/integration/tree_concurrency_test.go | 29 +++++++++++++----------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/test/integration/tree_concurrency_test.go b/test/integration/tree_concurrency_test.go
index 9a921a009..09c0a55b5 100644
--- a/test/integration/tree_concurrency_test.go
+++ b/test/integration/tree_concurrency_test.go
@@ -322,36 +322,37 @@ func TestTreeConcurrencyEditEdit(t *testing.T) {
RunTestTreeConcurrency("concurrently-edit-edit-test", t, initialState, initialXML, ranges, editOperations1, editOperations2)
}
-// TODO(justiceHui): add split test for splitLevel > 1
func TestTreeConcurrencySplitSplit(t *testing.T) {
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- //
a b c d
e f g h
i j k l
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ //
a b c d
e f g h
i j k l
initialState := json.TreeNode{
Type: "root",
Children: []json.TreeNode{
{Type: "p", Children: []json.TreeNode{
{Type: "p", Children: []json.TreeNode{
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "abcd"}}},
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "efgh"}}},
+ {Type: "p", Children: []json.TreeNode{
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "abcd"}}},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "efgh"}}},
+ }},
+ {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ijkl"}}},
}},
- {Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ijkl"}}},
}},
},
}
- initialXML := `abcd
efgh
ijkl
`
+ initialXML := `abcd
efgh
ijkl
`
ranges := []twoRangesType{
// equal-single-element: abcd
- makeTwoRanges(2, 5, 8, 2, 5, 8, `equal-single`),
+ makeTwoRanges(3, 6, 9, 3, 6, 9, `equal-single`),
// equal-multiple-element: abcd
efgh
- makeTwoRanges(2, 8, 14, 2, 8, 14, `equal-multiple`),
+ makeTwoRanges(3, 9, 15, 3, 9, 15, `equal-multiple`),
// A contains B same level: abcd
efgh
- efgh
- makeTwoRanges(2, 8, 14, 8, 11, 14, `A contains B same level`),
+ makeTwoRanges(3, 9, 15, 9, 12, 15, `A contains B same level`),
// A contains B multiple level: abcd
efgh
ijkl
- efgh
- makeTwoRanges(1, 15, 21, 8, 11, 14, `A contains B multiple level`),
+ makeTwoRanges(2, 16, 22, 9, 12, 15, `A contains B multiple level`),
// side by side
- makeTwoRanges(2, 5, 8, 8, 11, 14, `B is next to A`),
+ makeTwoRanges(3, 6, 9, 9, 12, 15, `B is next to A`),
}
splitOperations := []operationInterface{
@@ -359,6 +360,10 @@ func TestTreeConcurrencySplitSplit(t *testing.T) {
editOperationType{RangeOneQuarter, SplitUpdate, nil, 1, `split-one-quarter-1`},
editOperationType{RangeThreeQuarter, SplitUpdate, nil, 1, `split-three-quarter-1`},
editOperationType{RangeBack, SplitUpdate, nil, 1, `split-back-1`},
+ editOperationType{RangeFront, SplitUpdate, nil, 2, `split-front-2`},
+ editOperationType{RangeOneQuarter, SplitUpdate, nil, 2, `split-one-quarter-2`},
+ editOperationType{RangeThreeQuarter, SplitUpdate, nil, 2, `split-three-quarter-2`},
+ editOperationType{RangeBack, SplitUpdate, nil, 2, `split-back-2`},
}
RunTestTreeConcurrency("concurrently-split-split-test", t, initialState, initialXML, ranges, splitOperations, splitOperations)