@fluidframework/merge-tree 2.31.0 → 2.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/client.d.ts +7 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +153 -44
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/mergeTree.d.ts +17 -5
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +188 -79
- package/dist/mergeTree.js.map +1 -1
- package/dist/mergeTreeNodes.d.ts +16 -18
- package/dist/mergeTreeNodes.d.ts.map +1 -1
- package/dist/mergeTreeNodes.js +6 -0
- package/dist/mergeTreeNodes.js.map +1 -1
- package/dist/perspective.d.ts +9 -0
- package/dist/perspective.d.ts.map +1 -1
- package/dist/perspective.js +14 -1
- package/dist/perspective.js.map +1 -1
- package/dist/segmentInfos.d.ts +32 -4
- package/dist/segmentInfos.d.ts.map +1 -1
- package/dist/segmentInfos.js +3 -1
- package/dist/segmentInfos.js.map +1 -1
- package/dist/sortedSegmentSet.d.ts +1 -0
- package/dist/sortedSegmentSet.d.ts.map +1 -1
- package/dist/sortedSegmentSet.js +3 -0
- package/dist/sortedSegmentSet.js.map +1 -1
- package/dist/test/beastTest.spec.js +5 -5
- package/dist/test/beastTest.spec.js.map +1 -1
- package/dist/test/client.localReference.spec.js +3 -3
- package/dist/test/client.localReference.spec.js.map +1 -1
- package/dist/test/client.rollback.spec.js +17 -0
- package/dist/test/client.rollback.spec.js.map +1 -1
- package/dist/test/clientTestHelper.d.ts +100 -0
- package/dist/test/clientTestHelper.d.ts.map +1 -0
- package/dist/test/clientTestHelper.js +196 -0
- package/dist/test/clientTestHelper.js.map +1 -0
- package/dist/test/mergeTree.annotate.spec.js +12 -12
- package/dist/test/mergeTree.annotate.spec.js.map +1 -1
- package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +1 -1
- package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
- package/dist/test/obliterate.concurrent.spec.js +93 -90
- package/dist/test/obliterate.concurrent.spec.js.map +1 -1
- package/dist/test/obliterate.deltaCallback.spec.js +121 -116
- package/dist/test/obliterate.deltaCallback.spec.js.map +1 -1
- package/dist/test/obliterate.rangeExpansion.spec.js +29 -79
- package/dist/test/obliterate.rangeExpansion.spec.js.map +1 -1
- package/dist/test/obliterate.reconnect.spec.js +235 -58
- package/dist/test/obliterate.reconnect.spec.js.map +1 -1
- package/dist/test/testClient.js +1 -1
- package/dist/test/testClient.js.map +1 -1
- package/dist/test/testUtils.d.ts +13 -0
- package/dist/test/testUtils.d.ts.map +1 -1
- package/dist/test/testUtils.js +22 -1
- package/dist/test/testUtils.js.map +1 -1
- package/lib/client.d.ts +7 -1
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +155 -46
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/mergeTree.d.ts +17 -5
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +192 -83
- package/lib/mergeTree.js.map +1 -1
- package/lib/mergeTreeNodes.d.ts +16 -18
- package/lib/mergeTreeNodes.d.ts.map +1 -1
- package/lib/mergeTreeNodes.js +7 -1
- package/lib/mergeTreeNodes.js.map +1 -1
- package/lib/perspective.d.ts +9 -0
- package/lib/perspective.d.ts.map +1 -1
- package/lib/perspective.js +12 -0
- package/lib/perspective.js.map +1 -1
- package/lib/segmentInfos.d.ts +32 -4
- package/lib/segmentInfos.d.ts.map +1 -1
- package/lib/segmentInfos.js +2 -1
- package/lib/segmentInfos.js.map +1 -1
- package/lib/sortedSegmentSet.d.ts +1 -0
- package/lib/sortedSegmentSet.d.ts.map +1 -1
- package/lib/sortedSegmentSet.js +3 -0
- package/lib/sortedSegmentSet.js.map +1 -1
- package/lib/test/beastTest.spec.js +5 -5
- package/lib/test/beastTest.spec.js.map +1 -1
- package/lib/test/client.localReference.spec.js +3 -3
- package/lib/test/client.localReference.spec.js.map +1 -1
- package/lib/test/client.rollback.spec.js +18 -1
- package/lib/test/client.rollback.spec.js.map +1 -1
- package/lib/test/clientTestHelper.d.ts +100 -0
- package/lib/test/clientTestHelper.d.ts.map +1 -0
- package/lib/test/clientTestHelper.js +192 -0
- package/lib/test/clientTestHelper.js.map +1 -0
- package/lib/test/mergeTree.annotate.spec.js +12 -12
- package/lib/test/mergeTree.annotate.spec.js.map +1 -1
- package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +1 -1
- package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
- package/lib/test/obliterate.concurrent.spec.js +93 -90
- package/lib/test/obliterate.concurrent.spec.js.map +1 -1
- package/lib/test/obliterate.deltaCallback.spec.js +121 -116
- package/lib/test/obliterate.deltaCallback.spec.js.map +1 -1
- package/lib/test/obliterate.rangeExpansion.spec.js +1 -51
- package/lib/test/obliterate.rangeExpansion.spec.js.map +1 -1
- package/lib/test/obliterate.reconnect.spec.js +236 -59
- package/lib/test/obliterate.reconnect.spec.js.map +1 -1
- package/lib/test/testClient.js +1 -1
- package/lib/test/testClient.js.map +1 -1
- package/lib/test/testUtils.d.ts +13 -0
- package/lib/test/testUtils.d.ts.map +1 -1
- package/lib/test/testUtils.js +20 -0
- package/lib/test/testUtils.js.map +1 -1
- package/package.json +19 -18
- package/src/client.ts +286 -55
- package/src/index.ts +1 -1
- package/src/mergeTree.ts +265 -98
- package/src/mergeTreeNodes.ts +24 -18
- package/src/perspective.ts +21 -0
- package/src/segmentInfos.ts +48 -6
- package/src/sortedSegmentSet.ts +4 -0
- package/dist/test/partialSyncHelper.d.ts +0 -42
- package/dist/test/partialSyncHelper.d.ts.map +0 -1
- package/dist/test/partialSyncHelper.js +0 -96
- package/dist/test/partialSyncHelper.js.map +0 -1
- package/dist/test/reconnectHelper.d.ts +0 -50
- package/dist/test/reconnectHelper.d.ts.map +0 -1
- package/dist/test/reconnectHelper.js +0 -106
- package/dist/test/reconnectHelper.js.map +0 -1
- package/lib/test/partialSyncHelper.d.ts +0 -42
- package/lib/test/partialSyncHelper.d.ts.map +0 -1
- package/lib/test/partialSyncHelper.js +0 -92
- package/lib/test/partialSyncHelper.js.map +0 -1
- package/lib/test/reconnectHelper.d.ts +0 -50
- package/lib/test/reconnectHelper.d.ts.map +0 -1
- package/lib/test/reconnectHelper.js +0 -102
- package/lib/test/reconnectHelper.js.map +0 -1
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { strict as assert } from "node:assert";
|
|
6
|
+
import { generatePairwiseOptions } from "@fluid-private/test-pairwise-generator";
|
|
6
7
|
import { LoggingError } from "@fluidframework/telemetry-utils/internal";
|
|
7
8
|
import { MergeTree } from "../mergeTree.js";
|
|
8
9
|
import { Side } from "../sequencePlace.js";
|
|
9
|
-
import {
|
|
10
|
-
import { ReconnectTestHelper } from "./reconnectHelper.js";
|
|
10
|
+
import { ClientTestHelper } from "./clientTestHelper.js";
|
|
11
11
|
import { useStrictPartialLengthChecks } from "./testUtils.js";
|
|
12
12
|
/**
|
|
13
13
|
* Some tests contain ASCII diagrams of the trees to make it easier to reason about
|
|
@@ -38,8 +38,11 @@ import { useStrictPartialLengthChecks } from "./testUtils.js";
|
|
|
38
38
|
* This diagram describes a single segment, `ABC`, that has been concurrently
|
|
39
39
|
* removed by two clients.
|
|
40
40
|
*/
|
|
41
|
-
for (const incremental
|
|
42
|
-
|
|
41
|
+
for (const { incremental, mergeTreeEnableSidedObliterate } of generatePairwiseOptions({
|
|
42
|
+
incremental: [true, false],
|
|
43
|
+
mergeTreeEnableSidedObliterate: [true, false],
|
|
44
|
+
})) {
|
|
45
|
+
describe(`obliterate partial lengths incremental = ${incremental} enableSidedObliterate = ${mergeTreeEnableSidedObliterate}`, () => {
|
|
43
46
|
useStrictPartialLengthChecks();
|
|
44
47
|
beforeEach(() => {
|
|
45
48
|
MergeTree.options.incrementalUpdate = incremental;
|
|
@@ -48,7 +51,7 @@ for (const incremental of [true, false]) {
|
|
|
48
51
|
MergeTree.options.incrementalUpdate = true;
|
|
49
52
|
});
|
|
50
53
|
it("obliterate, then insert at the end of the string", () => {
|
|
51
|
-
const helper = new
|
|
54
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
52
55
|
helper.insertText("A", 0, "01234567");
|
|
53
56
|
helper.processAllOps();
|
|
54
57
|
helper.obliterateRange("A", 0, 8);
|
|
@@ -57,7 +60,7 @@ for (const incremental of [true, false]) {
|
|
|
57
60
|
helper.logger.validate({ baseText: "BBB" });
|
|
58
61
|
});
|
|
59
62
|
it("insert, then obliterate at the end of the string", () => {
|
|
60
|
-
const helper = new
|
|
63
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
61
64
|
helper.insertText("A", 0, "01234567");
|
|
62
65
|
helper.processAllOps();
|
|
63
66
|
helper.insertText("B", 8, "BBB");
|
|
@@ -66,7 +69,7 @@ for (const incremental of [true, false]) {
|
|
|
66
69
|
helper.logger.validate({ baseText: "BBB" });
|
|
67
70
|
});
|
|
68
71
|
it("length of children does not differ from parent when overlapping remove+obliterate", () => {
|
|
69
|
-
const helper = new
|
|
72
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
70
73
|
// ABCDEFGH
|
|
71
74
|
// I-[J]-(KLM-[ABC]-D-123456-E-[FG]-H)
|
|
72
75
|
helper.insertText("A", 0, "ABCDEFGH");
|
|
@@ -82,7 +85,7 @@ for (const incremental of [true, false]) {
|
|
|
82
85
|
helper.logger.validate();
|
|
83
86
|
});
|
|
84
87
|
it("deletes concurrent insert that occurs after obliterate", () => {
|
|
85
|
-
const helper = new
|
|
88
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
86
89
|
helper.insertText("B", 0, "ABCD");
|
|
87
90
|
helper.processAllOps();
|
|
88
91
|
helper.obliterateRange("B", 0, 4);
|
|
@@ -93,7 +96,7 @@ for (const incremental of [true, false]) {
|
|
|
93
96
|
helper.logger.validate();
|
|
94
97
|
});
|
|
95
98
|
it("deletes concurrent insert that occurs before obliterate", () => {
|
|
96
|
-
const helper = new
|
|
99
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
97
100
|
helper.insertText("B", 0, "ABCD");
|
|
98
101
|
helper.processAllOps();
|
|
99
102
|
helper.insertText("C", 2, "X");
|
|
@@ -104,7 +107,7 @@ for (const incremental of [true, false]) {
|
|
|
104
107
|
helper.logger.validate();
|
|
105
108
|
});
|
|
106
109
|
it("does not delete unacked segment at start of string", () => {
|
|
107
|
-
const helper = new
|
|
110
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
108
111
|
helper.insertText("C", 0, "ABC");
|
|
109
112
|
helper.obliterateRange("C", 2, 3);
|
|
110
113
|
helper.insertText("B", 0, "X");
|
|
@@ -115,7 +118,7 @@ for (const incremental of [true, false]) {
|
|
|
115
118
|
helper.logger.validate();
|
|
116
119
|
});
|
|
117
120
|
it("throws when local obliterate has range end outside length of local string", () => {
|
|
118
|
-
const helper = new
|
|
121
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
119
122
|
helper.insertText("B", 0, "A");
|
|
120
123
|
helper.insertText("C", 0, "B");
|
|
121
124
|
try {
|
|
@@ -124,11 +127,11 @@ for (const incremental of [true, false]) {
|
|
|
124
127
|
}
|
|
125
128
|
catch (error) {
|
|
126
129
|
assert(error instanceof LoggingError);
|
|
127
|
-
assert.equal(error.message, "RangeOutOfBounds");
|
|
130
|
+
assert.equal(error.message, mergeTreeEnableSidedObliterate ? "InvalidRange" : "RangeOutOfBounds");
|
|
128
131
|
}
|
|
129
132
|
});
|
|
130
133
|
it("does not delete when obliterate immediately after insert", () => {
|
|
131
|
-
const helper = new
|
|
134
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
132
135
|
helper.insertText("C", 0, "A");
|
|
133
136
|
helper.obliterateRange("C", 0, 1);
|
|
134
137
|
helper.insertText("B", 0, "W");
|
|
@@ -141,7 +144,7 @@ for (const incremental of [true, false]) {
|
|
|
141
144
|
helper.logger.validate();
|
|
142
145
|
});
|
|
143
146
|
it("does not delete remote insert when between local insert+obliterate", () => {
|
|
144
|
-
const helper = new
|
|
147
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
145
148
|
helper.insertText("C", 0, "A");
|
|
146
149
|
helper.insertText("B", 0, "X");
|
|
147
150
|
helper.obliterateRange("C", 0, 1);
|
|
@@ -154,7 +157,7 @@ for (const incremental of [true, false]) {
|
|
|
154
157
|
helper.logger.validate();
|
|
155
158
|
});
|
|
156
159
|
it("does not delete remote insert when between local insert+obliterate", () => {
|
|
157
|
-
const helper = new
|
|
160
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
158
161
|
helper.insertText("C", 0, "A");
|
|
159
162
|
helper.obliterateRange("C", 0, 1);
|
|
160
163
|
helper.insertText("B", 0, "B");
|
|
@@ -167,7 +170,7 @@ for (const incremental of [true, false]) {
|
|
|
167
170
|
helper.logger.validate();
|
|
168
171
|
});
|
|
169
172
|
it("does not delete remote insert when in middle of segment", () => {
|
|
170
|
-
const helper = new
|
|
173
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
171
174
|
helper.insertText("C", 0, "ABC");
|
|
172
175
|
helper.obliterateRange("C", 2, 3);
|
|
173
176
|
helper.obliterateRange("C", 0, 1);
|
|
@@ -179,7 +182,7 @@ for (const incremental of [true, false]) {
|
|
|
179
182
|
helper.logger.validate();
|
|
180
183
|
});
|
|
181
184
|
it("deletes segment inserted into locally obliterated segment", () => {
|
|
182
|
-
const helper = new
|
|
185
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
183
186
|
helper.insertText("C", 0, "A");
|
|
184
187
|
helper.insertText("B", 0, "X");
|
|
185
188
|
helper.insertText("C", 0, "B");
|
|
@@ -191,7 +194,7 @@ for (const incremental of [true, false]) {
|
|
|
191
194
|
helper.logger.validate();
|
|
192
195
|
});
|
|
193
196
|
it("updates lengths after obliterated insertion", () => {
|
|
194
|
-
const helper = new
|
|
197
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
195
198
|
helper.insertText("C", 0, "A");
|
|
196
199
|
helper.insertText("B", 0, "X");
|
|
197
200
|
helper.insertText("C", 0, "N");
|
|
@@ -207,7 +210,7 @@ for (const incremental of [true, false]) {
|
|
|
207
210
|
helper.logger.validate();
|
|
208
211
|
});
|
|
209
212
|
it("updates lengths when insertion causes tree to split", () => {
|
|
210
|
-
const helper = new
|
|
213
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
211
214
|
helper.insertText("A", 0, "0");
|
|
212
215
|
helper.insertText("C", 0, "123");
|
|
213
216
|
helper.insertText("B", 0, "BB");
|
|
@@ -222,7 +225,7 @@ for (const incremental of [true, false]) {
|
|
|
222
225
|
helper.logger.validate();
|
|
223
226
|
});
|
|
224
227
|
it("length of node split by insertion does not count remotely obliterated segments", () => {
|
|
225
|
-
const helper = new
|
|
228
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
226
229
|
helper.insertText("A", 0, "1");
|
|
227
230
|
helper.insertText("A", 0, "2");
|
|
228
231
|
helper.insertText("C", 0, "XXXX");
|
|
@@ -236,7 +239,7 @@ for (const incremental of [true, false]) {
|
|
|
236
239
|
helper.logger.validate();
|
|
237
240
|
});
|
|
238
241
|
it("length of node split by obliterate does not count remotely obliterated segments", () => {
|
|
239
|
-
const helper = new
|
|
242
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
240
243
|
helper.insertText("A", 0, "1");
|
|
241
244
|
helper.insertText("A", 0, "2");
|
|
242
245
|
helper.insertText("C", 0, "XXXX");
|
|
@@ -251,7 +254,7 @@ for (const incremental of [true, false]) {
|
|
|
251
254
|
helper.logger.validate();
|
|
252
255
|
});
|
|
253
256
|
it("counts remotely but not concurrently inserted segments for length when tree is split", () => {
|
|
254
|
-
const helper = new
|
|
257
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
255
258
|
// a-b-c-d-e-123
|
|
256
259
|
// (a-b)-c-d-e-1-[2]-3
|
|
257
260
|
helper.insertText("B", 0, "123");
|
|
@@ -269,7 +272,7 @@ for (const incremental of [true, false]) {
|
|
|
269
272
|
helper.logger.validate();
|
|
270
273
|
});
|
|
271
274
|
it("does obliterate X for all clients", () => {
|
|
272
|
-
const helper = new
|
|
275
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
273
276
|
helper.insertText("B", 0, "DE");
|
|
274
277
|
helper.obliterateRange("B", 0, 1);
|
|
275
278
|
helper.insertText("A", 0, "X");
|
|
@@ -281,7 +284,7 @@ for (const incremental of [true, false]) {
|
|
|
281
284
|
helper.logger.validate();
|
|
282
285
|
});
|
|
283
286
|
it("does not include remote but unacked segments in partial len calculation", () => {
|
|
284
|
-
const helper = new
|
|
287
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
285
288
|
// 89-4567-123-X
|
|
286
289
|
// 8-(9-4-w-567-1)-23-Y-X
|
|
287
290
|
helper.insertText("A", 0, "X");
|
|
@@ -298,7 +301,7 @@ for (const incremental of [true, false]) {
|
|
|
298
301
|
helper.logger.validate();
|
|
299
302
|
});
|
|
300
303
|
it("correctly accounts for overlapping obliterate", () => {
|
|
301
|
-
const helper = new
|
|
304
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
302
305
|
helper.insertText("B", 0, "AB");
|
|
303
306
|
helper.processAllOps();
|
|
304
307
|
helper.obliterateRange("C", 0, 1);
|
|
@@ -310,7 +313,7 @@ for (const incremental of [true, false]) {
|
|
|
310
313
|
helper.logger.validate();
|
|
311
314
|
});
|
|
312
315
|
it("correctly accounts for overlapping obliterate and remove", () => {
|
|
313
|
-
const helper = new
|
|
316
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
314
317
|
helper.insertText("B", 0, "AB");
|
|
315
318
|
helper.processAllOps();
|
|
316
319
|
helper.removeRange("C", 0, 1);
|
|
@@ -322,7 +325,7 @@ for (const incremental of [true, false]) {
|
|
|
322
325
|
helper.logger.validate();
|
|
323
326
|
});
|
|
324
327
|
it("clones removes array during insert", () => {
|
|
325
|
-
const helper = new
|
|
328
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
326
329
|
// the bug found here:
|
|
327
330
|
// the X was skipped over by client `A` because it had already been
|
|
328
331
|
// deleted, so its length at refSeq was 0
|
|
@@ -341,7 +344,7 @@ for (const incremental of [true, false]) {
|
|
|
341
344
|
helper.logger.validate();
|
|
342
345
|
});
|
|
343
346
|
it("client partial lens consider overlapping obliterates", () => {
|
|
344
|
-
const helper = new
|
|
347
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
345
348
|
helper.insertText("A", 0, "123");
|
|
346
349
|
helper.insertText("A", 0, "ABCDEF");
|
|
347
350
|
helper.processAllOps();
|
|
@@ -355,7 +358,7 @@ for (const incremental of [true, false]) {
|
|
|
355
358
|
helper.logger.validate();
|
|
356
359
|
});
|
|
357
360
|
it("client partial lens consider overlapping obliterates", () => {
|
|
358
|
-
const helper = new
|
|
361
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
359
362
|
helper.insertText("C", 0, "X");
|
|
360
363
|
helper.insertText("C", 0, "ABCDEFG");
|
|
361
364
|
helper.processAllOps();
|
|
@@ -368,7 +371,7 @@ for (const incremental of [true, false]) {
|
|
|
368
371
|
helper.logger.validate();
|
|
369
372
|
});
|
|
370
373
|
it("tracks obliterate refSeq when acking op for partial len calculation", () => {
|
|
371
|
-
const helper = new
|
|
374
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
372
375
|
// v-----------------------v
|
|
373
376
|
// v--v
|
|
374
377
|
// v--v
|
|
@@ -386,7 +389,7 @@ for (const incremental of [true, false]) {
|
|
|
386
389
|
helper.logger.validate();
|
|
387
390
|
});
|
|
388
391
|
it("does not have negative len when segment obliterated before insert", () => {
|
|
389
|
-
const helper = new
|
|
392
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
390
393
|
// 1234567-D-C-AB
|
|
391
394
|
// 12-([3-X-45]-67)-D-C-AB
|
|
392
395
|
helper.insertText("A", 0, "AB");
|
|
@@ -405,7 +408,7 @@ for (const incremental of [true, false]) {
|
|
|
405
408
|
helper.logger.validate();
|
|
406
409
|
});
|
|
407
410
|
it("does not have negative len when segment obliterated before insert", () => {
|
|
408
|
-
const helper = new
|
|
411
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
409
412
|
// ABCDE-1-[2]-3
|
|
410
413
|
// (A-XX-B)-(CD)-E-1-3
|
|
411
414
|
helper.insertText("B", 0, "123");
|
|
@@ -423,7 +426,7 @@ for (const incremental of [true, false]) {
|
|
|
423
426
|
helper.logger.validate();
|
|
424
427
|
});
|
|
425
428
|
it("deletes segments between two obliterates with different seq", () => {
|
|
426
|
-
const helper = new
|
|
429
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
427
430
|
// 90-8-1234-(5)-67-D-C-B-A
|
|
428
431
|
// 9-(EFG-[0-8-1234-(5)-67)]-D-C-B-A
|
|
429
432
|
helper.insertText("A", 0, "A");
|
|
@@ -443,7 +446,7 @@ for (const incremental of [true, false]) {
|
|
|
443
446
|
helper.logger.validate();
|
|
444
447
|
});
|
|
445
448
|
it("deletes inserted segment when obliterate of different seq in-between", () => {
|
|
446
|
-
const helper = new
|
|
449
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
447
450
|
helper.insertText("A", 0, "AB");
|
|
448
451
|
helper.insertText("B", 0, "E");
|
|
449
452
|
helper.obliterateRange("A", 0, 1);
|
|
@@ -457,7 +460,7 @@ for (const incremental of [true, false]) {
|
|
|
457
460
|
helper.logger.validate();
|
|
458
461
|
});
|
|
459
462
|
it("deletes inserted segment when obliterate of different seq in-between", () => {
|
|
460
|
-
const helper = new
|
|
463
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
461
464
|
helper.insertText("A", 0, "ABC");
|
|
462
465
|
helper.obliterateRange("A", 1, 2);
|
|
463
466
|
helper.processAllOps();
|
|
@@ -470,7 +473,7 @@ for (const incremental of [true, false]) {
|
|
|
470
473
|
helper.logger.validate();
|
|
471
474
|
});
|
|
472
475
|
it("deletes inserted segment when obliterate of different seq in-between", () => {
|
|
473
|
-
const helper = new
|
|
476
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
474
477
|
helper.insertText("A", 0, "ABC");
|
|
475
478
|
helper.obliterateRange("A", 1, 2);
|
|
476
479
|
helper.processAllOps();
|
|
@@ -483,7 +486,7 @@ for (const incremental of [true, false]) {
|
|
|
483
486
|
helper.logger.validate();
|
|
484
487
|
});
|
|
485
488
|
it("considers obliterated local segments as remotely obliterate", () => {
|
|
486
|
-
const helper = new
|
|
489
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
487
490
|
// G-(H-F-I-C)-J-DE-A-(B)
|
|
488
491
|
// G-J-(H-F-I-CD)-E
|
|
489
492
|
helper.insertText("A", 0, "AB");
|
|
@@ -500,7 +503,7 @@ for (const incremental of [true, false]) {
|
|
|
500
503
|
helper.logger.validate();
|
|
501
504
|
});
|
|
502
505
|
it("traverses hier block in obliterated when len at ref seq is >0 and len at len seq == 0", () => {
|
|
503
|
-
const helper = new
|
|
506
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
504
507
|
helper.insertText("A", 0, "AB");
|
|
505
508
|
helper.insertText("A", 2, "CD");
|
|
506
509
|
helper.removeRange("A", 1, 3);
|
|
@@ -518,7 +521,7 @@ for (const incremental of [true, false]) {
|
|
|
518
521
|
helper.logger.validate();
|
|
519
522
|
});
|
|
520
523
|
it("traverses hier block in obliterate when len at ref seq is >0 and len at len seq == 0", () => {
|
|
521
|
-
const helper = new
|
|
524
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
522
525
|
// [E]-FGH-12-[A]-[B]-CD
|
|
523
526
|
// 3-4-F-[G-(H-1)-2]-CD
|
|
524
527
|
helper.insertText("B", 0, "ABCD");
|
|
@@ -539,7 +542,7 @@ for (const incremental of [true, false]) {
|
|
|
539
542
|
helper.logger.validate();
|
|
540
543
|
});
|
|
541
544
|
it("ignores segments obliterated at insertion time for partial len calculations", () => {
|
|
542
|
-
const helper = new
|
|
545
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
543
546
|
helper.insertText("B", 0, "ABC");
|
|
544
547
|
helper.insertText("A", 0, "DEF");
|
|
545
548
|
helper.removeRange("A", 1, 2);
|
|
@@ -556,7 +559,7 @@ for (const incremental of [true, false]) {
|
|
|
556
559
|
helper.logger.validate();
|
|
557
560
|
});
|
|
558
561
|
it("accounts for overlapping obliterates from same client", () => {
|
|
559
|
-
const helper = new
|
|
562
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
560
563
|
helper.insertText("A", 0, "AB");
|
|
561
564
|
helper.processAllOps();
|
|
562
565
|
helper.logger.validate();
|
|
@@ -570,7 +573,7 @@ for (const incremental of [true, false]) {
|
|
|
570
573
|
helper.logger.validate();
|
|
571
574
|
});
|
|
572
575
|
it("accounts for concurrently obliterated segments from the perspective of the inserting client for partial lengths", () => {
|
|
573
|
-
const helper = new
|
|
576
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
574
577
|
helper.insertText("B", 0, "A");
|
|
575
578
|
helper.insertText("C", 0, "B");
|
|
576
579
|
helper.insertText("C", 0, "C");
|
|
@@ -585,7 +588,7 @@ for (const incremental of [true, false]) {
|
|
|
585
588
|
helper.logger.validate();
|
|
586
589
|
});
|
|
587
590
|
it("traverses segments when there is a local obliterate", () => {
|
|
588
|
-
const helper = new
|
|
591
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
589
592
|
helper.insertText("A", 0, "AB");
|
|
590
593
|
helper.obliterateRange("A", 0, 1);
|
|
591
594
|
helper.insertText("C", 0, "12");
|
|
@@ -598,7 +601,7 @@ for (const incremental of [true, false]) {
|
|
|
598
601
|
helper.logger.validate();
|
|
599
602
|
});
|
|
600
603
|
it("keeps track of all obliterates on a segment", () => {
|
|
601
|
-
const helper = new
|
|
604
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
602
605
|
// B-A
|
|
603
606
|
// (B-C-(A))
|
|
604
607
|
helper.insertText("C", 0, "A");
|
|
@@ -618,7 +621,7 @@ for (const incremental of [true, false]) {
|
|
|
618
621
|
helper.logger.validate();
|
|
619
622
|
});
|
|
620
623
|
it("many overlapping obliterates", () => {
|
|
621
|
-
const helper = new
|
|
624
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
622
625
|
// EF-ABCD
|
|
623
626
|
// (1)-2-((E)-F-A)-B-(C)-D
|
|
624
627
|
helper.insertText("C", 0, "ABCD");
|
|
@@ -635,7 +638,7 @@ for (const incremental of [true, false]) {
|
|
|
635
638
|
helper.logger.validate();
|
|
636
639
|
});
|
|
637
640
|
it("overlapping obliterates at start", () => {
|
|
638
|
-
const helper = new
|
|
641
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
639
642
|
// 12345-B-A
|
|
640
643
|
// ((1-C-2)-3)-4-D-5-B-A
|
|
641
644
|
helper.insertText("C", 0, "A");
|
|
@@ -651,7 +654,7 @@ for (const incremental of [true, false]) {
|
|
|
651
654
|
helper.logger.validate();
|
|
652
655
|
});
|
|
653
656
|
it("partial lengths updated when local insert is acked", () => {
|
|
654
|
-
const helper = new
|
|
657
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
655
658
|
// A-BCDEF
|
|
656
659
|
// (A-B-G-C)-D-I-E-H-F
|
|
657
660
|
helper.insertText("A", 0, "A");
|
|
@@ -670,7 +673,7 @@ for (const incremental of [true, false]) {
|
|
|
670
673
|
helper.logger.validate();
|
|
671
674
|
});
|
|
672
675
|
it("two local obliterates get different seq numbers after ack", () => {
|
|
673
|
-
const helper = new
|
|
676
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
674
677
|
// C-AB
|
|
675
678
|
// (C-A)-D-(B)
|
|
676
679
|
helper.insertText("C", 0, "AB");
|
|
@@ -688,7 +691,7 @@ for (const incremental of [true, false]) {
|
|
|
688
691
|
helper.logger.validate();
|
|
689
692
|
});
|
|
690
693
|
it("acks remote segment obliterated by local op", () => {
|
|
691
|
-
const helper = new
|
|
694
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
692
695
|
// (D-C-A)-B
|
|
693
696
|
// (D-C-A)-B-E
|
|
694
697
|
helper.insertText("B", 0, "AB");
|
|
@@ -706,7 +709,7 @@ for (const incremental of [true, false]) {
|
|
|
706
709
|
helper.logger.validate();
|
|
707
710
|
});
|
|
708
711
|
it("skips segments obliterated before refSeq when traversing for insertion", () => {
|
|
709
|
-
const helper = new
|
|
712
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
710
713
|
// CDE-(A)-B
|
|
711
714
|
// C-(DE-F-(A)-B)
|
|
712
715
|
helper.insertText("A", 0, "AB");
|
|
@@ -726,7 +729,7 @@ for (const incremental of [true, false]) {
|
|
|
726
729
|
helper.logger.validate();
|
|
727
730
|
});
|
|
728
731
|
it("applies correct obliterate when right segment has multiple obliterates", () => {
|
|
729
|
-
const helper = new
|
|
732
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
730
733
|
// AB
|
|
731
734
|
// (A-C-D-(B))
|
|
732
735
|
helper.insertText("B", 0, "AB");
|
|
@@ -745,7 +748,7 @@ for (const incremental of [true, false]) {
|
|
|
745
748
|
helper.logger.validate();
|
|
746
749
|
});
|
|
747
750
|
it("takes the correct remove clientId/stamp when multiple obliterates apply", () => {
|
|
748
|
-
const helper = new
|
|
751
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
749
752
|
// AB
|
|
750
753
|
// (A-C-D-(B))
|
|
751
754
|
helper.insertText("A", 0, "AB");
|
|
@@ -764,7 +767,7 @@ for (const incremental of [true, false]) {
|
|
|
764
767
|
helper.logger.validate();
|
|
765
768
|
});
|
|
766
769
|
it("selects clientId if 0", () => {
|
|
767
|
-
const helper = new
|
|
770
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
768
771
|
// AB
|
|
769
772
|
// (A-D-E-(C)-B)
|
|
770
773
|
helper.insertText("B", 0, "AB");
|
|
@@ -784,7 +787,7 @@ for (const incremental of [true, false]) {
|
|
|
784
787
|
helper.logger.validate();
|
|
785
788
|
});
|
|
786
789
|
it("obliterates unacked segment inside non-leaf-segment", () => {
|
|
787
|
-
const helper = new
|
|
790
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
788
791
|
// FGHIJ-E-12345678-D-C-A-K-B
|
|
789
792
|
// FGHIJ-E-12345-(6-[7-L-8-D]-C)-A-K-B
|
|
790
793
|
helper.insertText("A", 0, "AB");
|
|
@@ -811,7 +814,7 @@ for (const incremental of [true, false]) {
|
|
|
811
814
|
helper.logger.validate();
|
|
812
815
|
});
|
|
813
816
|
it("tracks length at seq of lower remove seq when overlapping", () => {
|
|
814
|
-
const helper = new
|
|
817
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
815
818
|
// H-FG-A-CDE-B
|
|
816
819
|
// (H-F-[G-A)-C-I-D]-E-B
|
|
817
820
|
helper.insertText("C", 0, "AB");
|
|
@@ -834,7 +837,7 @@ for (const incremental of [true, false]) {
|
|
|
834
837
|
helper.logger.validate();
|
|
835
838
|
});
|
|
836
839
|
it("segment obliterated on insert overlaps with local obliterate", () => {
|
|
837
|
-
const helper = new
|
|
840
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
838
841
|
// AB
|
|
839
842
|
// ((A-C)-B)
|
|
840
843
|
helper.insertText("B", 0, "AB");
|
|
@@ -848,7 +851,7 @@ for (const incremental of [true, false]) {
|
|
|
848
851
|
helper.logger.validate();
|
|
849
852
|
});
|
|
850
853
|
it("obliterates entire string when concurrent inserts inside range", () => {
|
|
851
|
-
const helper = new
|
|
854
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
852
855
|
// GT
|
|
853
856
|
// (G-O-S-Y-T)
|
|
854
857
|
helper.insertText("B", 0, "GT");
|
|
@@ -862,7 +865,7 @@ for (const incremental of [true, false]) {
|
|
|
862
865
|
helper.logger.validate();
|
|
863
866
|
});
|
|
864
867
|
it("obliterate ack traverses over non-obliterated remove", () => {
|
|
865
|
-
const helper = new
|
|
868
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
866
869
|
// ABCDEFGH-1
|
|
867
870
|
// ABCDE-(F-[G]-2-H)-1
|
|
868
871
|
// ABCDE-(F-[G]-2-H)-1-3
|
|
@@ -883,7 +886,7 @@ for (const incremental of [true, false]) {
|
|
|
883
886
|
helper.logger.validate();
|
|
884
887
|
});
|
|
885
888
|
it("overlapping remove and obliterate when remove happens last", () => {
|
|
886
|
-
const helper = new
|
|
889
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
887
890
|
// FGH-E-D-BC-A
|
|
888
891
|
// ([F]-G)-H-E-D-B-I-C-A
|
|
889
892
|
helper.insertText("A", 0, "A");
|
|
@@ -904,7 +907,7 @@ for (const incremental of [true, false]) {
|
|
|
904
907
|
helper.logger.validate();
|
|
905
908
|
});
|
|
906
909
|
it("overlapping remove and obliterate when remove happens last _and_ partial length already exists", () => {
|
|
907
|
-
const helper = new
|
|
910
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
908
911
|
// FGH-CDE-B-A
|
|
909
912
|
// [F-(GH)-C]-D-Z-E-B-A
|
|
910
913
|
helper.insertText("B", 0, "A");
|
|
@@ -921,7 +924,7 @@ for (const incremental of [true, false]) {
|
|
|
921
924
|
helper.logger.validate();
|
|
922
925
|
});
|
|
923
926
|
it("overlapping obliterate and remove when obliterate is larger than remove and happened last", () => {
|
|
924
|
-
const helper = new
|
|
927
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
925
928
|
// H-CDEFG-B-A
|
|
926
929
|
// (H-C-[D]-E)-F-Z-G-B-A
|
|
927
930
|
helper.insertText("B", 0, "A");
|
|
@@ -938,7 +941,7 @@ for (const incremental of [true, false]) {
|
|
|
938
941
|
helper.logger.validate();
|
|
939
942
|
});
|
|
940
943
|
it("wasRemovedOnInsert computation remains accurate after leaf node is split", () => {
|
|
941
|
-
const helper = new
|
|
944
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
942
945
|
// CD-B-A
|
|
943
946
|
// I-(C-(G)H-E)-F-D-B-A
|
|
944
947
|
helper.insertText("C", 0, "A");
|
|
@@ -956,7 +959,7 @@ for (const incremental of [true, false]) {
|
|
|
956
959
|
helper.logger.validate();
|
|
957
960
|
});
|
|
958
961
|
it("overlapping obliterates, segment is obliterated on insert and by local client", () => {
|
|
959
|
-
const helper = new
|
|
962
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
960
963
|
// DEFG-BC-A
|
|
961
964
|
// v-----------v
|
|
962
965
|
// v-----v
|
|
@@ -975,7 +978,7 @@ for (const incremental of [true, false]) {
|
|
|
975
978
|
helper.logger.validate();
|
|
976
979
|
});
|
|
977
980
|
it("overlapping obliterates and remove", () => {
|
|
978
|
-
const helper = new
|
|
981
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
979
982
|
// FGHIJKL-BCDE-A
|
|
980
983
|
// (FGHI-[JK-(L-B)-C]-D)-E-M-A
|
|
981
984
|
helper.insertText("C", 0, "A");
|
|
@@ -992,7 +995,7 @@ for (const incremental of [true, false]) {
|
|
|
992
995
|
helper.logger.validate();
|
|
993
996
|
});
|
|
994
997
|
it("does not mark obliterated on insert for non-acked obliterates", () => {
|
|
995
|
-
const helper = new
|
|
998
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
996
999
|
// CDE-B-A
|
|
997
1000
|
// I-((C-F)-G-D)-H-E-B-A
|
|
998
1001
|
helper.insertText("B", 0, "A");
|
|
@@ -1010,7 +1013,7 @@ for (const incremental of [true, false]) {
|
|
|
1010
1013
|
helper.logger.validate();
|
|
1011
1014
|
});
|
|
1012
1015
|
it("partial len isLocal when seq is local but a non-local obliterate affects the segment", () => {
|
|
1013
|
-
const helper = new
|
|
1016
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1014
1017
|
// CDEFG-AB
|
|
1015
1018
|
// C-((D-I-E)-F)-G-A-H-B
|
|
1016
1019
|
helper.insertText("A", 0, "AB");
|
|
@@ -1026,7 +1029,7 @@ for (const incremental of [true, false]) {
|
|
|
1026
1029
|
helper.logger.validate();
|
|
1027
1030
|
});
|
|
1028
1031
|
it("obliterated on insert by overlapping obliterates", () => {
|
|
1029
|
-
const helper = new
|
|
1032
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1030
1033
|
// B-DEFG-C-A
|
|
1031
1034
|
// ((B-D-H-E)-F-I-G-C)-A
|
|
1032
1035
|
helper.insertText("C", 0, "A");
|
|
@@ -1043,7 +1046,7 @@ for (const incremental of [true, false]) {
|
|
|
1043
1046
|
helper.logger.validate();
|
|
1044
1047
|
});
|
|
1045
1048
|
it("overlapping obliterates", () => {
|
|
1046
|
-
const helper = new
|
|
1049
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1047
1050
|
// ABCDEF
|
|
1048
1051
|
// v-------------v
|
|
1049
1052
|
// v-----------v
|
|
@@ -1062,7 +1065,7 @@ for (const incremental of [true, false]) {
|
|
|
1062
1065
|
helper.logger.validate();
|
|
1063
1066
|
});
|
|
1064
1067
|
it("overlapping obliterates", () => {
|
|
1065
|
-
const helper = new
|
|
1068
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1066
1069
|
// CDEF-AB
|
|
1067
1070
|
// v-------------------v
|
|
1068
1071
|
// v---------v
|
|
@@ -1082,7 +1085,7 @@ for (const incremental of [true, false]) {
|
|
|
1082
1085
|
helper.logger.validate();
|
|
1083
1086
|
});
|
|
1084
1087
|
it("overlapping remove and obliterate, local obliterate does not have a remote obliterated len", () => {
|
|
1085
|
-
const helper = new
|
|
1088
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1086
1089
|
// v-v------v-v
|
|
1087
1090
|
// G-(H-[F]-E)-D-[A]-B-I-C
|
|
1088
1091
|
helper.insertText("A", 0, "ABC");
|
|
@@ -1098,7 +1101,7 @@ for (const incremental of [true, false]) {
|
|
|
1098
1101
|
helper.logger.validate();
|
|
1099
1102
|
});
|
|
1100
1103
|
it("triple overlapping obliterate and overlapping remove", () => {
|
|
1101
|
-
const helper = new
|
|
1104
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1102
1105
|
// I-H-BCDEFG-A
|
|
1103
1106
|
// v------------v
|
|
1104
1107
|
// v-------v
|
|
@@ -1123,7 +1126,7 @@ for (const incremental of [true, false]) {
|
|
|
1123
1126
|
helper.logger.validate();
|
|
1124
1127
|
});
|
|
1125
1128
|
it("triple overlapping obliterate with one being local", () => {
|
|
1126
|
-
const helper = new
|
|
1129
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1127
1130
|
// CDEFG-B-A
|
|
1128
1131
|
// v--------v
|
|
1129
1132
|
// v--------v
|
|
@@ -1145,7 +1148,7 @@ for (const incremental of [true, false]) {
|
|
|
1145
1148
|
helper.logger.validate();
|
|
1146
1149
|
});
|
|
1147
1150
|
it("obliterate ack traversal is not stopped by obliterated segment", () => {
|
|
1148
|
-
const helper = new
|
|
1151
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1149
1152
|
// ABCD
|
|
1150
1153
|
// (A-(B)-E-C)-D-F
|
|
1151
1154
|
helper.insertText("B", 0, "ABCD");
|
|
@@ -1163,7 +1166,7 @@ for (const incremental of [true, false]) {
|
|
|
1163
1166
|
helper.logger.validate();
|
|
1164
1167
|
});
|
|
1165
1168
|
it("updates partial lengths for segments when doing obliterate ack traversal", () => {
|
|
1166
|
-
const helper = new
|
|
1169
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1167
1170
|
// O-JKLMN-FGHI-E-CD-AB
|
|
1168
1171
|
// v-v---v-----v
|
|
1169
1172
|
// (P-O-JKLMN-FG-[H]-Q-[I-E-C]-D-A)-B
|
|
@@ -1189,7 +1192,7 @@ for (const incremental of [true, false]) {
|
|
|
1189
1192
|
helper.logger.validate();
|
|
1190
1193
|
});
|
|
1191
1194
|
it("combines remote obliterated length ", () => {
|
|
1192
|
-
const helper = new
|
|
1195
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1193
1196
|
// R-XYZ12-STUVW-LMNOP-DEFGHIJK-A-34567890-Q-BC
|
|
1194
1197
|
// v---------------v------------v------v--------v------------v
|
|
1195
1198
|
// [R-XYZ12-STUVW-L]-abcdefghij-[MNOP-D]-klmnop-[EFGHIJK-A-34]-5-(6-x-7)-890-Q-BC
|
|
@@ -1232,7 +1235,7 @@ for (const incremental of [true, false]) {
|
|
|
1232
1235
|
helper.logger.validate();
|
|
1233
1236
|
});
|
|
1234
1237
|
it("three obliterates on same segment", () => {
|
|
1235
|
-
const helper = new
|
|
1238
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1236
1239
|
// A
|
|
1237
1240
|
// (C-B-D-((A)))
|
|
1238
1241
|
helper.insertText("B", 0, "A");
|
|
@@ -1249,7 +1252,7 @@ for (const incremental of [true, false]) {
|
|
|
1249
1252
|
});
|
|
1250
1253
|
describe("incremental partial length updates", () => {
|
|
1251
1254
|
it("obliterates concurrently inserted segment", () => {
|
|
1252
|
-
const helper = new
|
|
1255
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1253
1256
|
// (C-B-A)
|
|
1254
1257
|
helper.insertText("A", 0, "A");
|
|
1255
1258
|
helper.insertText("B", 0, "B");
|
|
@@ -1260,7 +1263,7 @@ for (const incremental of [true, false]) {
|
|
|
1260
1263
|
helper.logger.validate();
|
|
1261
1264
|
});
|
|
1262
1265
|
it("obliterates 2 concurrently inserted segments", () => {
|
|
1263
|
-
const helper = new
|
|
1266
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1264
1267
|
// (C-B-D-A)
|
|
1265
1268
|
helper.insertText("B", 0, "A");
|
|
1266
1269
|
helper.insertText("A", 0, "B");
|
|
@@ -1272,7 +1275,7 @@ for (const incremental of [true, false]) {
|
|
|
1272
1275
|
helper.logger.validate();
|
|
1273
1276
|
});
|
|
1274
1277
|
it("obliterates 4 concurrently inserted segments", () => {
|
|
1275
|
-
const helper = new
|
|
1278
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1276
1279
|
// I-F-(G-D-H-E-C-A)-B
|
|
1277
1280
|
helper.insertText("B", 0, "AB");
|
|
1278
1281
|
helper.insertText("B", 0, "C");
|
|
@@ -1286,7 +1289,7 @@ for (const incremental of [true, false]) {
|
|
|
1286
1289
|
helper.logger.validate();
|
|
1287
1290
|
});
|
|
1288
1291
|
it("obliterates 3 concurrently inserted segments", () => {
|
|
1289
|
-
const helper = new
|
|
1292
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1290
1293
|
// I-G-(H-D-F-E-B)-C-A
|
|
1291
1294
|
helper.insertText("B", 0, "A");
|
|
1292
1295
|
helper.insertText("B", 0, "BC");
|
|
@@ -1300,7 +1303,7 @@ for (const incremental of [true, false]) {
|
|
|
1300
1303
|
helper.logger.validate();
|
|
1301
1304
|
});
|
|
1302
1305
|
it("overlapping remove + obliterate, remove happened first", () => {
|
|
1303
|
-
const helper = new
|
|
1306
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1304
1307
|
// D-EFG-B-H-C-A
|
|
1305
1308
|
// I-D-([E]-F)-G-B-H-C-A
|
|
1306
1309
|
helper.insertText("A", 0, "A");
|
|
@@ -1317,7 +1320,7 @@ for (const incremental of [true, false]) {
|
|
|
1317
1320
|
helper.logger.validate();
|
|
1318
1321
|
});
|
|
1319
1322
|
it("overlapping remove + obliterate, remove happened last", () => {
|
|
1320
|
-
const helper = new
|
|
1323
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1321
1324
|
// DEFGH-C-B-A
|
|
1322
1325
|
// [D]-[E-(F)-G]-H-C-B-A
|
|
1323
1326
|
helper.insertText("C", 0, "A");
|
|
@@ -1334,7 +1337,7 @@ for (const incremental of [true, false]) {
|
|
|
1334
1337
|
helper.logger.validate();
|
|
1335
1338
|
});
|
|
1336
1339
|
it("segment inside locally obliterated segment group is split", () => {
|
|
1337
|
-
const helper = new
|
|
1340
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1338
1341
|
// CDEF-AB
|
|
1339
1342
|
// [C]-DE-(F-(G)-H-A)-B
|
|
1340
1343
|
// [C]-DE-(F-(G)-H-A)-(B)
|
|
@@ -1354,7 +1357,7 @@ for (const incremental of [true, false]) {
|
|
|
1354
1357
|
helper.logger.validate();
|
|
1355
1358
|
});
|
|
1356
1359
|
it("continues traversal past locally removed segment inserted before first obliterate", () => {
|
|
1357
|
-
const helper = new
|
|
1360
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1358
1361
|
// ABC
|
|
1359
1362
|
// (E-D-(A)-[B]-C)
|
|
1360
1363
|
helper.insertText("A", 0, "ABC");
|
|
@@ -1370,7 +1373,7 @@ for (const incremental of [true, false]) {
|
|
|
1370
1373
|
helper.logger.validate();
|
|
1371
1374
|
});
|
|
1372
1375
|
it("keeps track of remote obliterated length when hier node contains hier nodes", () => {
|
|
1373
|
-
const helper = new
|
|
1376
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1374
1377
|
// LMNO-HIJ-E-K-FG-D-C-AB
|
|
1375
1378
|
// lmnopq-L-[M]-NO-H-ghijk-I-(J-E-K-FG-D-C-A-a)-bc-ef-d-B
|
|
1376
1379
|
// v--------------------------------------v
|
|
@@ -1407,7 +1410,7 @@ for (const incremental of [true, false]) {
|
|
|
1407
1410
|
helper.logger.validate();
|
|
1408
1411
|
});
|
|
1409
1412
|
it("combines remote obliterated length for parent node of tree with depth >=3", () => {
|
|
1410
|
-
const helper = new
|
|
1413
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate });
|
|
1411
1414
|
// VWXYZ0-(K)-[L]-M-[N]-O-EFGHIJ-[A]-B-P-TU-QRS-CD
|
|
1412
1415
|
// v-v------v------------v
|
|
1413
1416
|
// v--------------------v
|
|
@@ -1454,7 +1457,7 @@ for (const incremental of [true, false]) {
|
|
|
1454
1457
|
// Strict partial lengths checks reported an inconsistency when B applies A's
|
|
1455
1458
|
// obliterateRange op for the length of the string at refSeq 4.
|
|
1456
1459
|
// With strict partial lengths disabled, this manifested in 0x4bc on the subsequent op application.
|
|
1457
|
-
const helper = new
|
|
1460
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate: true });
|
|
1458
1461
|
helper.insertText("D", 0, "ABCDEFGH");
|
|
1459
1462
|
helper.processAllOps();
|
|
1460
1463
|
helper.insertText("B", 0, "123456xxxxx7890");
|
|
@@ -1471,7 +1474,7 @@ for (const incremental of [true, false]) {
|
|
|
1471
1474
|
helper.logger.validate({ baseText: "cx7890FGH" });
|
|
1472
1475
|
});
|
|
1473
1476
|
it("Avoids adding entries for insert with subsequent removal", () => {
|
|
1474
|
-
const helper = new
|
|
1477
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate: true });
|
|
1475
1478
|
helper.insertText("D", 0, "bZL4aQd");
|
|
1476
1479
|
helper.processAllOps();
|
|
1477
1480
|
helper.insertText("A", 0, "8mvaLcEa4nwhELu");
|
|
@@ -1498,7 +1501,7 @@ for (const incremental of [true, false]) {
|
|
|
1498
1501
|
// Once fuzz testing more meaninfully leverages ops being sent to different clients at different types (partial
|
|
1499
1502
|
// synchronization), it's probably fine to remove this.
|
|
1500
1503
|
it("fuzz regression: Local obliterate wins post-insertion of segment previously thought to have won", () => {
|
|
1501
|
-
const helper = new
|
|
1504
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate: true });
|
|
1502
1505
|
helper.insertText("A", 0, "Hx15J");
|
|
1503
1506
|
helper.processAllOps();
|
|
1504
1507
|
helper.insertText("A", 0, "9T");
|
|
@@ -1520,7 +1523,7 @@ for (const incremental of [true, false]) {
|
|
|
1520
1523
|
});
|
|
1521
1524
|
// Simpler version of the above test which has the same root cause but reproduces a slightly different failure mode.
|
|
1522
1525
|
it("Local obliterate wins post-insertion of segment previously thought to have won", () => {
|
|
1523
|
-
const helper = new
|
|
1526
|
+
const helper = new ClientTestHelper({ mergeTreeEnableSidedObliterate: true });
|
|
1524
1527
|
helper.insertText("A", 0, "1xx2");
|
|
1525
1528
|
helper.processAllOps();
|
|
1526
1529
|
// A and B both obliterate the 'xx' segment with an expanding obliterate, then try to insert
|