@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.
Files changed (137) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/client.d.ts +7 -1
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +153 -44
  5. package/dist/client.js.map +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +3 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/mergeTree.d.ts +17 -5
  11. package/dist/mergeTree.d.ts.map +1 -1
  12. package/dist/mergeTree.js +188 -79
  13. package/dist/mergeTree.js.map +1 -1
  14. package/dist/mergeTreeNodes.d.ts +16 -18
  15. package/dist/mergeTreeNodes.d.ts.map +1 -1
  16. package/dist/mergeTreeNodes.js +6 -0
  17. package/dist/mergeTreeNodes.js.map +1 -1
  18. package/dist/perspective.d.ts +9 -0
  19. package/dist/perspective.d.ts.map +1 -1
  20. package/dist/perspective.js +14 -1
  21. package/dist/perspective.js.map +1 -1
  22. package/dist/segmentInfos.d.ts +32 -4
  23. package/dist/segmentInfos.d.ts.map +1 -1
  24. package/dist/segmentInfos.js +3 -1
  25. package/dist/segmentInfos.js.map +1 -1
  26. package/dist/sortedSegmentSet.d.ts +1 -0
  27. package/dist/sortedSegmentSet.d.ts.map +1 -1
  28. package/dist/sortedSegmentSet.js +3 -0
  29. package/dist/sortedSegmentSet.js.map +1 -1
  30. package/dist/test/beastTest.spec.js +5 -5
  31. package/dist/test/beastTest.spec.js.map +1 -1
  32. package/dist/test/client.localReference.spec.js +3 -3
  33. package/dist/test/client.localReference.spec.js.map +1 -1
  34. package/dist/test/client.rollback.spec.js +17 -0
  35. package/dist/test/client.rollback.spec.js.map +1 -1
  36. package/dist/test/clientTestHelper.d.ts +100 -0
  37. package/dist/test/clientTestHelper.d.ts.map +1 -0
  38. package/dist/test/clientTestHelper.js +196 -0
  39. package/dist/test/clientTestHelper.js.map +1 -0
  40. package/dist/test/mergeTree.annotate.spec.js +12 -12
  41. package/dist/test/mergeTree.annotate.spec.js.map +1 -1
  42. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +1 -1
  43. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  44. package/dist/test/obliterate.concurrent.spec.js +93 -90
  45. package/dist/test/obliterate.concurrent.spec.js.map +1 -1
  46. package/dist/test/obliterate.deltaCallback.spec.js +121 -116
  47. package/dist/test/obliterate.deltaCallback.spec.js.map +1 -1
  48. package/dist/test/obliterate.rangeExpansion.spec.js +29 -79
  49. package/dist/test/obliterate.rangeExpansion.spec.js.map +1 -1
  50. package/dist/test/obliterate.reconnect.spec.js +235 -58
  51. package/dist/test/obliterate.reconnect.spec.js.map +1 -1
  52. package/dist/test/testClient.js +1 -1
  53. package/dist/test/testClient.js.map +1 -1
  54. package/dist/test/testUtils.d.ts +13 -0
  55. package/dist/test/testUtils.d.ts.map +1 -1
  56. package/dist/test/testUtils.js +22 -1
  57. package/dist/test/testUtils.js.map +1 -1
  58. package/lib/client.d.ts +7 -1
  59. package/lib/client.d.ts.map +1 -1
  60. package/lib/client.js +155 -46
  61. package/lib/client.js.map +1 -1
  62. package/lib/index.d.ts +1 -1
  63. package/lib/index.d.ts.map +1 -1
  64. package/lib/index.js +1 -0
  65. package/lib/index.js.map +1 -1
  66. package/lib/mergeTree.d.ts +17 -5
  67. package/lib/mergeTree.d.ts.map +1 -1
  68. package/lib/mergeTree.js +192 -83
  69. package/lib/mergeTree.js.map +1 -1
  70. package/lib/mergeTreeNodes.d.ts +16 -18
  71. package/lib/mergeTreeNodes.d.ts.map +1 -1
  72. package/lib/mergeTreeNodes.js +7 -1
  73. package/lib/mergeTreeNodes.js.map +1 -1
  74. package/lib/perspective.d.ts +9 -0
  75. package/lib/perspective.d.ts.map +1 -1
  76. package/lib/perspective.js +12 -0
  77. package/lib/perspective.js.map +1 -1
  78. package/lib/segmentInfos.d.ts +32 -4
  79. package/lib/segmentInfos.d.ts.map +1 -1
  80. package/lib/segmentInfos.js +2 -1
  81. package/lib/segmentInfos.js.map +1 -1
  82. package/lib/sortedSegmentSet.d.ts +1 -0
  83. package/lib/sortedSegmentSet.d.ts.map +1 -1
  84. package/lib/sortedSegmentSet.js +3 -0
  85. package/lib/sortedSegmentSet.js.map +1 -1
  86. package/lib/test/beastTest.spec.js +5 -5
  87. package/lib/test/beastTest.spec.js.map +1 -1
  88. package/lib/test/client.localReference.spec.js +3 -3
  89. package/lib/test/client.localReference.spec.js.map +1 -1
  90. package/lib/test/client.rollback.spec.js +18 -1
  91. package/lib/test/client.rollback.spec.js.map +1 -1
  92. package/lib/test/clientTestHelper.d.ts +100 -0
  93. package/lib/test/clientTestHelper.d.ts.map +1 -0
  94. package/lib/test/clientTestHelper.js +192 -0
  95. package/lib/test/clientTestHelper.js.map +1 -0
  96. package/lib/test/mergeTree.annotate.spec.js +12 -12
  97. package/lib/test/mergeTree.annotate.spec.js.map +1 -1
  98. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +1 -1
  99. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  100. package/lib/test/obliterate.concurrent.spec.js +93 -90
  101. package/lib/test/obliterate.concurrent.spec.js.map +1 -1
  102. package/lib/test/obliterate.deltaCallback.spec.js +121 -116
  103. package/lib/test/obliterate.deltaCallback.spec.js.map +1 -1
  104. package/lib/test/obliterate.rangeExpansion.spec.js +1 -51
  105. package/lib/test/obliterate.rangeExpansion.spec.js.map +1 -1
  106. package/lib/test/obliterate.reconnect.spec.js +236 -59
  107. package/lib/test/obliterate.reconnect.spec.js.map +1 -1
  108. package/lib/test/testClient.js +1 -1
  109. package/lib/test/testClient.js.map +1 -1
  110. package/lib/test/testUtils.d.ts +13 -0
  111. package/lib/test/testUtils.d.ts.map +1 -1
  112. package/lib/test/testUtils.js +20 -0
  113. package/lib/test/testUtils.js.map +1 -1
  114. package/package.json +19 -18
  115. package/src/client.ts +286 -55
  116. package/src/index.ts +1 -1
  117. package/src/mergeTree.ts +265 -98
  118. package/src/mergeTreeNodes.ts +24 -18
  119. package/src/perspective.ts +21 -0
  120. package/src/segmentInfos.ts +48 -6
  121. package/src/sortedSegmentSet.ts +4 -0
  122. package/dist/test/partialSyncHelper.d.ts +0 -42
  123. package/dist/test/partialSyncHelper.d.ts.map +0 -1
  124. package/dist/test/partialSyncHelper.js +0 -96
  125. package/dist/test/partialSyncHelper.js.map +0 -1
  126. package/dist/test/reconnectHelper.d.ts +0 -50
  127. package/dist/test/reconnectHelper.d.ts.map +0 -1
  128. package/dist/test/reconnectHelper.js +0 -106
  129. package/dist/test/reconnectHelper.js.map +0 -1
  130. package/lib/test/partialSyncHelper.d.ts +0 -42
  131. package/lib/test/partialSyncHelper.d.ts.map +0 -1
  132. package/lib/test/partialSyncHelper.js +0 -92
  133. package/lib/test/partialSyncHelper.js.map +0 -1
  134. package/lib/test/reconnectHelper.d.ts +0 -50
  135. package/lib/test/reconnectHelper.d.ts.map +0 -1
  136. package/lib/test/reconnectHelper.js +0 -102
  137. 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 { PartialSyncTestHelper } from "./partialSyncHelper.js";
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 of [true, false]) {
42
- describe(`obliterate partial lengths incremental = ${incremental}`, () => {
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 ReconnectTestHelper();
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 PartialSyncTestHelper();
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 PartialSyncTestHelper();
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 PartialSyncTestHelper();
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 PartialSyncTestHelper();
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