@fluidframework/merge-tree 2.20.0 → 2.22.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 (183) hide show
  1. package/.eslintrc.cjs +0 -1
  2. package/CHANGELOG.md +8 -0
  3. package/README.md +1 -0
  4. package/dist/attributionCollection.js +5 -7
  5. package/dist/attributionCollection.js.map +1 -1
  6. package/dist/localReference.js +6 -8
  7. package/dist/localReference.js.map +1 -1
  8. package/dist/mergeTree.d.ts.map +1 -1
  9. package/dist/mergeTree.js +69 -34
  10. package/dist/mergeTree.js.map +1 -1
  11. package/dist/mergeTreeNodes.d.ts +15 -4
  12. package/dist/mergeTreeNodes.d.ts.map +1 -1
  13. package/dist/mergeTreeNodes.js +1 -1
  14. package/dist/mergeTreeNodes.js.map +1 -1
  15. package/dist/partialLengths.d.ts +114 -144
  16. package/dist/partialLengths.d.ts.map +1 -1
  17. package/dist/partialLengths.js +431 -525
  18. package/dist/partialLengths.js.map +1 -1
  19. package/dist/perspective.d.ts +10 -1
  20. package/dist/perspective.d.ts.map +1 -1
  21. package/dist/perspective.js +10 -1
  22. package/dist/perspective.js.map +1 -1
  23. package/dist/properties.d.ts.map +1 -1
  24. package/dist/properties.js +2 -3
  25. package/dist/properties.js.map +1 -1
  26. package/dist/revertibles.js +3 -3
  27. package/dist/revertibles.js.map +1 -1
  28. package/dist/segmentInfos.d.ts +3 -0
  29. package/dist/segmentInfos.d.ts.map +1 -1
  30. package/dist/segmentInfos.js.map +1 -1
  31. package/dist/segmentPropertiesManager.js +3 -3
  32. package/dist/segmentPropertiesManager.js.map +1 -1
  33. package/dist/snapshotLoader.js +2 -2
  34. package/dist/snapshotLoader.js.map +1 -1
  35. package/dist/sortedSegmentSet.d.ts +5 -3
  36. package/dist/sortedSegmentSet.d.ts.map +1 -1
  37. package/dist/sortedSegmentSet.js +33 -41
  38. package/dist/sortedSegmentSet.js.map +1 -1
  39. package/dist/sortedSet.d.ts +20 -3
  40. package/dist/sortedSet.d.ts.map +1 -1
  41. package/dist/sortedSet.js +23 -14
  42. package/dist/sortedSet.js.map +1 -1
  43. package/dist/test/Snapshot.perf.spec.js +1 -1
  44. package/dist/test/Snapshot.perf.spec.js.map +1 -1
  45. package/dist/test/client.applyMsg.spec.js +20 -0
  46. package/dist/test/client.applyMsg.spec.js.map +1 -1
  47. package/dist/test/client.applyStashedOpFarm.spec.js +1 -1
  48. package/dist/test/client.applyStashedOpFarm.spec.js.map +1 -1
  49. package/dist/test/client.attributionFarm.spec.js +1 -1
  50. package/dist/test/client.attributionFarm.spec.js.map +1 -1
  51. package/dist/test/client.localReference.spec.js +48 -0
  52. package/dist/test/client.localReference.spec.js.map +1 -1
  53. package/dist/test/client.obliterateFarm.spec.d.ts +12 -0
  54. package/dist/test/client.obliterateFarm.spec.d.ts.map +1 -0
  55. package/dist/test/client.obliterateFarm.spec.js +89 -0
  56. package/dist/test/client.obliterateFarm.spec.js.map +1 -0
  57. package/dist/test/client.reconnectFarm.spec.js +1 -1
  58. package/dist/test/client.reconnectFarm.spec.js.map +1 -1
  59. package/dist/test/client.searchForMarker.spec.js +2 -2
  60. package/dist/test/client.searchForMarker.spec.js.map +1 -1
  61. package/dist/test/mergeTreeOperationRunner.d.ts +7 -2
  62. package/dist/test/mergeTreeOperationRunner.d.ts.map +1 -1
  63. package/dist/test/mergeTreeOperationRunner.js +31 -14
  64. package/dist/test/mergeTreeOperationRunner.js.map +1 -1
  65. package/dist/test/obliterate.concurrent.spec.js +45 -1
  66. package/dist/test/obliterate.concurrent.spec.js.map +1 -1
  67. package/dist/test/obliterate.rangeExpansion.spec.js +81 -5
  68. package/dist/test/obliterate.rangeExpansion.spec.js.map +1 -1
  69. package/dist/test/obliterate.spec.js +3 -3
  70. package/dist/test/obliterate.spec.js.map +1 -1
  71. package/dist/test/obliterateOperations.d.ts +15 -0
  72. package/dist/test/obliterateOperations.d.ts.map +1 -0
  73. package/dist/test/obliterateOperations.js +132 -0
  74. package/dist/test/obliterateOperations.js.map +1 -0
  75. package/dist/test/partialSyncHelper.d.ts +42 -0
  76. package/dist/test/partialSyncHelper.d.ts.map +1 -0
  77. package/dist/test/partialSyncHelper.js +96 -0
  78. package/dist/test/partialSyncHelper.js.map +1 -0
  79. package/dist/test/revertibles.spec.js +3 -3
  80. package/dist/test/revertibles.spec.js.map +1 -1
  81. package/dist/test/sortedSegmentSet.spec.js +21 -0
  82. package/dist/test/sortedSegmentSet.spec.js.map +1 -1
  83. package/dist/test/testClient.d.ts +1 -1
  84. package/dist/test/testClient.d.ts.map +1 -1
  85. package/dist/test/testClient.js +1 -0
  86. package/dist/test/testClient.js.map +1 -1
  87. package/dist/test/testUtils.js +2 -2
  88. package/dist/test/testUtils.js.map +1 -1
  89. package/lib/attributionCollection.js +5 -7
  90. package/lib/attributionCollection.js.map +1 -1
  91. package/lib/localReference.js +6 -8
  92. package/lib/localReference.js.map +1 -1
  93. package/lib/mergeTree.d.ts.map +1 -1
  94. package/lib/mergeTree.js +69 -34
  95. package/lib/mergeTree.js.map +1 -1
  96. package/lib/mergeTreeNodes.d.ts +15 -4
  97. package/lib/mergeTreeNodes.d.ts.map +1 -1
  98. package/lib/mergeTreeNodes.js +1 -1
  99. package/lib/mergeTreeNodes.js.map +1 -1
  100. package/lib/partialLengths.d.ts +114 -144
  101. package/lib/partialLengths.d.ts.map +1 -1
  102. package/lib/partialLengths.js +432 -525
  103. package/lib/partialLengths.js.map +1 -1
  104. package/lib/perspective.d.ts +10 -1
  105. package/lib/perspective.d.ts.map +1 -1
  106. package/lib/perspective.js +10 -1
  107. package/lib/perspective.js.map +1 -1
  108. package/lib/properties.d.ts.map +1 -1
  109. package/lib/properties.js +2 -3
  110. package/lib/properties.js.map +1 -1
  111. package/lib/revertibles.js +3 -3
  112. package/lib/revertibles.js.map +1 -1
  113. package/lib/segmentInfos.d.ts +3 -0
  114. package/lib/segmentInfos.d.ts.map +1 -1
  115. package/lib/segmentInfos.js.map +1 -1
  116. package/lib/segmentPropertiesManager.js +3 -3
  117. package/lib/segmentPropertiesManager.js.map +1 -1
  118. package/lib/snapshotLoader.js +2 -2
  119. package/lib/snapshotLoader.js.map +1 -1
  120. package/lib/sortedSegmentSet.d.ts +5 -3
  121. package/lib/sortedSegmentSet.d.ts.map +1 -1
  122. package/lib/sortedSegmentSet.js +33 -41
  123. package/lib/sortedSegmentSet.js.map +1 -1
  124. package/lib/sortedSet.d.ts +20 -3
  125. package/lib/sortedSet.d.ts.map +1 -1
  126. package/lib/sortedSet.js +23 -14
  127. package/lib/sortedSet.js.map +1 -1
  128. package/lib/test/Snapshot.perf.spec.js +1 -1
  129. package/lib/test/Snapshot.perf.spec.js.map +1 -1
  130. package/lib/test/client.applyMsg.spec.js +20 -0
  131. package/lib/test/client.applyMsg.spec.js.map +1 -1
  132. package/lib/test/client.applyStashedOpFarm.spec.js +1 -1
  133. package/lib/test/client.applyStashedOpFarm.spec.js.map +1 -1
  134. package/lib/test/client.attributionFarm.spec.js +1 -1
  135. package/lib/test/client.attributionFarm.spec.js.map +1 -1
  136. package/lib/test/client.localReference.spec.js +48 -0
  137. package/lib/test/client.localReference.spec.js.map +1 -1
  138. package/lib/test/client.obliterateFarm.spec.d.ts +12 -0
  139. package/lib/test/client.obliterateFarm.spec.d.ts.map +1 -0
  140. package/lib/test/client.obliterateFarm.spec.js +88 -0
  141. package/lib/test/client.obliterateFarm.spec.js.map +1 -0
  142. package/lib/test/client.reconnectFarm.spec.js +1 -1
  143. package/lib/test/client.reconnectFarm.spec.js.map +1 -1
  144. package/lib/test/client.searchForMarker.spec.js +2 -2
  145. package/lib/test/client.searchForMarker.spec.js.map +1 -1
  146. package/lib/test/mergeTreeOperationRunner.d.ts +7 -2
  147. package/lib/test/mergeTreeOperationRunner.d.ts.map +1 -1
  148. package/lib/test/mergeTreeOperationRunner.js +31 -14
  149. package/lib/test/mergeTreeOperationRunner.js.map +1 -1
  150. package/lib/test/obliterate.concurrent.spec.js +45 -1
  151. package/lib/test/obliterate.concurrent.spec.js.map +1 -1
  152. package/lib/test/obliterate.rangeExpansion.spec.js +81 -5
  153. package/lib/test/obliterate.rangeExpansion.spec.js.map +1 -1
  154. package/lib/test/obliterate.spec.js +3 -3
  155. package/lib/test/obliterate.spec.js.map +1 -1
  156. package/lib/test/obliterateOperations.d.ts +15 -0
  157. package/lib/test/obliterateOperations.d.ts.map +1 -0
  158. package/lib/test/obliterateOperations.js +123 -0
  159. package/lib/test/obliterateOperations.js.map +1 -0
  160. package/lib/test/partialSyncHelper.d.ts +42 -0
  161. package/lib/test/partialSyncHelper.d.ts.map +1 -0
  162. package/lib/test/partialSyncHelper.js +92 -0
  163. package/lib/test/partialSyncHelper.js.map +1 -0
  164. package/lib/test/revertibles.spec.js +3 -3
  165. package/lib/test/revertibles.spec.js.map +1 -1
  166. package/lib/test/sortedSegmentSet.spec.js +21 -0
  167. package/lib/test/sortedSegmentSet.spec.js.map +1 -1
  168. package/lib/test/testClient.d.ts +1 -1
  169. package/lib/test/testClient.d.ts.map +1 -1
  170. package/lib/test/testClient.js +1 -0
  171. package/lib/test/testClient.js.map +1 -1
  172. package/lib/test/testUtils.js +2 -2
  173. package/lib/test/testUtils.js.map +1 -1
  174. package/package.json +21 -79
  175. package/src/mergeTree.ts +80 -28
  176. package/src/mergeTreeNodes.ts +15 -4
  177. package/src/partialLengths.ts +559 -776
  178. package/src/perspective.ts +10 -1
  179. package/src/properties.ts +2 -3
  180. package/src/segmentInfos.ts +3 -0
  181. package/src/snapshotLoader.ts +1 -1
  182. package/src/sortedSegmentSet.ts +41 -50
  183. package/src/sortedSet.ts +32 -16
@@ -5,8 +5,8 @@
5
5
  import { strict as assert } from "node:assert";
6
6
  import { Side } from "../sequencePlace.js";
7
7
  import { ReconnectTestHelper } from "./reconnectHelper.js";
8
- function itCorrectlyObliterates({ title, action, expectedText, }) {
9
- return it(title, () => {
8
+ function createObliterateTestBody({ action, expectedText }) {
9
+ return () => {
10
10
  const events = [];
11
11
  const helper = new ReconnectTestHelper({
12
12
  mergeTreeEnableSidedObliterate: true,
@@ -17,12 +17,16 @@ function itCorrectlyObliterates({ title, action, expectedText, }) {
17
17
  action(helper);
18
18
  helper.processAllOps();
19
19
  helper.logger.validate({ baseText: expectedText });
20
- });
20
+ };
21
+ }
22
+ function itCorrectlyObliterates(args) {
23
+ return it(args.title, createObliterateTestBody(args));
21
24
  }
22
- itCorrectlyObliterates.skip = ({ title, }) => it.skip(title, () => { });
25
+ itCorrectlyObliterates.skip = (args) => it.skip(args.title, createObliterateTestBody(args));
26
+ itCorrectlyObliterates.only = (args) => it.only(args.title, createObliterateTestBody(args));
23
27
  describe("obliterate", () => {
24
28
  itCorrectlyObliterates({
25
- title: "obliterate adjacent insert",
29
+ title: "Obliterate adjacent insert",
26
30
  action: (helper) => {
27
31
  helper.insertText("A", 0, "|ABC>");
28
32
  helper.processAllOps();
@@ -35,6 +39,23 @@ describe("obliterate", () => {
35
39
  },
36
40
  expectedText: "|BBB>",
37
41
  });
42
+ itCorrectlyObliterates({
43
+ title: "Obliterate adjacent insert followed by obliterate",
44
+ action: (helper) => {
45
+ helper.insertText("A", 0, "0xx12345678");
46
+ helper.processAllOps();
47
+ helper.obliterateRange("A", { pos: 0, side: Side.After }, { pos: 2, side: Side.After });
48
+ helper.obliterateRange("B", { pos: 0, side: Side.After }, { pos: 2, side: Side.After });
49
+ // B won the obliterate, so this segment should be obliterated on insertion
50
+ helper.insertText("A", 1, "AAAAAAAAAA");
51
+ // Nonetheless, all clients should recognize that subsequent ops from A won't have realized this (until A's refSeq advances beyond
52
+ // acking B's obliterate). At one point this caused 0xa3f because other clients didn't realize that the positions here still assume
53
+ // existence of the 'AAAAAAAAAA' segment.
54
+ helper.obliterateRange("A", { pos: 6, side: Side.After }, { pos: 15, side: Side.After });
55
+ helper.processAllOps();
56
+ },
57
+ expectedText: "0678",
58
+ });
38
59
  itCorrectlyObliterates({
39
60
  title: "does not obliterate non-adjacent insert",
40
61
  action: (helper) => {
@@ -46,6 +67,46 @@ describe("obliterate", () => {
46
67
  },
47
68
  expectedText: "XYZhe world",
48
69
  });
70
+ describe("removes prior insert from same client", () => {
71
+ itCorrectlyObliterates({
72
+ title: "when the insert is unacked",
73
+ action: (helper) => {
74
+ helper.insertText("A", 0, "ABC");
75
+ helper.obliterateRange("A", { pos: 0, side: Side.After }, { pos: 2, side: Side.Before });
76
+ },
77
+ expectedText: "AC",
78
+ });
79
+ itCorrectlyObliterates({
80
+ title: "when the insert is acked",
81
+ action: (helper) => {
82
+ helper.insertText("A", 0, "ABC");
83
+ helper.processAllOps();
84
+ helper.obliterateRange("A", { pos: 0, side: Side.After }, { pos: 2, side: Side.Before });
85
+ },
86
+ expectedText: "AC",
87
+ });
88
+ });
89
+ describe("does not remove subsequent insert from the same client", () => {
90
+ itCorrectlyObliterates({
91
+ title: "when the obliterate is unacked",
92
+ action: (helper) => {
93
+ helper.insertText("A", 0, "ABC");
94
+ helper.obliterateRange("A", { pos: 0, side: Side.After }, { pos: 2, side: Side.Before });
95
+ helper.insertText("A", 1, "D");
96
+ },
97
+ expectedText: "ADC",
98
+ });
99
+ itCorrectlyObliterates({
100
+ title: "when the obliterate is unacked",
101
+ action: (helper) => {
102
+ helper.insertText("A", 0, "ABC");
103
+ helper.obliterateRange("A", { pos: 0, side: Side.After }, { pos: 2, side: Side.Before });
104
+ helper.processAllOps();
105
+ helper.insertText("A", 1, "D");
106
+ },
107
+ expectedText: "ADC",
108
+ });
109
+ });
49
110
  itCorrectlyObliterates({
50
111
  title: "obliterate, then insert at the end of the string",
51
112
  action: (helper) => {
@@ -193,6 +254,21 @@ describe("overlapping edits", () => {
193
254
  },
194
255
  expectedText: "heorld",
195
256
  });
257
+ // This test is somewhat arbitrary: it's a minimized fuzz test failure that ended up root-causing to an issue
258
+ // in SortedSegmentSet (local references were not compared correctly when put at various offsets). We also have
259
+ // more direct unit tests for that, but this is a good sanity check and adds some extra verification for concurrent obliterates.
260
+ itCorrectlyObliterates({
261
+ title: "overlapping obliterates with third client inserting",
262
+ action: (helper) => {
263
+ helper.insertText("A", 0, "0123456789");
264
+ helper.processAllOps();
265
+ helper.obliterateRange("A", { pos: 7, side: Side.After }, { pos: 8, side: Side.After });
266
+ helper.obliterateRange("C", { pos: 1, side: Side.Before }, { pos: 8, side: Side.After });
267
+ helper.insertText("B", 5, "V");
268
+ helper.processAllOps();
269
+ },
270
+ expectedText: "09",
271
+ });
196
272
  });
197
273
  describe.skip("reconnect", () => {
198
274
  itCorrectlyObliterates({
@@ -1 +1 @@
1
- {"version":3,"file":"obliterate.rangeExpansion.spec.js","sourceRoot":"","sources":["../../src/test/obliterate.rangeExpansion.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { Side } from \"../sequencePlace.js\";\n\nimport { ReconnectTestHelper } from \"./reconnectHelper.js\";\n\nfunction itCorrectlyObliterates({\n\ttitle,\n\taction,\n\texpectedText,\n}: {\n\ttitle: string;\n\taction: (helper: ReconnectTestHelper) => void;\n\texpectedText: string;\n}): Mocha.Test {\n\treturn it(title, () => {\n\t\tconst events: number[] = [];\n\n\t\tconst helper = new ReconnectTestHelper({\n\t\t\tmergeTreeEnableSidedObliterate: true,\n\t\t});\n\t\thelper.clients.A.on(\"delta\", (opArgs, deltaArgs) => {\n\t\t\tevents.push(deltaArgs.operation);\n\t\t});\n\t\taction(helper);\n\t\thelper.processAllOps();\n\n\t\thelper.logger.validate({ baseText: expectedText });\n\t});\n}\nitCorrectlyObliterates.skip = ({\n\ttitle,\n}: {\n\ttitle: string;\n\taction: (helper: ReconnectTestHelper) => void;\n\texpectedText: string;\n}) => it.skip(title, () => {});\n\ndescribe(\"obliterate\", () => {\n\titCorrectlyObliterates({\n\t\ttitle: \"obliterate adjacent insert\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"|ABC>\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 0, side: Side.After }, { pos: 4, side: Side.Before });\n\t\t\t// not concurrent to A's obliterate - ops on the same client are never concurrent to one another\n\t\t\t// because they are all sequenced locally\n\t\t\thelper.insertText(\"A\", 1, \"AAA\");\n\t\t\thelper.obliterateRange(\"B\", { pos: 0, side: Side.After }, { pos: 4, side: Side.Before });\n\t\t\thelper.insertText(\"B\", 1, \"BBB\");\n\t\t},\n\t\texpectedText: \"|BBB>\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"does not obliterate non-adjacent insert\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t\t// do not obliterate the XYZ - outside the obliterated range without expansion\n\t\t\thelper.insertText(\"B\", 0, \"XYZ\");\n\t\t},\n\t\texpectedText: \"XYZhe world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"obliterate, then insert at the end of the string\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"A\",\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t\t{ pos: 10, side: Side.After },\n\t\t\t);\n\t\t\thelper.insertText(\"B\", 10, \"123\");\n\t\t},\n\t\texpectedText: \"hello\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"insert, then obliterate at the end of the string\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\thelper.insertText(\"A\", 10, \"123\");\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t\t{ pos: 10, side: Side.After },\n\t\t\t);\n\t\t},\n\t\texpectedText: \"hello\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"obliterate, then insert at the end of the string\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"A\",\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t\t{ pos: 10, side: Side.After },\n\t\t\t);\n\t\t\thelper.insertText(\"B\", 10, \"123\");\n\t\t},\n\t\texpectedText: \"hello\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"insert, then obliterate at the end of the string\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\thelper.insertText(\"A\", 10, \"123\");\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t\t{ pos: 10, side: Side.After },\n\t\t\t);\n\t\t},\n\t\texpectedText: \"hello\",\n\t});\n\tdescribe(\"zero length\", () => {\n\t\t// TODO: #17785: Allow start and end to be used as obliteration range endpoints.\n\t\titCorrectlyObliterates.skip({\n\t\t\ttitle: \"zero length obliterate at the start of the string\",\n\t\t\taction: (helper) => {\n\t\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\t\thelper.processAllOps();\n\n\t\t\t\thelper.obliterateRange(\n\t\t\t\t\t\"A\",\n\t\t\t\t\t{ pos: -1, side: Side.After },\n\t\t\t\t\t{ pos: 0, side: Side.Before },\n\t\t\t\t);\n\t\t\t\thelper.insertText(\"B\", 0, \"more \");\n\t\t\t},\n\t\t\texpectedText: \"hello world\",\n\t\t});\n\t\titCorrectlyObliterates({\n\t\t\ttitle: \"zero length obliterate in the middle of the string\",\n\t\t\taction: (helper) => {\n\t\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\t\thelper.processAllOps();\n\n\t\t\t\thelper.obliterateRange(\n\t\t\t\t\t\"A\",\n\t\t\t\t\t{ pos: 0, side: Side.After },\n\t\t\t\t\t{ pos: 1, side: Side.Before },\n\t\t\t\t);\n\t\t\t\thelper.insertText(\"B\", 1, \"more \");\n\t\t\t},\n\t\t\texpectedText: \"hello world\",\n\t\t});\n\t\t// TODO: #17785: Allow start and end to be used as obliteration range endpoints.\n\t\titCorrectlyObliterates.skip({\n\t\t\ttitle: \"zero length obliterate at the end of the string\",\n\t\t\taction: (helper) => {\n\t\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\t\thelper.processAllOps();\n\n\t\t\t\thelper.obliterateRange(\n\t\t\t\t\t\"A\",\n\t\t\t\t\t{ pos: helper.clients.A.getLength() - 1, side: Side.After },\n\t\t\t\t\t{ pos: -1, side: Side.Before },\n\t\t\t\t);\n\t\t\t\thelper.insertText(\"B\", helper.clients.B.getLength(), \" more\");\n\t\t\t},\n\t\t\texpectedText: \"hello world\",\n\t\t});\n\t});\n});\n\ndescribe(\"overlapping edits\", () => {\n\titCorrectlyObliterates({\n\t\ttitle: \"overlapping obliterate and obliterate\",\n\t\taction: (helper) => {\n\t\t\tconst text = \"abcdef\";\n\n\t\t\thelper.insertText(\"A\", 0, text);\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"A\",\n\t\t\t\t{ pos: 0, side: Side.Before },\n\t\t\t\t{ pos: text.length - 1, side: Side.After },\n\t\t\t);\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 0, side: Side.Before },\n\t\t\t\t{ pos: text.length - 1, side: Side.After },\n\t\t\t);\n\t\t},\n\t\texpectedText: \"\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"adjacent obliterates\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 3, side: Side.After });\n\t\t\thelper.obliterateRange(\"B\", { pos: 4, side: Side.Before }, { pos: 5, side: Side.After });\n\t\t},\n\t\texpectedText: \"heworld\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"remove within obliterated range\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 5, side: Side.After });\n\t\t\thelper.removeRange(\"B\", 3, 4);\n\t\t},\n\t\texpectedText: \"heworld\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"obliterate, then remove adjacent to range start\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 1, side: Side.After }, { pos: 5, side: Side.After });\n\t\t\thelper.removeRange(\"B\", 1, 2);\n\t\t},\n\t\texpectedText: \"hworld\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"obliterate, then remove adjacent to range end\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t\thelper.removeRange(\"B\", 4, 6);\n\t\t},\n\t\texpectedText: \"heworld\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"remove, then obliterate adjacent to range start\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.removeRange(\"A\", 4, 6);\n\t\t\thelper.obliterateRange(\"B\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t},\n\t\texpectedText: \"heworld\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"remove, then obliterate adjacent to range end\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.removeRange(\"A\", 2, 4);\n\t\t\thelper.obliterateRange(\"B\", { pos: 3, side: Side.After }, { pos: 6, side: Side.After });\n\t\t},\n\t\texpectedText: \"heorld\",\n\t});\n});\n\ndescribe.skip(\"reconnect\", () => {\n\titCorrectlyObliterates({\n\t\ttitle: \"add text, disconnect, obliterate, reconnect, insert adjacent to obliterated range\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.disconnect([\"C\"]);\n\t\t\tconst op = helper.obliterateRangeLocal(\n\t\t\t\t\"C\",\n\t\t\t\t{ pos: 1, side: Side.After },\n\t\t\t\t{ pos: 4, side: Side.After },\n\t\t\t);\n\t\t\thelper.reconnect([\"C\"]);\n\t\t\thelper.submitDisconnectedOp(\"C\", op);\n\t\t\thelper.processAllOps();\n\t\t\t// inserting adjacent to the obliterated range start\n\t\t\thelper.insertText(\"A\", 2, \"123\");\n\t\t},\n\t\texpectedText: \"heo world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"add text, disconnect, obliterate, insert adjacent to obliterated range, reconnect\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.disconnect([\"C\"]);\n\t\t\tconst op = helper.obliterateRangeLocal(\n\t\t\t\t\"C\",\n\t\t\t\t{ pos: 1, side: Side.After },\n\t\t\t\t{ pos: 4, side: Side.After },\n\t\t\t);\n\t\t\t// inserting adjacent to the obliterated range start\n\t\t\thelper.insertText(\"A\", 2, \"123\");\n\t\t\thelper.reconnect([\"C\"]);\n\t\t\thelper.submitDisconnectedOp(\"C\", op);\n\t\t},\n\t\texpectedText: \"heo world\",\n\t});\n});\n\ndescribe(\"sided obliterates\", () => {\n\t/**\n\t * All test cases will operate on the same numerical positions, but differ on their sidedness:\n\t * 1. A expand both endpoints, B expand neither endpoint = expand range on both endpoints\n\t * 2. A expand start endpoint, B expand end endpoint = either FWW/LWW\n\t * 3. A expand both endpoints, B expand start = expand range on both endpoints\n\t * 4. (similar to 3) A expand both endpoints, B expand end = expand range on both endpoints\n\t * 5. A expand neither endpoint, B expand start = expand start endpoint\n\t * 6. A expand neither endpoint, B expand end = expand end endpoint\n\t * before = 0, after = 1\n\t */\n\titCorrectlyObliterates({\n\t\ttitle: \"1. A expand both endpoints, B expand neither endpoint\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\t// in order to get the right behavior, the range needs to start after the previous position\n\t\t\t// if so, for a range ( 2, 4 ) itCorrectlyObliterates would need to be after 1 and before 5\n\t\t\t// h e( l l o )_ w o r l d\n\t\t\thelper.obliterateRange(\"A\", { pos: 1, side: Side.After }, { pos: 5, side: Side.Before });\n\t\t\t// [2, 4]: before 2, after 4 => h e [l l o] _ w o r l d\n\t\t\thelper.obliterateRange(\"B\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t\thelper.insertText(\"C\", 2, \"123\");\n\t\t\thelper.insertText(\"C\", 8, \"456\");\n\t\t},\n\t\texpectedText: \"he world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"2. A expand start endpoint, B expand end endpoint\",\n\t\taction: (helper) => {\n\t\t\t// currently this is the example from obliterate notation loop doc\n\t\t\t// TODO: translate this into same format as others\n\t\t\t// i think this gets difficult when the range to obliterate > 1 character\n\t\t\thelper.insertText(\"A\", 0, \"ABC\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.insertText(\"A\", 2, \"D\");\n\t\t\t// ( 1]: after 0, after 1 => A( B] D C\n\t\t\thelper.obliterateRange(\"A\", { pos: 0, side: Side.After }, { pos: 1, side: Side.After });\n\t\t\t// included in the range -- should get obliterated\n\t\t\thelper.insertText(\"B\", 1, \"E\");\n\t\t\t// [1 ): before 1, before 2 => A E [B )C\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 1, side: Side.Before },\n\t\t\t\t{ pos: 3, side: Side.Before },\n\t\t\t);\n\t\t},\n\t\texpectedText: \"AC\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"3. A expand both endpoints, B expand start\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\t// ( 2, 4 ): after 1, before 5 => h e( l l o )_ w o r l d\n\t\t\thelper.obliterateRange(\"A\", { pos: 1, side: Side.After }, { pos: 5, side: Side.Before });\n\t\t\t// ( 2, 4]: after 1, after 4 => h e( l l o] _ w o r l d\n\t\t\thelper.obliterateRange(\"B\", { pos: 2, side: Side.After }, { pos: 4, side: Side.Before });\n\t\t\thelper.insertText(\"C\", 2, \"123\");\n\t\t\t// for this to be interesting, might want to insert at 5\n\t\t\thelper.insertText(\"C\", 4, \"456\");\n\t\t},\n\t\texpectedText: \"he world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"4. A expand both endpoints, B expand end\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\t// ( 2, 4 ): after 1, before 5 => h e( l l o )_ w o r l d\n\t\t\thelper.obliterateRange(\"A\", { pos: 1, side: Side.After }, { pos: 5, side: Side.Before });\n\t\t\t// [2, 4 ): before 2, before 5 => h e [l l o )_ w o r l d\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 2, side: Side.Before },\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t);\n\t\t\thelper.insertText(\"C\", 2, \"123\"); // he123llo world\n\t\t\t// for this to be interesting, might want to insert at 5\n\t\t\thelper.insertText(\"C\", 8, \"456\"); // he123llo456 world\n\t\t},\n\t\texpectedText: \"he world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"5. A expand neither endpoint, B expand start\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\t// [2, 4]: before 2, after 4 => h e [l l o] _ w o r l d\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t\t// ( 2, 4]: after 1, after 4 => h e( l l o] _ w o r l d\n\t\t\thelper.obliterateRange(\"B\", { pos: 1, side: Side.After }, { pos: 4, side: Side.After });\n\n\t\t\thelper.insertText(\"C\", 2, \"123\"); // h e( 123 l l o] _ w o r l d\n\t\t\thelper.insertText(\"C\", 8, \"456\"); // h e( 123 l l o) 456 _ w o r l d\n\t\t\thelper.processAllOps();\n\n\t\t\tassert.equal(helper.clients.A.getText(), \"he456 world\");\n\t\t\tassert.equal(helper.clients.B.getText(), \"he456 world\");\n\t\t\tassert.equal(helper.clients.C.getText(), \"he456 world\");\n\n\t\t\thelper.logger.validate();\n\t\t},\n\t\texpectedText: \"he456 world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"6. A expand neither endpoint, B expand end\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\t// [2, 4]: before 2, after 4 => h e [l l o] _ w o r l d\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t\t// [2, 4 ): before 2, before 5 => h e [l l o )_ w o r l d\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 2, side: Side.Before },\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t);\n\n\t\t\thelper.insertText(\"C\", 2, \"123\");\n\t\t\thelper.insertText(\"C\", 8, \"456\");\n\n\t\t\thelper.processAllOps();\n\n\t\t\tassert.equal(helper.clients.A.getText(), \"he123 world\");\n\t\t\tassert.equal(helper.clients.B.getText(), \"he123 world\");\n\t\t\tassert.equal(helper.clients.C.getText(), \"he123 world\");\n\n\t\t\thelper.logger.validate();\n\t\t},\n\t\texpectedText: \"he123 world\",\n\t});\n});\n"]}
1
+ {"version":3,"file":"obliterate.rangeExpansion.spec.js","sourceRoot":"","sources":["../../src/test/obliterate.rangeExpansion.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { Side } from \"../sequencePlace.js\";\n\nimport { ReconnectTestHelper } from \"./reconnectHelper.js\";\n\nfunction createObliterateTestBody({ action, expectedText }: ObliterateTestArgs): () => void {\n\treturn () => {\n\t\tconst events: number[] = [];\n\n\t\tconst helper = new ReconnectTestHelper({\n\t\t\tmergeTreeEnableSidedObliterate: true,\n\t\t});\n\t\thelper.clients.A.on(\"delta\", (opArgs, deltaArgs) => {\n\t\t\tevents.push(deltaArgs.operation);\n\t\t});\n\t\taction(helper);\n\t\thelper.processAllOps();\n\n\t\thelper.logger.validate({ baseText: expectedText });\n\t};\n}\n\ninterface ObliterateTestArgs {\n\ttitle: string;\n\taction: (helper: ReconnectTestHelper) => void;\n\texpectedText: string;\n}\n\nfunction itCorrectlyObliterates(args: ObliterateTestArgs): Mocha.Test {\n\treturn it(args.title, createObliterateTestBody(args));\n}\nitCorrectlyObliterates.skip = (args: ObliterateTestArgs) =>\n\tit.skip(args.title, createObliterateTestBody(args));\nitCorrectlyObliterates.only = (args: ObliterateTestArgs) =>\n\tit.only(args.title, createObliterateTestBody(args));\n\ndescribe(\"obliterate\", () => {\n\titCorrectlyObliterates({\n\t\ttitle: \"Obliterate adjacent insert\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"|ABC>\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 0, side: Side.After }, { pos: 4, side: Side.Before });\n\t\t\t// not concurrent to A's obliterate - ops on the same client are never concurrent to one another\n\t\t\t// because they are all sequenced locally\n\t\t\thelper.insertText(\"A\", 1, \"AAA\");\n\t\t\thelper.obliterateRange(\"B\", { pos: 0, side: Side.After }, { pos: 4, side: Side.Before });\n\t\t\thelper.insertText(\"B\", 1, \"BBB\");\n\t\t},\n\t\texpectedText: \"|BBB>\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"Obliterate adjacent insert followed by obliterate\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"0xx12345678\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 0, side: Side.After }, { pos: 2, side: Side.After });\n\t\t\thelper.obliterateRange(\"B\", { pos: 0, side: Side.After }, { pos: 2, side: Side.After });\n\t\t\t// B won the obliterate, so this segment should be obliterated on insertion\n\t\t\thelper.insertText(\"A\", 1, \"AAAAAAAAAA\");\n\t\t\t// Nonetheless, all clients should recognize that subsequent ops from A won't have realized this (until A's refSeq advances beyond\n\t\t\t// acking B's obliterate). At one point this caused 0xa3f because other clients didn't realize that the positions here still assume\n\t\t\t// existence of the 'AAAAAAAAAA' segment.\n\t\t\thelper.obliterateRange(\"A\", { pos: 6, side: Side.After }, { pos: 15, side: Side.After });\n\t\t\thelper.processAllOps();\n\t\t},\n\t\texpectedText: \"0678\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"does not obliterate non-adjacent insert\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t\t// do not obliterate the XYZ - outside the obliterated range without expansion\n\t\t\thelper.insertText(\"B\", 0, \"XYZ\");\n\t\t},\n\t\texpectedText: \"XYZhe world\",\n\t});\n\tdescribe(\"removes prior insert from same client\", () => {\n\t\titCorrectlyObliterates({\n\t\t\ttitle: \"when the insert is unacked\",\n\t\t\taction: (helper) => {\n\t\t\t\thelper.insertText(\"A\", 0, \"ABC\");\n\t\t\t\thelper.obliterateRange(\n\t\t\t\t\t\"A\",\n\t\t\t\t\t{ pos: 0, side: Side.After },\n\t\t\t\t\t{ pos: 2, side: Side.Before },\n\t\t\t\t);\n\t\t\t},\n\t\t\texpectedText: \"AC\",\n\t\t});\n\t\titCorrectlyObliterates({\n\t\t\ttitle: \"when the insert is acked\",\n\t\t\taction: (helper) => {\n\t\t\t\thelper.insertText(\"A\", 0, \"ABC\");\n\t\t\t\thelper.processAllOps();\n\t\t\t\thelper.obliterateRange(\n\t\t\t\t\t\"A\",\n\t\t\t\t\t{ pos: 0, side: Side.After },\n\t\t\t\t\t{ pos: 2, side: Side.Before },\n\t\t\t\t);\n\t\t\t},\n\t\t\texpectedText: \"AC\",\n\t\t});\n\t});\n\n\tdescribe(\"does not remove subsequent insert from the same client\", () => {\n\t\titCorrectlyObliterates({\n\t\t\ttitle: \"when the obliterate is unacked\",\n\t\t\taction: (helper) => {\n\t\t\t\thelper.insertText(\"A\", 0, \"ABC\");\n\t\t\t\thelper.obliterateRange(\n\t\t\t\t\t\"A\",\n\t\t\t\t\t{ pos: 0, side: Side.After },\n\t\t\t\t\t{ pos: 2, side: Side.Before },\n\t\t\t\t);\n\t\t\t\thelper.insertText(\"A\", 1, \"D\");\n\t\t\t},\n\t\t\texpectedText: \"ADC\",\n\t\t});\n\t\titCorrectlyObliterates({\n\t\t\ttitle: \"when the obliterate is unacked\",\n\t\t\taction: (helper) => {\n\t\t\t\thelper.insertText(\"A\", 0, \"ABC\");\n\t\t\t\thelper.obliterateRange(\n\t\t\t\t\t\"A\",\n\t\t\t\t\t{ pos: 0, side: Side.After },\n\t\t\t\t\t{ pos: 2, side: Side.Before },\n\t\t\t\t);\n\t\t\t\thelper.processAllOps();\n\t\t\t\thelper.insertText(\"A\", 1, \"D\");\n\t\t\t},\n\t\t\texpectedText: \"ADC\",\n\t\t});\n\t});\n\n\titCorrectlyObliterates({\n\t\ttitle: \"obliterate, then insert at the end of the string\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"A\",\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t\t{ pos: 10, side: Side.After },\n\t\t\t);\n\t\t\thelper.insertText(\"B\", 10, \"123\");\n\t\t},\n\t\texpectedText: \"hello\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"insert, then obliterate at the end of the string\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\thelper.insertText(\"A\", 10, \"123\");\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t\t{ pos: 10, side: Side.After },\n\t\t\t);\n\t\t},\n\t\texpectedText: \"hello\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"obliterate, then insert at the end of the string\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"A\",\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t\t{ pos: 10, side: Side.After },\n\t\t\t);\n\t\t\thelper.insertText(\"B\", 10, \"123\");\n\t\t},\n\t\texpectedText: \"hello\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"insert, then obliterate at the end of the string\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\thelper.insertText(\"A\", 10, \"123\");\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t\t{ pos: 10, side: Side.After },\n\t\t\t);\n\t\t},\n\t\texpectedText: \"hello\",\n\t});\n\tdescribe(\"zero length\", () => {\n\t\t// TODO: #17785: Allow start and end to be used as obliteration range endpoints.\n\t\titCorrectlyObliterates.skip({\n\t\t\ttitle: \"zero length obliterate at the start of the string\",\n\t\t\taction: (helper) => {\n\t\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\t\thelper.processAllOps();\n\n\t\t\t\thelper.obliterateRange(\n\t\t\t\t\t\"A\",\n\t\t\t\t\t{ pos: -1, side: Side.After },\n\t\t\t\t\t{ pos: 0, side: Side.Before },\n\t\t\t\t);\n\t\t\t\thelper.insertText(\"B\", 0, \"more \");\n\t\t\t},\n\t\t\texpectedText: \"hello world\",\n\t\t});\n\t\titCorrectlyObliterates({\n\t\t\ttitle: \"zero length obliterate in the middle of the string\",\n\t\t\taction: (helper) => {\n\t\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\t\thelper.processAllOps();\n\n\t\t\t\thelper.obliterateRange(\n\t\t\t\t\t\"A\",\n\t\t\t\t\t{ pos: 0, side: Side.After },\n\t\t\t\t\t{ pos: 1, side: Side.Before },\n\t\t\t\t);\n\t\t\t\thelper.insertText(\"B\", 1, \"more \");\n\t\t\t},\n\t\t\texpectedText: \"hello world\",\n\t\t});\n\t\t// TODO: #17785: Allow start and end to be used as obliteration range endpoints.\n\t\titCorrectlyObliterates.skip({\n\t\t\ttitle: \"zero length obliterate at the end of the string\",\n\t\t\taction: (helper) => {\n\t\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\t\thelper.processAllOps();\n\n\t\t\t\thelper.obliterateRange(\n\t\t\t\t\t\"A\",\n\t\t\t\t\t{ pos: helper.clients.A.getLength() - 1, side: Side.After },\n\t\t\t\t\t{ pos: -1, side: Side.Before },\n\t\t\t\t);\n\t\t\t\thelper.insertText(\"B\", helper.clients.B.getLength(), \" more\");\n\t\t\t},\n\t\t\texpectedText: \"hello world\",\n\t\t});\n\t});\n});\n\ndescribe(\"overlapping edits\", () => {\n\titCorrectlyObliterates({\n\t\ttitle: \"overlapping obliterate and obliterate\",\n\t\taction: (helper) => {\n\t\t\tconst text = \"abcdef\";\n\n\t\t\thelper.insertText(\"A\", 0, text);\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"A\",\n\t\t\t\t{ pos: 0, side: Side.Before },\n\t\t\t\t{ pos: text.length - 1, side: Side.After },\n\t\t\t);\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 0, side: Side.Before },\n\t\t\t\t{ pos: text.length - 1, side: Side.After },\n\t\t\t);\n\t\t},\n\t\texpectedText: \"\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"adjacent obliterates\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 3, side: Side.After });\n\t\t\thelper.obliterateRange(\"B\", { pos: 4, side: Side.Before }, { pos: 5, side: Side.After });\n\t\t},\n\t\texpectedText: \"heworld\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"remove within obliterated range\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 5, side: Side.After });\n\t\t\thelper.removeRange(\"B\", 3, 4);\n\t\t},\n\t\texpectedText: \"heworld\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"obliterate, then remove adjacent to range start\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 1, side: Side.After }, { pos: 5, side: Side.After });\n\t\t\thelper.removeRange(\"B\", 1, 2);\n\t\t},\n\t\texpectedText: \"hworld\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"obliterate, then remove adjacent to range end\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t\thelper.removeRange(\"B\", 4, 6);\n\t\t},\n\t\texpectedText: \"heworld\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"remove, then obliterate adjacent to range start\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.removeRange(\"A\", 4, 6);\n\t\t\thelper.obliterateRange(\"B\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t},\n\t\texpectedText: \"heworld\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"remove, then obliterate adjacent to range end\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.removeRange(\"A\", 2, 4);\n\t\t\thelper.obliterateRange(\"B\", { pos: 3, side: Side.After }, { pos: 6, side: Side.After });\n\t\t},\n\t\texpectedText: \"heorld\",\n\t});\n\n\t// This test is somewhat arbitrary: it's a minimized fuzz test failure that ended up root-causing to an issue\n\t// in SortedSegmentSet (local references were not compared correctly when put at various offsets). We also have\n\t// more direct unit tests for that, but this is a good sanity check and adds some extra verification for concurrent obliterates.\n\titCorrectlyObliterates({\n\t\ttitle: \"overlapping obliterates with third client inserting\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"0123456789\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.obliterateRange(\"A\", { pos: 7, side: Side.After }, { pos: 8, side: Side.After });\n\t\t\thelper.obliterateRange(\"C\", { pos: 1, side: Side.Before }, { pos: 8, side: Side.After });\n\t\t\thelper.insertText(\"B\", 5, \"V\");\n\t\t\thelper.processAllOps();\n\t\t},\n\t\texpectedText: \"09\",\n\t});\n});\n\ndescribe.skip(\"reconnect\", () => {\n\titCorrectlyObliterates({\n\t\ttitle: \"add text, disconnect, obliterate, reconnect, insert adjacent to obliterated range\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.disconnect([\"C\"]);\n\t\t\tconst op = helper.obliterateRangeLocal(\n\t\t\t\t\"C\",\n\t\t\t\t{ pos: 1, side: Side.After },\n\t\t\t\t{ pos: 4, side: Side.After },\n\t\t\t);\n\t\t\thelper.reconnect([\"C\"]);\n\t\t\thelper.submitDisconnectedOp(\"C\", op);\n\t\t\thelper.processAllOps();\n\t\t\t// inserting adjacent to the obliterated range start\n\t\t\thelper.insertText(\"A\", 2, \"123\");\n\t\t},\n\t\texpectedText: \"heo world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"add text, disconnect, obliterate, insert adjacent to obliterated range, reconnect\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.disconnect([\"C\"]);\n\t\t\tconst op = helper.obliterateRangeLocal(\n\t\t\t\t\"C\",\n\t\t\t\t{ pos: 1, side: Side.After },\n\t\t\t\t{ pos: 4, side: Side.After },\n\t\t\t);\n\t\t\t// inserting adjacent to the obliterated range start\n\t\t\thelper.insertText(\"A\", 2, \"123\");\n\t\t\thelper.reconnect([\"C\"]);\n\t\t\thelper.submitDisconnectedOp(\"C\", op);\n\t\t},\n\t\texpectedText: \"heo world\",\n\t});\n});\n\ndescribe(\"sided obliterates\", () => {\n\t/**\n\t * All test cases will operate on the same numerical positions, but differ on their sidedness:\n\t * 1. A expand both endpoints, B expand neither endpoint = expand range on both endpoints\n\t * 2. A expand start endpoint, B expand end endpoint = either FWW/LWW\n\t * 3. A expand both endpoints, B expand start = expand range on both endpoints\n\t * 4. (similar to 3) A expand both endpoints, B expand end = expand range on both endpoints\n\t * 5. A expand neither endpoint, B expand start = expand start endpoint\n\t * 6. A expand neither endpoint, B expand end = expand end endpoint\n\t * before = 0, after = 1\n\t */\n\titCorrectlyObliterates({\n\t\ttitle: \"1. A expand both endpoints, B expand neither endpoint\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\t\t\t// in order to get the right behavior, the range needs to start after the previous position\n\t\t\t// if so, for a range ( 2, 4 ) itCorrectlyObliterates would need to be after 1 and before 5\n\t\t\t// h e( l l o )_ w o r l d\n\t\t\thelper.obliterateRange(\"A\", { pos: 1, side: Side.After }, { pos: 5, side: Side.Before });\n\t\t\t// [2, 4]: before 2, after 4 => h e [l l o] _ w o r l d\n\t\t\thelper.obliterateRange(\"B\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t\thelper.insertText(\"C\", 2, \"123\");\n\t\t\thelper.insertText(\"C\", 8, \"456\");\n\t\t},\n\t\texpectedText: \"he world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"2. A expand start endpoint, B expand end endpoint\",\n\t\taction: (helper) => {\n\t\t\t// currently this is the example from obliterate notation loop doc\n\t\t\t// TODO: translate this into same format as others\n\t\t\t// i think this gets difficult when the range to obliterate > 1 character\n\t\t\thelper.insertText(\"A\", 0, \"ABC\");\n\t\t\thelper.processAllOps();\n\t\t\thelper.insertText(\"A\", 2, \"D\");\n\t\t\t// ( 1]: after 0, after 1 => A( B] D C\n\t\t\thelper.obliterateRange(\"A\", { pos: 0, side: Side.After }, { pos: 1, side: Side.After });\n\t\t\t// included in the range -- should get obliterated\n\t\t\thelper.insertText(\"B\", 1, \"E\");\n\t\t\t// [1 ): before 1, before 2 => A E [B )C\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 1, side: Side.Before },\n\t\t\t\t{ pos: 3, side: Side.Before },\n\t\t\t);\n\t\t},\n\t\texpectedText: \"AC\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"3. A expand both endpoints, B expand start\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\t// ( 2, 4 ): after 1, before 5 => h e( l l o )_ w o r l d\n\t\t\thelper.obliterateRange(\"A\", { pos: 1, side: Side.After }, { pos: 5, side: Side.Before });\n\t\t\t// ( 2, 4]: after 1, after 4 => h e( l l o] _ w o r l d\n\t\t\thelper.obliterateRange(\"B\", { pos: 2, side: Side.After }, { pos: 4, side: Side.Before });\n\t\t\thelper.insertText(\"C\", 2, \"123\");\n\t\t\t// for this to be interesting, might want to insert at 5\n\t\t\thelper.insertText(\"C\", 4, \"456\");\n\t\t},\n\t\texpectedText: \"he world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"4. A expand both endpoints, B expand end\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\t// ( 2, 4 ): after 1, before 5 => h e( l l o )_ w o r l d\n\t\t\thelper.obliterateRange(\"A\", { pos: 1, side: Side.After }, { pos: 5, side: Side.Before });\n\t\t\t// [2, 4 ): before 2, before 5 => h e [l l o )_ w o r l d\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 2, side: Side.Before },\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t);\n\t\t\thelper.insertText(\"C\", 2, \"123\"); // he123llo world\n\t\t\t// for this to be interesting, might want to insert at 5\n\t\t\thelper.insertText(\"C\", 8, \"456\"); // he123llo456 world\n\t\t},\n\t\texpectedText: \"he world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"5. A expand neither endpoint, B expand start\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\t// [2, 4]: before 2, after 4 => h e [l l o] _ w o r l d\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t\t// ( 2, 4]: after 1, after 4 => h e( l l o] _ w o r l d\n\t\t\thelper.obliterateRange(\"B\", { pos: 1, side: Side.After }, { pos: 4, side: Side.After });\n\n\t\t\thelper.insertText(\"C\", 2, \"123\"); // h e( 123 l l o] _ w o r l d\n\t\t\thelper.insertText(\"C\", 8, \"456\"); // h e( 123 l l o) 456 _ w o r l d\n\t\t\thelper.processAllOps();\n\n\t\t\tassert.equal(helper.clients.A.getText(), \"he456 world\");\n\t\t\tassert.equal(helper.clients.B.getText(), \"he456 world\");\n\t\t\tassert.equal(helper.clients.C.getText(), \"he456 world\");\n\n\t\t\thelper.logger.validate();\n\t\t},\n\t\texpectedText: \"he456 world\",\n\t});\n\titCorrectlyObliterates({\n\t\ttitle: \"6. A expand neither endpoint, B expand end\",\n\t\taction: (helper) => {\n\t\t\thelper.insertText(\"A\", 0, \"hello world\");\n\t\t\thelper.processAllOps();\n\n\t\t\t// [2, 4]: before 2, after 4 => h e [l l o] _ w o r l d\n\t\t\thelper.obliterateRange(\"A\", { pos: 2, side: Side.Before }, { pos: 4, side: Side.After });\n\t\t\t// [2, 4 ): before 2, before 5 => h e [l l o )_ w o r l d\n\t\t\thelper.obliterateRange(\n\t\t\t\t\"B\",\n\t\t\t\t{ pos: 2, side: Side.Before },\n\t\t\t\t{ pos: 5, side: Side.Before },\n\t\t\t);\n\n\t\t\thelper.insertText(\"C\", 2, \"123\");\n\t\t\thelper.insertText(\"C\", 8, \"456\");\n\n\t\t\thelper.processAllOps();\n\n\t\t\tassert.equal(helper.clients.A.getText(), \"he123 world\");\n\t\t\tassert.equal(helper.clients.B.getText(), \"he123 world\");\n\t\t\tassert.equal(helper.clients.C.getText(), \"he123 world\");\n\n\t\t\thelper.logger.validate();\n\t\t},\n\t\texpectedText: \"he123 world\",\n\t});\n});\n"]}
@@ -164,13 +164,14 @@ describe("obliterate", () => {
164
164
  const obliterateEnd = client.getLength();
165
165
  const startSeg = client.getContainingSegment(obliterateStart);
166
166
  const endSeg = client.getContainingSegment(obliterateEnd);
167
+ let seq = refSeq;
167
168
  obliterateRange({
168
169
  mergeTree: client.mergeTree,
169
170
  start: obliterateStart,
170
171
  end: obliterateEnd,
171
172
  refSeq,
172
173
  clientId: remoteClientId,
173
- seq: refSeq + 1,
174
+ seq: ++seq,
174
175
  opArgs: undefined,
175
176
  });
176
177
  insertText({
@@ -178,7 +179,7 @@ describe("obliterate", () => {
178
179
  pos: 1,
179
180
  refSeq,
180
181
  clientId: remoteClientId + 1,
181
- seq: refSeq + 2,
182
+ seq: ++seq,
182
183
  text: "more ",
183
184
  props: undefined,
184
185
  opArgs: { op: { type: MergeTreeDeltaType.INSERT } },
@@ -193,7 +194,6 @@ describe("obliterate", () => {
193
194
  assert(oblProps?.end !== undefined, "end ref should NOT be removed");
194
195
  });
195
196
  // this will force Zamboni to run
196
- let seq = refSeq;
197
197
  for (let i = 0; i < 5; i++) {
198
198
  const insert = client.makeOpMessage(client.insertTextLocal(client.getLength(), i.toString()), ++seq);
199
199
  insert.minimumSequenceNumber = seq - 1;
@@ -1 +1 @@
1
- {"version":3,"file":"obliterate.spec.js","sourceRoot":"","sources":["../../src/test/obliterate.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport type { ISegmentPrivate, ObliterateInfo } from \"../mergeTreeNodes.js\";\nimport { MergeTreeDeltaType } from \"../ops.js\";\n\nimport { TestClient } from \"./testClient.js\";\nimport { insertText, obliterateRange } from \"./testUtils.js\";\n\ndescribe(\"obliterate\", () => {\n\tlet client: TestClient;\n\tlet refSeq: number;\n\tconst localClientId = 17;\n\tconst remoteClientId = localClientId + 1;\n\n\tbeforeEach(() => {\n\t\tclient = new TestClient({\n\t\t\tmergeTreeEnableObliterate: true,\n\t\t});\n\t\tclient.startOrUpdateCollaboration(\"local\");\n\t\tfor (const char of \"hello world\") {\n\t\t\tclient.applyMsg(\n\t\t\t\tclient.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), char),\n\t\t\t\t\tclient.getCurrentSeq() + 1,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tassert.equal(client.getText(), \"hello world\");\n\t\trefSeq = client.getCurrentSeq();\n\t});\n\n\tit(\"removes text\", () => {\n\t\tclient.obliterateRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tdescribe(\"concurrent obliterate and insert\", () => {\n\t\tit(\"removes text for obliterate then insert\", () => {\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 0,\n\t\t\t\tend: client.getLength(),\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 1,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t\tit(\"removes text for insert then obliterate when deleting entire string\", () => {\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 1,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 0,\n\t\t\t\tend: \"hello world\".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t\tit(\"removes text for insert then obliterate\", () => {\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 5,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 1,\n\t\t\t\tend: \"hello world\".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"h\");\n\t\t});\n\t});\n\n\tdescribe(\"endpoint behavior\", () => {\n\t\tit(\"does not expand to include text inserted at start\", () => {\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 5,\n\t\t\t\tend: client.getLength(),\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 5,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\ttext: \"XXX\",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"helloXXX\");\n\t\t});\n\t\tit(\"does not expand to include text inserted at end\", () => {\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 0,\n\t\t\t\tend: \"hello\".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 5,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\ttext: \"XXX\",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"XXX world\");\n\t\t});\n\t});\n\n\tdescribe(\"local obliterate with concurrent inserts\", () => {\n\t\tit(\"removes range when pending local obliterate op\", () => {\n\t\t\tclient.obliterateRangeLocal(0, client.getLength());\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 1,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\ttext: \"XXX\",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t});\n\n\tdescribe(\"local references\", () => {\n\t\tit(\"cleans up local references once the collab window advances enough\", () => {\n\t\t\tconst client2 = new TestClient({ mergeTreeEnableObliterate: true });\n\t\t\tclient2.startOrUpdateCollaboration(\"client2\");\n\n\t\t\tconst obliterateStart = 0;\n\t\t\tconst obliterateEnd = client.getLength();\n\t\t\tconst startSeg = client.getContainingSegment<ISegmentPrivate>(obliterateStart);\n\t\t\tconst endSeg = client.getContainingSegment<ISegmentPrivate>(obliterateEnd);\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: obliterateStart,\n\t\t\t\tend: obliterateEnd,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 1,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"\");\n\n\t\t\tstartSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps?.start !== undefined, \"start ref should NOT be removed\");\n\t\t\t});\n\t\t\tendSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps?.end !== undefined, \"end ref should NOT be removed\");\n\t\t\t});\n\n\t\t\t// this will force Zamboni to run\n\t\t\tlet seq = refSeq;\n\t\t\tfor (let i = 0; i < 5; i++) {\n\t\t\t\tconst insert = client.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), i.toString()),\n\t\t\t\t\t++seq,\n\t\t\t\t);\n\t\t\t\tinsert.minimumSequenceNumber = seq - 1;\n\t\t\t\tclient.applyMsg(insert);\n\t\t\t\tclient2.applyMsg(insert);\n\t\t\t}\n\n\t\t\t// want to check that the start and end segment don't have the obliterate refs on them\n\t\t\tstartSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps.start === undefined, \"start ref should be removed\");\n\t\t\t});\n\t\t\tendSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps.end === undefined, \"end ref should be removed\");\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"obliterate.spec.js","sourceRoot":"","sources":["../../src/test/obliterate.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport type { ISegmentPrivate, ObliterateInfo } from \"../mergeTreeNodes.js\";\nimport { MergeTreeDeltaType } from \"../ops.js\";\n\nimport { TestClient } from \"./testClient.js\";\nimport { insertText, obliterateRange } from \"./testUtils.js\";\n\ndescribe(\"obliterate\", () => {\n\tlet client: TestClient;\n\tlet refSeq: number;\n\tconst localClientId = 17;\n\tconst remoteClientId = localClientId + 1;\n\n\tbeforeEach(() => {\n\t\tclient = new TestClient({\n\t\t\tmergeTreeEnableObliterate: true,\n\t\t});\n\t\tclient.startOrUpdateCollaboration(\"local\");\n\t\tfor (const char of \"hello world\") {\n\t\t\tclient.applyMsg(\n\t\t\t\tclient.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), char),\n\t\t\t\t\tclient.getCurrentSeq() + 1,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tassert.equal(client.getText(), \"hello world\");\n\t\trefSeq = client.getCurrentSeq();\n\t});\n\n\tit(\"removes text\", () => {\n\t\tclient.obliterateRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tdescribe(\"concurrent obliterate and insert\", () => {\n\t\tit(\"removes text for obliterate then insert\", () => {\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 0,\n\t\t\t\tend: client.getLength(),\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 1,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t\tit(\"removes text for insert then obliterate when deleting entire string\", () => {\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 1,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 0,\n\t\t\t\tend: \"hello world\".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t\tit(\"removes text for insert then obliterate\", () => {\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 5,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 1,\n\t\t\t\tend: \"hello world\".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"h\");\n\t\t});\n\t});\n\n\tdescribe(\"endpoint behavior\", () => {\n\t\tit(\"does not expand to include text inserted at start\", () => {\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 5,\n\t\t\t\tend: client.getLength(),\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 5,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\ttext: \"XXX\",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"helloXXX\");\n\t\t});\n\t\tit(\"does not expand to include text inserted at end\", () => {\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 0,\n\t\t\t\tend: \"hello\".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 5,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\ttext: \"XXX\",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"XXX world\");\n\t\t});\n\t});\n\n\tdescribe(\"local obliterate with concurrent inserts\", () => {\n\t\tit(\"removes range when pending local obliterate op\", () => {\n\t\t\tclient.obliterateRangeLocal(0, client.getLength());\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 1,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\ttext: \"XXX\",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t});\n\n\tdescribe(\"local references\", () => {\n\t\tit(\"cleans up local references once the collab window advances enough\", () => {\n\t\t\tconst client2 = new TestClient({ mergeTreeEnableObliterate: true });\n\t\t\tclient2.startOrUpdateCollaboration(\"client2\");\n\n\t\t\tconst obliterateStart = 0;\n\t\t\tconst obliterateEnd = client.getLength();\n\t\t\tconst startSeg = client.getContainingSegment<ISegmentPrivate>(obliterateStart);\n\t\t\tconst endSeg = client.getContainingSegment<ISegmentPrivate>(obliterateEnd);\n\t\t\tlet seq = refSeq;\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: obliterateStart,\n\t\t\t\tend: obliterateEnd,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: ++seq,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 1,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: ++seq,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"\");\n\n\t\t\tstartSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps?.start !== undefined, \"start ref should NOT be removed\");\n\t\t\t});\n\t\t\tendSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps?.end !== undefined, \"end ref should NOT be removed\");\n\t\t\t});\n\n\t\t\t// this will force Zamboni to run\n\t\t\tfor (let i = 0; i < 5; i++) {\n\t\t\t\tconst insert = client.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), i.toString()),\n\t\t\t\t\t++seq,\n\t\t\t\t);\n\t\t\t\tinsert.minimumSequenceNumber = seq - 1;\n\t\t\t\tclient.applyMsg(insert);\n\t\t\t\tclient2.applyMsg(insert);\n\t\t\t}\n\n\t\t\t// want to check that the start and end segment don't have the obliterate refs on them\n\t\t\tstartSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps.start === undefined, \"start ref should be removed\");\n\t\t\t});\n\t\t\tendSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps.end === undefined, \"end ref should be removed\");\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
@@ -0,0 +1,15 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import type { IRandom } from "@fluid-private/stochastic-test-utils";
6
+ import type { IMergeTreeOp } from "../ops.js";
7
+ import { type TestOperation } from "./mergeTreeOperationRunner.js";
8
+ import type { TestClient } from "./testClient.js";
9
+ export declare const insertField: TestOperation;
10
+ export declare const obliterateField: TestOperation;
11
+ export declare const insertAvoidField: TestOperation;
12
+ export declare const removeWithField: TestOperation;
13
+ export declare const annotateWithField: TestOperation;
14
+ export declare const generateInsertWithField: (client: TestClient, random: IRandom) => IMergeTreeOp | undefined;
15
+ //# sourceMappingURL=obliterateOperations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obliterateOperations.d.ts","sourceRoot":"","sources":["../../src/test/obliterateOperations.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAGpE,OAAO,KAAK,EAAuB,YAAY,EAAE,MAAM,WAAW,CAAC;AAGnE,OAAO,EAA8B,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAuElD,eAAO,MAAM,WAAW,EAAE,aAUzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,aA6C7B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,aAY9B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,aAc7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,aAc/B,CAAC;AAEF,eAAO,MAAM,uBAAuB,WAC3B,UAAU,UACV,OAAO,KACb,YAAY,GAAG,SAQjB,CAAC"}
@@ -0,0 +1,123 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
6
+ import { strict as assert } from "node:assert";
7
+ import { Side } from "../sequencePlace.js";
8
+ import { annotateRange, removeRange } from "./mergeTreeOperationRunner.js";
9
+ const posInField = (client, pos) => {
10
+ const isFieldCharacter = (char) => Number.isInteger(Number(char)) || char === "{" || char === "}";
11
+ if (pos >= client.getLength() || !isFieldCharacter(client.getText(pos, pos + 1))) {
12
+ // pos is not within a field.
13
+ return undefined;
14
+ }
15
+ let startPos = pos;
16
+ let endPos = pos;
17
+ // To find the start and end separators, walk backwards and forwards until the desired character is found.
18
+ while (startPos > 0 && client.getText(startPos, startPos + 1) !== "{") {
19
+ const text = client.getText(endPos, endPos + 1);
20
+ assert(Number.isInteger(Number(text)) || text === "}", "Non-integer character found within a field");
21
+ startPos--;
22
+ }
23
+ while (endPos < client.getLength() && client.getText(endPos, endPos + 1) !== "}") {
24
+ const text = client.getText(endPos, endPos + 1);
25
+ assert(Number.isInteger(Number(text)) || text === "{", "Non-integer character found within a field");
26
+ endPos++;
27
+ }
28
+ assert(client.getText(startPos, startPos + 1) === "{", "Start separator not found");
29
+ assert(endPos < client.getLength() && client.getText(endPos, endPos + 1) === "}", "End separator not found");
30
+ return { startPos, endPos };
31
+ };
32
+ const getFieldEndpoints = (client, start, end) => {
33
+ const startField = posInField(client, start);
34
+ const endField = posInField(client, end);
35
+ if (startField === undefined && endField === undefined) {
36
+ return undefined;
37
+ }
38
+ return startField ?? endField;
39
+ };
40
+ const generateFieldText = (client, random) => {
41
+ const chunkLength = random.integer(1, 10);
42
+ return (client.longClientId.codePointAt(0) % 10).toString().repeat(chunkLength);
43
+ };
44
+ const insertFieldText = (client, opStart, random) => {
45
+ const text = generateFieldText(client, random);
46
+ return client.insertTextLocal(opStart, text);
47
+ };
48
+ export const insertField = (client, opStart, opEnd, random) => {
49
+ const numberText = generateFieldText(client, random);
50
+ if (posInField(client, opStart) === undefined) {
51
+ return client.insertTextLocal(opStart, `{${numberText}}`);
52
+ }
53
+ };
54
+ export const obliterateField = (client, opStart, opEnd, random) => {
55
+ const fieldEndpoints = getFieldEndpoints(client, opStart,
56
+ // the operation runner generates endpoints with client length, but this model only supports up to client length - 1.
57
+ Math.min(opEnd, client.getLength() - 1));
58
+ let endISP;
59
+ if (fieldEndpoints !== undefined) {
60
+ const { startPos, endPos } = fieldEndpoints;
61
+ // Obliterate text between the separators, but avoid the case where the obliterate range is zero length.
62
+ if (endPos - startPos > 1) {
63
+ const obliterateOp = client.obliterateRangeLocal({ pos: startPos, side: Side.After }, { pos: endPos, side: Side.Before });
64
+ const insertOp = insertFieldText(client, startPos + 1, random);
65
+ assert(insertOp !== undefined, "Insert op should not be undefined");
66
+ // TODO: AB#31001: We should be able to sometimes use group ops here rather than submit two separate ops,
67
+ // but this causes failures which likely indicate there are bugs with the intersection of obliterate and grouped batching.
68
+ // const op = createGroupOp(obliterateOp, insertOp);
69
+ return [obliterateOp, insertOp];
70
+ }
71
+ else {
72
+ return;
73
+ }
74
+ }
75
+ if (opEnd >= client.getLength()) {
76
+ endISP = { pos: client.getLength() - 1, side: Side.After };
77
+ }
78
+ if (!client.getText(opStart, opEnd).includes("{")) {
79
+ // Avoid issuing obliterates that might contain multiple fields.
80
+ // Otherwise we may end up with field characters that look like they're outside of the field,
81
+ // since one of these obliterates can wipe out the field including the `{}` delimiters, but
82
+ // a "field replace" obliterate + insert can win and insert the numerical characters.
83
+ return client.obliterateRangeLocal({ pos: opStart, side: Side.Before }, endISP ?? { pos: opEnd, side: Side.After });
84
+ }
85
+ };
86
+ export const insertAvoidField = (client, opStart, opEnd, random) => {
87
+ let start = opStart;
88
+ const endpoints = posInField(client, opStart);
89
+ if (endpoints !== undefined) {
90
+ start = endpoints.startPos;
91
+ }
92
+ return client.insertTextLocal(start, client.longClientId.repeat(random.integer(1, 3)));
93
+ };
94
+ export const removeWithField = (client, opStart, opEnd, random) => {
95
+ let start = opStart;
96
+ let end = opEnd;
97
+ const fieldEndpoints = getFieldEndpoints(client, opStart, opEnd);
98
+ if (fieldEndpoints !== undefined) {
99
+ start = fieldEndpoints.startPos;
100
+ end = fieldEndpoints.endPos + 1;
101
+ }
102
+ return removeRange(client, start, end, random);
103
+ };
104
+ export const annotateWithField = (client, opStart, opEnd, random) => {
105
+ let start = opStart;
106
+ let end = opEnd;
107
+ const fieldEndpoints = getFieldEndpoints(client, opStart, opEnd);
108
+ if (fieldEndpoints !== undefined) {
109
+ start = fieldEndpoints.startPos;
110
+ end = fieldEndpoints.endPos + 1;
111
+ }
112
+ return annotateRange(client, start, end, random);
113
+ };
114
+ export const generateInsertWithField = (client, random) => {
115
+ const text = client.longClientId.repeat(random.integer(1, 3));
116
+ let pos = random.integer(0, client.getLength());
117
+ const endpoints = posInField(client, pos);
118
+ if (endpoints !== undefined) {
119
+ pos = 0;
120
+ }
121
+ return client.insertTextLocal(pos, text);
122
+ };
123
+ //# sourceMappingURL=obliterateOperations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obliterateOperations.js","sourceRoot":"","sources":["../../src/test/obliterateOperations.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport type { IRandom } from \"@fluid-private/stochastic-test-utils\";\n\n// import { createGroupOp } from \"../opBuilder.js\";\nimport type { IMergeTreeInsertMsg, IMergeTreeOp } from \"../ops.js\";\nimport { InteriorSequencePlace, Side } from \"../sequencePlace.js\";\n\nimport { annotateRange, removeRange, type TestOperation } from \"./mergeTreeOperationRunner.js\";\nimport type { TestClient } from \"./testClient.js\";\n\nconst posInField = (\n\tclient: TestClient,\n\tpos: number,\n): { startPos: number; endPos: number } | undefined => {\n\tconst isFieldCharacter = (char: string): boolean =>\n\t\tNumber.isInteger(Number(char)) || char === \"{\" || char === \"}\";\n\tif (pos >= client.getLength() || !isFieldCharacter(client.getText(pos, pos + 1))) {\n\t\t// pos is not within a field.\n\t\treturn undefined;\n\t}\n\n\tlet startPos = pos;\n\tlet endPos = pos;\n\t// To find the start and end separators, walk backwards and forwards until the desired character is found.\n\twhile (startPos > 0 && client.getText(startPos, startPos + 1) !== \"{\") {\n\t\tconst text = client.getText(endPos, endPos + 1);\n\t\tassert(\n\t\t\tNumber.isInteger(Number(text)) || text === \"}\",\n\t\t\t\"Non-integer character found within a field\",\n\t\t);\n\t\tstartPos--;\n\t}\n\n\twhile (endPos < client.getLength() && client.getText(endPos, endPos + 1) !== \"}\") {\n\t\tconst text = client.getText(endPos, endPos + 1);\n\t\tassert(\n\t\t\tNumber.isInteger(Number(text)) || text === \"{\",\n\t\t\t\"Non-integer character found within a field\",\n\t\t);\n\t\tendPos++;\n\t}\n\n\tassert(client.getText(startPos, startPos + 1) === \"{\", \"Start separator not found\");\n\tassert(\n\t\tendPos < client.getLength() && client.getText(endPos, endPos + 1) === \"}\",\n\t\t\"End separator not found\",\n\t);\n\n\treturn { startPos, endPos };\n};\n\nconst getFieldEndpoints = (\n\tclient: TestClient,\n\tstart: number,\n\tend: number,\n): { startPos: number; endPos: number } | undefined => {\n\tconst startField = posInField(client, start);\n\tconst endField = posInField(client, end);\n\n\tif (startField === undefined && endField === undefined) {\n\t\treturn undefined;\n\t}\n\treturn startField ?? endField;\n};\n\nconst generateFieldText = (client: TestClient, random: IRandom): string => {\n\tconst chunkLength = random.integer(1, 10);\n\treturn (client.longClientId!.codePointAt(0)! % 10).toString().repeat(chunkLength);\n};\n\nconst insertFieldText = (\n\tclient: TestClient,\n\topStart: number,\n\trandom: IRandom,\n): IMergeTreeInsertMsg | undefined => {\n\tconst text = generateFieldText(client, random);\n\treturn client.insertTextLocal(opStart, text);\n};\n\nexport const insertField: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tconst numberText = generateFieldText(client, random);\n\tif (posInField(client, opStart) === undefined) {\n\t\treturn client.insertTextLocal(opStart, `{${numberText}}`);\n\t}\n};\n\nexport const obliterateField: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tconst fieldEndpoints = getFieldEndpoints(\n\t\tclient,\n\t\topStart,\n\t\t// the operation runner generates endpoints with client length, but this model only supports up to client length - 1.\n\t\tMath.min(opEnd, client.getLength() - 1),\n\t);\n\n\tlet endISP: InteriorSequencePlace | undefined;\n\tif (fieldEndpoints !== undefined) {\n\t\tconst { startPos, endPos } = fieldEndpoints;\n\t\t// Obliterate text between the separators, but avoid the case where the obliterate range is zero length.\n\t\tif (endPos - startPos > 1) {\n\t\t\tconst obliterateOp = client.obliterateRangeLocal(\n\t\t\t\t{ pos: startPos, side: Side.After },\n\t\t\t\t{ pos: endPos, side: Side.Before },\n\t\t\t);\n\t\t\tconst insertOp = insertFieldText(client, startPos + 1, random);\n\t\t\tassert(insertOp !== undefined, \"Insert op should not be undefined\");\n\t\t\t// TODO: AB#31001: We should be able to sometimes use group ops here rather than submit two separate ops,\n\t\t\t// but this causes failures which likely indicate there are bugs with the intersection of obliterate and grouped batching.\n\t\t\t// const op = createGroupOp(obliterateOp, insertOp);\n\t\t\treturn [obliterateOp, insertOp];\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\t}\n\tif (opEnd >= client.getLength()) {\n\t\tendISP = { pos: client.getLength() - 1, side: Side.After };\n\t}\n\tif (!client.getText(opStart, opEnd).includes(\"{\")) {\n\t\t// Avoid issuing obliterates that might contain multiple fields.\n\t\t// Otherwise we may end up with field characters that look like they're outside of the field,\n\t\t// since one of these obliterates can wipe out the field including the `{}` delimiters, but\n\t\t// a \"field replace\" obliterate + insert can win and insert the numerical characters.\n\t\treturn client.obliterateRangeLocal(\n\t\t\t{ pos: opStart, side: Side.Before },\n\t\t\tendISP ?? { pos: opEnd, side: Side.After },\n\t\t);\n\t}\n};\n\nexport const insertAvoidField: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tlet start = opStart;\n\tconst endpoints = posInField(client, opStart);\n\tif (endpoints !== undefined) {\n\t\tstart = endpoints.startPos;\n\t}\n\treturn client.insertTextLocal(start, client.longClientId!.repeat(random.integer(1, 3)));\n};\n\nexport const removeWithField: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tlet start = opStart;\n\tlet end = opEnd;\n\tconst fieldEndpoints = getFieldEndpoints(client, opStart, opEnd);\n\tif (fieldEndpoints !== undefined) {\n\t\tstart = fieldEndpoints.startPos;\n\t\tend = fieldEndpoints.endPos + 1;\n\t}\n\treturn removeRange(client, start, end, random);\n};\n\nexport const annotateWithField: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tlet start = opStart;\n\tlet end = opEnd;\n\tconst fieldEndpoints = getFieldEndpoints(client, opStart, opEnd);\n\tif (fieldEndpoints !== undefined) {\n\t\tstart = fieldEndpoints.startPos;\n\t\tend = fieldEndpoints.endPos + 1;\n\t}\n\treturn annotateRange(client, start, end, random);\n};\n\nexport const generateInsertWithField = (\n\tclient: TestClient,\n\trandom: IRandom,\n): IMergeTreeOp | undefined => {\n\tconst text = client.longClientId!.repeat(random.integer(1, 3));\n\tlet pos = random.integer(0, client.getLength());\n\tconst endpoints = posInField(client, pos);\n\tif (endpoints !== undefined) {\n\t\tpos = 0;\n\t}\n\treturn client.insertTextLocal(pos, text);\n};\n"]}
@@ -0,0 +1,42 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
6
+ import type { IMergeTreeOptions, InteriorSequencePlace } from "../index.js";
7
+ import type { TestClient } from "./testClient.js";
8
+ import { TestClientLogger } from "./testClientLogger.js";
9
+ declare const ClientIds: readonly ["A", "B", "C", "D"];
10
+ type ClientName = (typeof ClientIds)[number];
11
+ /**
12
+ * Like `ReconnectHelper`, but:
13
+ * - does not support reconnecting clients
14
+ * - supports advancing only some clients to a given sequence number (not all clients must be synchronized at the same time).
15
+ *
16
+ * This allows testing sequences of operations where clients have varying refSeqs, rather than having all clients advance refSeq
17
+ * in lockstep.
18
+ */
19
+ export declare class PartialSyncTestHelper {
20
+ clients: Record<ClientName, TestClient> & {
21
+ all: TestClient[];
22
+ };
23
+ idxFromName(name: ClientName): number;
24
+ logger: TestClientLogger;
25
+ ops: ISequencedDocumentMessage[];
26
+ clientToLastAppliedSeq: Map<"A" | "C" | "B" | "D", number>;
27
+ perClientOps: ISequencedDocumentMessage[][];
28
+ private seq;
29
+ constructor(options?: IMergeTreeOptions);
30
+ private addMessage;
31
+ insertText(clientName: ClientName, pos: number, text: string): void;
32
+ removeRange(clientName: ClientName, start: number, end: number): void;
33
+ obliterateRange(clientName: ClientName, start: number | InteriorSequencePlace, end: number | InteriorSequencePlace): void;
34
+ advanceClientToSeq(clientName: ClientName, seq: number): void;
35
+ /**
36
+ * Sends all known ops to the procieded client ids.
37
+ */
38
+ advanceClients(...clientNames: ClientName[]): void;
39
+ processAllOps(): void;
40
+ }
41
+ export {};
42
+ //# sourceMappingURL=partialSyncHelper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partialSyncHelper.d.ts","sourceRoot":"","sources":["../../src/test/partialSyncHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAExF,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAA+B,MAAM,uBAAuB,CAAC;AAEtF,QAAA,MAAM,SAAS,+BAAgC,CAAC;AAChD,KAAK,UAAU,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7C;;;;;;;GAOG;AACH,qBAAa,qBAAqB;IACjC,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG;QAAE,GAAG,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;IAEhE,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAIrC,MAAM,EAAE,gBAAgB,CAAC;IAEzB,GAAG,EAAE,yBAAyB,EAAE,CAAM;IACtC,sBAAsB,qCAAiC;IAEvD,YAAY,EAAE,yBAAyB,EAAE,EAAE,CAAC;IAE5C,OAAO,CAAC,GAAG,CAAa;gBAEL,OAAO,GAAE,iBAAsB;IAgBlD,OAAO,CAAC,UAAU;IAUX,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKnE,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAKrE,eAAe,CACrB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,GAAG,qBAAqB,EACrC,GAAG,EAAE,MAAM,GAAG,qBAAqB,GACjC,IAAI;IAWA,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAwBpE;;OAEG;IACI,cAAc,CAAC,GAAG,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI;IAOlD,aAAa,IAAI,IAAI;CAM5B"}