@fluidframework/merge-tree 2.30.0 → 2.31.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 (308) hide show
  1. package/CHANGELOG.md +403 -399
  2. package/api-report/merge-tree.legacy.alpha.api.md +1 -0
  3. package/dist/MergeTreeTextHelper.d.ts +9 -3
  4. package/dist/MergeTreeTextHelper.d.ts.map +1 -1
  5. package/dist/MergeTreeTextHelper.js +5 -5
  6. package/dist/MergeTreeTextHelper.js.map +1 -1
  7. package/dist/client.d.ts +7 -13
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +136 -110
  10. package/dist/client.js.map +1 -1
  11. package/dist/endOfTreeSegment.d.ts +12 -8
  12. package/dist/endOfTreeSegment.d.ts.map +1 -1
  13. package/dist/endOfTreeSegment.js +2 -4
  14. package/dist/endOfTreeSegment.js.map +1 -1
  15. package/dist/index.d.ts +6 -3
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +2 -3
  18. package/dist/index.js.map +1 -1
  19. package/dist/mergeTree.d.ts +37 -23
  20. package/dist/mergeTree.d.ts.map +1 -1
  21. package/dist/mergeTree.js +400 -483
  22. package/dist/mergeTree.js.map +1 -1
  23. package/dist/mergeTreeDeltaCallback.d.ts +4 -8
  24. package/dist/mergeTreeDeltaCallback.d.ts.map +1 -1
  25. package/dist/mergeTreeDeltaCallback.js.map +1 -1
  26. package/dist/mergeTreeNodes.d.ts +32 -10
  27. package/dist/mergeTreeNodes.d.ts.map +1 -1
  28. package/dist/mergeTreeNodes.js +43 -28
  29. package/dist/mergeTreeNodes.js.map +1 -1
  30. package/dist/partialLengths.d.ts +2 -2
  31. package/dist/partialLengths.d.ts.map +1 -1
  32. package/dist/partialLengths.js +181 -109
  33. package/dist/partialLengths.js.map +1 -1
  34. package/dist/perspective.d.ts +8 -27
  35. package/dist/perspective.d.ts.map +1 -1
  36. package/dist/perspective.js +7 -67
  37. package/dist/perspective.js.map +1 -1
  38. package/dist/revertibles.d.ts.map +1 -1
  39. package/dist/revertibles.js +2 -2
  40. package/dist/revertibles.js.map +1 -1
  41. package/dist/segmentInfos.d.ts +20 -106
  42. package/dist/segmentInfos.d.ts.map +1 -1
  43. package/dist/segmentInfos.js +28 -42
  44. package/dist/segmentInfos.js.map +1 -1
  45. package/dist/segmentPropertiesManager.d.ts +1 -14
  46. package/dist/segmentPropertiesManager.d.ts.map +1 -1
  47. package/dist/segmentPropertiesManager.js +3 -17
  48. package/dist/segmentPropertiesManager.js.map +1 -1
  49. package/dist/snapshotLoader.d.ts.map +1 -1
  50. package/dist/snapshotLoader.js +62 -19
  51. package/dist/snapshotLoader.js.map +1 -1
  52. package/dist/snapshotV1.d.ts.map +1 -1
  53. package/dist/snapshotV1.js +55 -24
  54. package/dist/snapshotV1.js.map +1 -1
  55. package/dist/snapshotlegacy.d.ts.map +1 -1
  56. package/dist/snapshotlegacy.js +6 -9
  57. package/dist/snapshotlegacy.js.map +1 -1
  58. package/dist/stamps.d.ts +1 -1
  59. package/dist/stamps.js +1 -1
  60. package/dist/stamps.js.map +1 -1
  61. package/dist/test/Insertion.perf.spec.js +6 -51
  62. package/dist/test/Insertion.perf.spec.js.map +1 -1
  63. package/dist/test/PartialLengths.perf.spec.js +18 -25
  64. package/dist/test/PartialLengths.perf.spec.js.map +1 -1
  65. package/dist/test/Removal.perf.spec.js +13 -41
  66. package/dist/test/Removal.perf.spec.js.map +1 -1
  67. package/dist/test/beastTest.spec.d.ts.map +1 -1
  68. package/dist/test/beastTest.spec.js +41 -66
  69. package/dist/test/beastTest.spec.js.map +1 -1
  70. package/dist/test/client.annotateMarker.spec.js +1 -11
  71. package/dist/test/client.annotateMarker.spec.js.map +1 -1
  72. package/dist/test/client.applyMsg.spec.js +14 -14
  73. package/dist/test/client.applyMsg.spec.js.map +1 -1
  74. package/dist/test/client.getPosition.spec.js +1 -1
  75. package/dist/test/client.getPosition.spec.js.map +1 -1
  76. package/dist/test/client.localReference.spec.js +1 -1
  77. package/dist/test/client.localReference.spec.js.map +1 -1
  78. package/dist/test/client.rollback.spec.js +49 -58
  79. package/dist/test/client.rollback.spec.js.map +1 -1
  80. package/dist/test/client.rollbackFarm.spec.js +1 -1
  81. package/dist/test/client.rollbackFarm.spec.js.map +1 -1
  82. package/dist/test/client.searchForMarker.spec.js +4 -21
  83. package/dist/test/client.searchForMarker.spec.js.map +1 -1
  84. package/dist/test/index.d.ts +2 -2
  85. package/dist/test/index.d.ts.map +1 -1
  86. package/dist/test/index.js +2 -6
  87. package/dist/test/index.js.map +1 -1
  88. package/dist/test/mergeTree.annotate.deltaCallback.spec.js +14 -59
  89. package/dist/test/mergeTree.annotate.deltaCallback.spec.js.map +1 -1
  90. package/dist/test/mergeTree.annotate.spec.js +47 -63
  91. package/dist/test/mergeTree.annotate.spec.js.map +1 -1
  92. package/dist/test/mergeTree.insert.deltaCallback.spec.js +9 -62
  93. package/dist/test/mergeTree.insert.deltaCallback.spec.js.map +1 -1
  94. package/dist/test/mergeTree.insertingWalk.spec.js +59 -125
  95. package/dist/test/mergeTree.insertingWalk.spec.js.map +1 -1
  96. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +12 -93
  97. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  98. package/dist/test/mergeTree.markRangeRemoved.spec.js +10 -7
  99. package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  100. package/dist/test/mergeTree.walk.spec.js +2 -14
  101. package/dist/test/mergeTree.walk.spec.js.map +1 -1
  102. package/dist/test/mergeTreeOperationRunner.js +2 -2
  103. package/dist/test/mergeTreeOperationRunner.js.map +1 -1
  104. package/dist/test/obliterate.concurrent.spec.js +18 -23
  105. package/dist/test/obliterate.concurrent.spec.js.map +1 -1
  106. package/dist/test/obliterate.partialLength.spec.js +166 -136
  107. package/dist/test/obliterate.partialLength.spec.js.map +1 -1
  108. package/dist/test/obliterate.spec.js +16 -126
  109. package/dist/test/obliterate.spec.js.map +1 -1
  110. package/dist/test/partialLength.spec.js +28 -196
  111. package/dist/test/partialLength.spec.js.map +1 -1
  112. package/dist/test/perspective.spec.js +34 -0
  113. package/dist/test/perspective.spec.js.map +1 -1
  114. package/dist/test/propertyManager.spec.js +1 -1
  115. package/dist/test/propertyManager.spec.js.map +1 -1
  116. package/dist/test/resetPendingSegmentsToOp.spec.js +0 -2
  117. package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  118. package/dist/test/segmentGroupCollection.spec.js +10 -4
  119. package/dist/test/segmentGroupCollection.spec.js.map +1 -1
  120. package/dist/test/testClient.d.ts +1 -0
  121. package/dist/test/testClient.d.ts.map +1 -1
  122. package/dist/test/testClient.js +16 -26
  123. package/dist/test/testClient.js.map +1 -1
  124. package/dist/test/testClientLogger.d.ts.map +1 -1
  125. package/dist/test/testClientLogger.js +3 -10
  126. package/dist/test/testClientLogger.js.map +1 -1
  127. package/dist/test/testServer.d.ts +2 -1
  128. package/dist/test/testServer.d.ts.map +1 -1
  129. package/dist/test/testServer.js +7 -5
  130. package/dist/test/testServer.js.map +1 -1
  131. package/dist/test/testUtils.d.ts +36 -56
  132. package/dist/test/testUtils.d.ts.map +1 -1
  133. package/dist/test/testUtils.js +68 -77
  134. package/dist/test/testUtils.js.map +1 -1
  135. package/dist/test/text.d.ts +2 -2
  136. package/dist/test/text.d.ts.map +1 -1
  137. package/dist/test/text.js +5 -2
  138. package/dist/test/text.js.map +1 -1
  139. package/dist/textSegment.d.ts +0 -6
  140. package/dist/textSegment.d.ts.map +1 -1
  141. package/dist/textSegment.js.map +1 -1
  142. package/dist/zamboni.d.ts.map +1 -1
  143. package/dist/zamboni.js +53 -26
  144. package/dist/zamboni.js.map +1 -1
  145. package/lib/MergeTreeTextHelper.d.ts +9 -3
  146. package/lib/MergeTreeTextHelper.d.ts.map +1 -1
  147. package/lib/MergeTreeTextHelper.js +5 -5
  148. package/lib/MergeTreeTextHelper.js.map +1 -1
  149. package/lib/client.d.ts +7 -13
  150. package/lib/client.d.ts.map +1 -1
  151. package/lib/client.js +117 -116
  152. package/lib/client.js.map +1 -1
  153. package/lib/endOfTreeSegment.d.ts +12 -8
  154. package/lib/endOfTreeSegment.d.ts.map +1 -1
  155. package/lib/endOfTreeSegment.js +2 -4
  156. package/lib/endOfTreeSegment.js.map +1 -1
  157. package/lib/index.d.ts +6 -3
  158. package/lib/index.d.ts.map +1 -1
  159. package/lib/index.js +1 -1
  160. package/lib/index.js.map +1 -1
  161. package/lib/mergeTree.d.ts +37 -23
  162. package/lib/mergeTree.d.ts.map +1 -1
  163. package/lib/mergeTree.js +381 -488
  164. package/lib/mergeTree.js.map +1 -1
  165. package/lib/mergeTreeDeltaCallback.d.ts +4 -8
  166. package/lib/mergeTreeDeltaCallback.d.ts.map +1 -1
  167. package/lib/mergeTreeDeltaCallback.js.map +1 -1
  168. package/lib/mergeTreeNodes.d.ts +32 -10
  169. package/lib/mergeTreeNodes.d.ts.map +1 -1
  170. package/lib/mergeTreeNodes.js +42 -29
  171. package/lib/mergeTreeNodes.js.map +1 -1
  172. package/lib/partialLengths.d.ts +2 -2
  173. package/lib/partialLengths.d.ts.map +1 -1
  174. package/lib/partialLengths.js +160 -111
  175. package/lib/partialLengths.js.map +1 -1
  176. package/lib/perspective.d.ts +8 -27
  177. package/lib/perspective.d.ts.map +1 -1
  178. package/lib/perspective.js +8 -68
  179. package/lib/perspective.js.map +1 -1
  180. package/lib/revertibles.d.ts.map +1 -1
  181. package/lib/revertibles.js +2 -2
  182. package/lib/revertibles.js.map +1 -1
  183. package/lib/segmentInfos.d.ts +20 -106
  184. package/lib/segmentInfos.d.ts.map +1 -1
  185. package/lib/segmentInfos.js +26 -37
  186. package/lib/segmentInfos.js.map +1 -1
  187. package/lib/segmentPropertiesManager.d.ts +1 -14
  188. package/lib/segmentPropertiesManager.d.ts.map +1 -1
  189. package/lib/segmentPropertiesManager.js +2 -16
  190. package/lib/segmentPropertiesManager.js.map +1 -1
  191. package/lib/snapshotLoader.d.ts.map +1 -1
  192. package/lib/snapshotLoader.js +39 -19
  193. package/lib/snapshotLoader.js.map +1 -1
  194. package/lib/snapshotV1.d.ts.map +1 -1
  195. package/lib/snapshotV1.js +34 -26
  196. package/lib/snapshotV1.js.map +1 -1
  197. package/lib/snapshotlegacy.d.ts.map +1 -1
  198. package/lib/snapshotlegacy.js +7 -10
  199. package/lib/snapshotlegacy.js.map +1 -1
  200. package/lib/stamps.d.ts +1 -1
  201. package/lib/stamps.js +1 -1
  202. package/lib/stamps.js.map +1 -1
  203. package/lib/test/Insertion.perf.spec.js +6 -51
  204. package/lib/test/Insertion.perf.spec.js.map +1 -1
  205. package/lib/test/PartialLengths.perf.spec.js +18 -25
  206. package/lib/test/PartialLengths.perf.spec.js.map +1 -1
  207. package/lib/test/Removal.perf.spec.js +13 -41
  208. package/lib/test/Removal.perf.spec.js.map +1 -1
  209. package/lib/test/beastTest.spec.d.ts.map +1 -1
  210. package/lib/test/beastTest.spec.js +42 -67
  211. package/lib/test/beastTest.spec.js.map +1 -1
  212. package/lib/test/client.annotateMarker.spec.js +1 -11
  213. package/lib/test/client.annotateMarker.spec.js.map +1 -1
  214. package/lib/test/client.applyMsg.spec.js +14 -14
  215. package/lib/test/client.applyMsg.spec.js.map +1 -1
  216. package/lib/test/client.getPosition.spec.js +1 -1
  217. package/lib/test/client.getPosition.spec.js.map +1 -1
  218. package/lib/test/client.localReference.spec.js +1 -1
  219. package/lib/test/client.localReference.spec.js.map +1 -1
  220. package/lib/test/client.rollback.spec.js +50 -59
  221. package/lib/test/client.rollback.spec.js.map +1 -1
  222. package/lib/test/client.rollbackFarm.spec.js +1 -1
  223. package/lib/test/client.rollbackFarm.spec.js.map +1 -1
  224. package/lib/test/client.searchForMarker.spec.js +4 -21
  225. package/lib/test/client.searchForMarker.spec.js.map +1 -1
  226. package/lib/test/index.d.ts +2 -2
  227. package/lib/test/index.d.ts.map +1 -1
  228. package/lib/test/index.js +1 -1
  229. package/lib/test/index.js.map +1 -1
  230. package/lib/test/mergeTree.annotate.deltaCallback.spec.js +15 -60
  231. package/lib/test/mergeTree.annotate.deltaCallback.spec.js.map +1 -1
  232. package/lib/test/mergeTree.annotate.spec.js +48 -64
  233. package/lib/test/mergeTree.annotate.spec.js.map +1 -1
  234. package/lib/test/mergeTree.insert.deltaCallback.spec.js +10 -63
  235. package/lib/test/mergeTree.insert.deltaCallback.spec.js.map +1 -1
  236. package/lib/test/mergeTree.insertingWalk.spec.js +61 -127
  237. package/lib/test/mergeTree.insertingWalk.spec.js.map +1 -1
  238. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +13 -94
  239. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  240. package/lib/test/mergeTree.markRangeRemoved.spec.js +10 -7
  241. package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  242. package/lib/test/mergeTree.walk.spec.js +2 -14
  243. package/lib/test/mergeTree.walk.spec.js.map +1 -1
  244. package/lib/test/mergeTreeOperationRunner.js +3 -3
  245. package/lib/test/mergeTreeOperationRunner.js.map +1 -1
  246. package/lib/test/obliterate.concurrent.spec.js +18 -23
  247. package/lib/test/obliterate.concurrent.spec.js.map +1 -1
  248. package/lib/test/obliterate.partialLength.spec.js +167 -137
  249. package/lib/test/obliterate.partialLength.spec.js.map +1 -1
  250. package/lib/test/obliterate.spec.js +17 -127
  251. package/lib/test/obliterate.spec.js.map +1 -1
  252. package/lib/test/partialLength.spec.js +29 -197
  253. package/lib/test/partialLength.spec.js.map +1 -1
  254. package/lib/test/perspective.spec.js +34 -0
  255. package/lib/test/perspective.spec.js.map +1 -1
  256. package/lib/test/propertyManager.spec.js +2 -2
  257. package/lib/test/propertyManager.spec.js.map +1 -1
  258. package/lib/test/resetPendingSegmentsToOp.spec.js +0 -2
  259. package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  260. package/lib/test/segmentGroupCollection.spec.js +10 -4
  261. package/lib/test/segmentGroupCollection.spec.js.map +1 -1
  262. package/lib/test/testClient.d.ts +1 -0
  263. package/lib/test/testClient.d.ts.map +1 -1
  264. package/lib/test/testClient.js +18 -28
  265. package/lib/test/testClient.js.map +1 -1
  266. package/lib/test/testClientLogger.d.ts.map +1 -1
  267. package/lib/test/testClientLogger.js +3 -10
  268. package/lib/test/testClientLogger.js.map +1 -1
  269. package/lib/test/testServer.d.ts +2 -1
  270. package/lib/test/testServer.d.ts.map +1 -1
  271. package/lib/test/testServer.js +7 -5
  272. package/lib/test/testServer.js.map +1 -1
  273. package/lib/test/testUtils.d.ts +36 -56
  274. package/lib/test/testUtils.d.ts.map +1 -1
  275. package/lib/test/testUtils.js +66 -48
  276. package/lib/test/testUtils.js.map +1 -1
  277. package/lib/test/text.d.ts +2 -2
  278. package/lib/test/text.d.ts.map +1 -1
  279. package/lib/test/text.js +6 -3
  280. package/lib/test/text.js.map +1 -1
  281. package/lib/textSegment.d.ts +0 -6
  282. package/lib/textSegment.d.ts.map +1 -1
  283. package/lib/textSegment.js.map +1 -1
  284. package/lib/tsdoc-metadata.json +1 -1
  285. package/lib/zamboni.d.ts.map +1 -1
  286. package/lib/zamboni.js +32 -28
  287. package/lib/zamboni.js.map +1 -1
  288. package/package.json +17 -20
  289. package/src/MergeTreeTextHelper.ts +17 -12
  290. package/src/client.ts +141 -197
  291. package/src/endOfTreeSegment.ts +11 -8
  292. package/src/index.ts +4 -3
  293. package/src/mergeTree.ts +482 -633
  294. package/src/mergeTreeDeltaCallback.ts +4 -8
  295. package/src/mergeTreeNodes.ts +66 -45
  296. package/src/partialLengths.ts +181 -137
  297. package/src/perspective.ts +17 -95
  298. package/src/revertibles.ts +2 -7
  299. package/src/segmentInfos.ts +48 -141
  300. package/src/segmentPropertiesManager.ts +2 -16
  301. package/src/snapshotLoader.ts +62 -30
  302. package/src/snapshotV1.ts +36 -28
  303. package/src/snapshotlegacy.ts +7 -16
  304. package/src/stamps.ts +1 -1
  305. package/src/textSegment.ts +0 -13
  306. package/src/zamboni.ts +38 -32
  307. package/tsconfig.json +1 -0
  308. package/prettier.config.cjs +0 -8
@@ -5,7 +5,6 @@
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const node_assert_1 = require("node:assert");
8
- const constants_js_1 = require("../constants.js");
9
8
  const mergeTree_js_1 = require("../mergeTree.js");
10
9
  const mergeTreeDeltaCallback_js_1 = require("../mergeTreeDeltaCallback.js");
11
10
  const ops_js_1 = require("../ops.js");
@@ -17,15 +16,7 @@ describe("MergeTree", () => {
17
16
  let currentSequenceNumber;
18
17
  beforeEach(() => {
19
18
  mergeTree = new mergeTree_js_1.MergeTree();
20
- (0, testUtils_js_1.insertSegments)({
21
- mergeTree,
22
- pos: 0,
23
- segments: [textSegment_js_1.TextSegment.make("hello world!")],
24
- refSeq: constants_js_1.UniversalSequenceNumber,
25
- clientId: constants_js_1.LocalClientId,
26
- seq: constants_js_1.UniversalSequenceNumber,
27
- opArgs: undefined,
28
- });
19
+ mergeTree.insertSegments(0, [textSegment_js_1.TextSegment.make("hello world!")], mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
29
20
  currentSequenceNumber = 0;
30
21
  mergeTree.startCollaboration(localClientId,
31
22
  /* minSeq: */ currentSequenceNumber,
@@ -34,16 +25,7 @@ describe("MergeTree", () => {
34
25
  describe("markRangeRemoved", () => {
35
26
  it("Event on Removal", () => {
36
27
  const count = (0, testUtils_js_1.countOperations)(mergeTree);
37
- (0, testUtils_js_1.markRangeRemoved)({
38
- mergeTree,
39
- start: 4,
40
- end: 6,
41
- refSeq: currentSequenceNumber,
42
- clientId: localClientId,
43
- seq: constants_js_1.UnassignedSequenceNumber,
44
- overwrite: false,
45
- opArgs: undefined,
46
- });
28
+ mergeTree.markRangeRemoved(4, 6, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
47
29
  node_assert_1.strict.deepStrictEqual(count, {
48
30
  [ops_js_1.MergeTreeDeltaType.REMOVE]: 1,
49
31
  [mergeTreeDeltaCallback_js_1.MergeTreeMaintenanceType.SPLIT]: 2,
@@ -54,16 +36,7 @@ describe("MergeTree", () => {
54
36
  const count = (0, testUtils_js_1.countOperations)(mergeTree);
55
37
  const start = 4;
56
38
  const end = 6;
57
- (0, testUtils_js_1.markRangeRemoved)({
58
- mergeTree,
59
- start,
60
- end,
61
- refSeq: currentSequenceNumber,
62
- clientId: localClientId,
63
- seq: constants_js_1.UnassignedSequenceNumber,
64
- overwrite: false,
65
- opArgs: undefined,
66
- });
39
+ mergeTree.markRangeRemoved(start, end, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
67
40
  // In order for the removed segment to unlinked by zamboni, we need to ACK the segment
68
41
  // and advance the collaboration window's minSeq past the removedSeq.
69
42
  mergeTree.ackPendingSegment({
@@ -87,87 +60,33 @@ describe("MergeTree", () => {
87
60
  });
88
61
  });
89
62
  it("Remote Before Local", () => {
90
- const remoteClientId = 35;
63
+ const remoteClient = (0, testUtils_js_1.makeRemoteClient)({ clientId: 35 });
91
64
  let remoteSequenceNumber = currentSequenceNumber;
92
- (0, testUtils_js_1.markRangeRemoved)({
93
- mergeTree,
94
- start: 4,
95
- end: 6,
96
- refSeq: remoteSequenceNumber,
97
- clientId: remoteClientId,
98
- seq: ++remoteSequenceNumber,
99
- overwrite: false,
100
- opArgs: undefined,
101
- });
65
+ mergeTree.markRangeRemoved(4, 6, remoteClient.perspectiveAt({ refSeq: remoteSequenceNumber }), remoteClient.stampAt({ seq: ++remoteSequenceNumber }), undefined);
102
66
  const count = (0, testUtils_js_1.countOperations)(mergeTree);
103
- (0, testUtils_js_1.markRangeRemoved)({
104
- mergeTree,
105
- start: 3,
106
- end: 5,
107
- refSeq: currentSequenceNumber,
108
- clientId: localClientId,
109
- seq: constants_js_1.UnassignedSequenceNumber,
110
- overwrite: false,
111
- opArgs: undefined,
112
- });
67
+ mergeTree.markRangeRemoved(3, 5, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
113
68
  node_assert_1.strict.deepStrictEqual(count, {
114
69
  [ops_js_1.MergeTreeDeltaType.REMOVE]: 1,
115
70
  [mergeTreeDeltaCallback_js_1.MergeTreeMaintenanceType.SPLIT]: 2,
116
71
  });
117
72
  });
118
73
  it("Local Before Remote", () => {
119
- const remoteClientId = 35;
74
+ const remoteClient = (0, testUtils_js_1.makeRemoteClient)({ clientId: 35 });
120
75
  let remoteSequenceNumber = currentSequenceNumber;
121
- (0, testUtils_js_1.markRangeRemoved)({
122
- mergeTree,
123
- start: 4,
124
- end: 6,
125
- refSeq: currentSequenceNumber,
126
- clientId: localClientId,
127
- seq: constants_js_1.UnassignedSequenceNumber,
128
- overwrite: false,
129
- opArgs: undefined,
130
- });
76
+ mergeTree.markRangeRemoved(4, 6, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
131
77
  const count = (0, testUtils_js_1.countOperations)(mergeTree);
132
- (0, testUtils_js_1.markRangeRemoved)({
133
- mergeTree,
134
- start: 3,
135
- end: 5,
136
- refSeq: remoteSequenceNumber,
137
- clientId: remoteClientId,
138
- seq: ++remoteSequenceNumber,
139
- overwrite: false,
140
- opArgs: undefined,
141
- });
78
+ mergeTree.markRangeRemoved(3, 5, remoteClient.perspectiveAt({ refSeq: remoteSequenceNumber }), remoteClient.stampAt({ seq: ++remoteSequenceNumber }), undefined);
142
79
  node_assert_1.strict.deepStrictEqual(count, {
143
80
  [ops_js_1.MergeTreeDeltaType.REMOVE]: 1,
144
81
  [mergeTreeDeltaCallback_js_1.MergeTreeMaintenanceType.SPLIT]: 2,
145
82
  });
146
83
  });
147
84
  it("Local delete shadows remote", () => {
148
- const remoteClientId = 35;
85
+ const remoteClient = (0, testUtils_js_1.makeRemoteClient)({ clientId: 35 });
149
86
  let remoteSequenceNumber = currentSequenceNumber;
150
- (0, testUtils_js_1.markRangeRemoved)({
151
- mergeTree,
152
- start: 3,
153
- end: 6,
154
- refSeq: currentSequenceNumber,
155
- clientId: localClientId,
156
- seq: constants_js_1.UnassignedSequenceNumber,
157
- overwrite: false,
158
- opArgs: undefined,
159
- });
87
+ mergeTree.markRangeRemoved(3, 6, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
160
88
  const count = (0, testUtils_js_1.countOperations)(mergeTree);
161
- (0, testUtils_js_1.markRangeRemoved)({
162
- mergeTree,
163
- start: 4,
164
- end: 5,
165
- refSeq: remoteSequenceNumber,
166
- clientId: remoteClientId,
167
- seq: ++remoteSequenceNumber,
168
- overwrite: false,
169
- opArgs: undefined,
170
- });
89
+ mergeTree.markRangeRemoved(4, 5, remoteClient.perspectiveAt({ refSeq: remoteSequenceNumber }), remoteClient.stampAt({ seq: ++remoteSequenceNumber }), undefined);
171
90
  node_assert_1.strict.deepStrictEqual(count, {
172
91
  /* MergeTreeDeltaType.REMOVE is absent as it should not be fired. */
173
92
  [mergeTreeDeltaCallback_js_1.MergeTreeMaintenanceType.SPLIT]: 2,
@@ -1 +1 @@
1
- {"version":3,"file":"mergeTree.markRangeRemoved.deltaCallback.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.markRangeRemoved.deltaCallback.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 { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport {\n\tLocalClientId,\n\tUnassignedSequenceNumber,\n\tUniversalSequenceNumber,\n} from \"../constants.js\";\nimport { MergeTree } from \"../mergeTree.js\";\nimport { MergeTreeMaintenanceType } from \"../mergeTreeDeltaCallback.js\";\nimport { MergeTreeDeltaType } from \"../ops.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { countOperations, insertSegments, markRangeRemoved } from \"./testUtils.js\";\n\ndescribe(\"MergeTree\", () => {\n\tlet mergeTree: MergeTree;\n\tconst localClientId = 17;\n\tlet currentSequenceNumber: number;\n\tbeforeEach(() => {\n\t\tmergeTree = new MergeTree();\n\t\tinsertSegments({\n\t\t\tmergeTree,\n\t\t\tpos: 0,\n\t\t\tsegments: [TextSegment.make(\"hello world!\")],\n\t\t\trefSeq: UniversalSequenceNumber,\n\t\t\tclientId: LocalClientId,\n\t\t\tseq: UniversalSequenceNumber,\n\t\t\topArgs: undefined,\n\t\t});\n\t\tcurrentSequenceNumber = 0;\n\t\tmergeTree.startCollaboration(\n\t\t\tlocalClientId,\n\t\t\t/* minSeq: */ currentSequenceNumber,\n\t\t\t/* currentSeq: */ currentSequenceNumber,\n\t\t);\n\t});\n\n\tdescribe(\"markRangeRemoved\", () => {\n\t\tit(\"Event on Removal\", () => {\n\t\t\tconst count = countOperations(mergeTree);\n\n\t\t\tmarkRangeRemoved({\n\t\t\t\tmergeTree,\n\t\t\t\tstart: 4,\n\t\t\t\tend: 6,\n\t\t\t\trefSeq: currentSequenceNumber,\n\t\t\t\tclientId: localClientId,\n\t\t\t\tseq: UnassignedSequenceNumber,\n\t\t\t\toverwrite: false,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\tassert.deepStrictEqual(count, {\n\t\t\t\t[MergeTreeDeltaType.REMOVE]: 1,\n\t\t\t\t[MergeTreeMaintenanceType.SPLIT]: 2,\n\t\t\t});\n\t\t});\n\n\t\t// Verify that zamboni unlinks a removed segment and raises the appropriate maintenance event.\n\t\tit(\"Event on Unlink\", () => {\n\t\t\tconst count = countOperations(mergeTree);\n\n\t\t\tconst start = 4;\n\t\t\tconst end = 6;\n\n\t\t\tmarkRangeRemoved({\n\t\t\t\tmergeTree,\n\t\t\t\tstart,\n\t\t\t\tend,\n\t\t\t\trefSeq: currentSequenceNumber,\n\t\t\t\tclientId: localClientId,\n\t\t\t\tseq: UnassignedSequenceNumber,\n\t\t\t\toverwrite: false,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\t// In order for the removed segment to unlinked by zamboni, we need to ACK the segment\n\t\t\t// and advance the collaboration window's minSeq past the removedSeq.\n\t\t\tmergeTree.ackPendingSegment({\n\t\t\t\top: {\n\t\t\t\t\tpos1: start,\n\t\t\t\t\tpos2: end,\n\t\t\t\t\ttype: MergeTreeDeltaType.REMOVE,\n\t\t\t\t},\n\t\t\t\tsequencedMessage: {\n\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t});\n\n\t\t\t// Move currentSeq/minSeq past the seq# at which the removal was ACKed.\n\t\t\tmergeTree.collabWindow.currentSeq = currentSequenceNumber;\n\t\t\tmergeTree.setMinSeq(currentSequenceNumber);\n\n\t\t\tassert.deepStrictEqual(count, {\n\t\t\t\t[MergeTreeDeltaType.REMOVE]: 1,\n\t\t\t\t[MergeTreeMaintenanceType.SPLIT]: 2,\n\t\t\t\t[MergeTreeMaintenanceType.UNLINK]: 1,\n\t\t\t\t[MergeTreeMaintenanceType.ACKNOWLEDGED]: 1,\n\t\t\t});\n\t\t});\n\n\t\tit(\"Remote Before Local\", () => {\n\t\t\tconst remoteClientId: number = 35;\n\t\t\tlet remoteSequenceNumber = currentSequenceNumber;\n\n\t\t\tmarkRangeRemoved({\n\t\t\t\tmergeTree,\n\t\t\t\tstart: 4,\n\t\t\t\tend: 6,\n\t\t\t\trefSeq: remoteSequenceNumber,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: ++remoteSequenceNumber,\n\t\t\t\toverwrite: false,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\tconst count = countOperations(mergeTree);\n\n\t\t\tmarkRangeRemoved({\n\t\t\t\tmergeTree,\n\t\t\t\tstart: 3,\n\t\t\t\tend: 5,\n\t\t\t\trefSeq: currentSequenceNumber,\n\t\t\t\tclientId: localClientId,\n\t\t\t\tseq: UnassignedSequenceNumber,\n\t\t\t\toverwrite: false,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\tassert.deepStrictEqual(count, {\n\t\t\t\t[MergeTreeDeltaType.REMOVE]: 1,\n\t\t\t\t[MergeTreeMaintenanceType.SPLIT]: 2,\n\t\t\t});\n\t\t});\n\n\t\tit(\"Local Before Remote\", () => {\n\t\t\tconst remoteClientId: number = 35;\n\t\t\tlet remoteSequenceNumber = currentSequenceNumber;\n\n\t\t\tmarkRangeRemoved({\n\t\t\t\tmergeTree,\n\t\t\t\tstart: 4,\n\t\t\t\tend: 6,\n\t\t\t\trefSeq: currentSequenceNumber,\n\t\t\t\tclientId: localClientId,\n\t\t\t\tseq: UnassignedSequenceNumber,\n\t\t\t\toverwrite: false,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\tconst count = countOperations(mergeTree);\n\n\t\t\tmarkRangeRemoved({\n\t\t\t\tmergeTree,\n\t\t\t\tstart: 3,\n\t\t\t\tend: 5,\n\t\t\t\trefSeq: remoteSequenceNumber,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: ++remoteSequenceNumber,\n\t\t\t\toverwrite: false,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\tassert.deepStrictEqual(count, {\n\t\t\t\t[MergeTreeDeltaType.REMOVE]: 1,\n\t\t\t\t[MergeTreeMaintenanceType.SPLIT]: 2,\n\t\t\t});\n\t\t});\n\n\t\tit(\"Local delete shadows remote\", () => {\n\t\t\tconst remoteClientId: number = 35;\n\t\t\tlet remoteSequenceNumber = currentSequenceNumber;\n\n\t\t\tmarkRangeRemoved({\n\t\t\t\tmergeTree,\n\t\t\t\tstart: 3,\n\t\t\t\tend: 6,\n\t\t\t\trefSeq: currentSequenceNumber,\n\t\t\t\tclientId: localClientId,\n\t\t\t\tseq: UnassignedSequenceNumber,\n\t\t\t\toverwrite: false,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\tconst count = countOperations(mergeTree);\n\n\t\t\tmarkRangeRemoved({\n\t\t\t\tmergeTree,\n\t\t\t\tstart: 4,\n\t\t\t\tend: 5,\n\t\t\t\trefSeq: remoteSequenceNumber,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: ++remoteSequenceNumber,\n\t\t\t\toverwrite: false,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\tassert.deepStrictEqual(count, {\n\t\t\t\t/* MergeTreeDeltaType.REMOVE is absent as it should not be fired. */\n\t\t\t\t[MergeTreeMaintenanceType.SPLIT]: 2,\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"mergeTree.markRangeRemoved.deltaCallback.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.markRangeRemoved.deltaCallback.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 { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport { MergeTree } from \"../mergeTree.js\";\nimport { MergeTreeMaintenanceType } from \"../mergeTreeDeltaCallback.js\";\nimport { MergeTreeDeltaType } from \"../ops.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { countOperations, makeRemoteClient } from \"./testUtils.js\";\n\ndescribe(\"MergeTree\", () => {\n\tlet mergeTree: MergeTree;\n\tconst localClientId = 17;\n\tlet currentSequenceNumber: number;\n\tbeforeEach(() => {\n\t\tmergeTree = new MergeTree();\n\t\tmergeTree.insertSegments(\n\t\t\t0,\n\t\t\t[TextSegment.make(\"hello world!\")],\n\t\t\tmergeTree.localPerspective,\n\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\tundefined,\n\t\t);\n\n\t\tcurrentSequenceNumber = 0;\n\t\tmergeTree.startCollaboration(\n\t\t\tlocalClientId,\n\t\t\t/* minSeq: */ currentSequenceNumber,\n\t\t\t/* currentSeq: */ currentSequenceNumber,\n\t\t);\n\t});\n\n\tdescribe(\"markRangeRemoved\", () => {\n\t\tit(\"Event on Removal\", () => {\n\t\t\tconst count = countOperations(mergeTree);\n\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t4,\n\t\t\t\t6,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tassert.deepStrictEqual(count, {\n\t\t\t\t[MergeTreeDeltaType.REMOVE]: 1,\n\t\t\t\t[MergeTreeMaintenanceType.SPLIT]: 2,\n\t\t\t});\n\t\t});\n\n\t\t// Verify that zamboni unlinks a removed segment and raises the appropriate maintenance event.\n\t\tit(\"Event on Unlink\", () => {\n\t\t\tconst count = countOperations(mergeTree);\n\n\t\t\tconst start = 4;\n\t\t\tconst end = 6;\n\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\tstart,\n\t\t\t\tend,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\t// In order for the removed segment to unlinked by zamboni, we need to ACK the segment\n\t\t\t// and advance the collaboration window's minSeq past the removedSeq.\n\t\t\tmergeTree.ackPendingSegment({\n\t\t\t\top: {\n\t\t\t\t\tpos1: start,\n\t\t\t\t\tpos2: end,\n\t\t\t\t\ttype: MergeTreeDeltaType.REMOVE,\n\t\t\t\t},\n\t\t\t\tsequencedMessage: {\n\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t});\n\n\t\t\t// Move currentSeq/minSeq past the seq# at which the removal was ACKed.\n\t\t\tmergeTree.collabWindow.currentSeq = currentSequenceNumber;\n\t\t\tmergeTree.setMinSeq(currentSequenceNumber);\n\n\t\t\tassert.deepStrictEqual(count, {\n\t\t\t\t[MergeTreeDeltaType.REMOVE]: 1,\n\t\t\t\t[MergeTreeMaintenanceType.SPLIT]: 2,\n\t\t\t\t[MergeTreeMaintenanceType.UNLINK]: 1,\n\t\t\t\t[MergeTreeMaintenanceType.ACKNOWLEDGED]: 1,\n\t\t\t});\n\t\t});\n\n\t\tit(\"Remote Before Local\", () => {\n\t\t\tconst remoteClient = makeRemoteClient({ clientId: 35 });\n\t\t\tlet remoteSequenceNumber = currentSequenceNumber;\n\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t4,\n\t\t\t\t6,\n\t\t\t\tremoteClient.perspectiveAt({ refSeq: remoteSequenceNumber }),\n\t\t\t\tremoteClient.stampAt({ seq: ++remoteSequenceNumber }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tconst count = countOperations(mergeTree);\n\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t3,\n\t\t\t\t5,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tassert.deepStrictEqual(count, {\n\t\t\t\t[MergeTreeDeltaType.REMOVE]: 1,\n\t\t\t\t[MergeTreeMaintenanceType.SPLIT]: 2,\n\t\t\t});\n\t\t});\n\n\t\tit(\"Local Before Remote\", () => {\n\t\t\tconst remoteClient = makeRemoteClient({ clientId: 35 });\n\t\t\tlet remoteSequenceNumber = currentSequenceNumber;\n\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t4,\n\t\t\t\t6,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tconst count = countOperations(mergeTree);\n\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t3,\n\t\t\t\t5,\n\t\t\t\tremoteClient.perspectiveAt({ refSeq: remoteSequenceNumber }),\n\t\t\t\tremoteClient.stampAt({ seq: ++remoteSequenceNumber }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tassert.deepStrictEqual(count, {\n\t\t\t\t[MergeTreeDeltaType.REMOVE]: 1,\n\t\t\t\t[MergeTreeMaintenanceType.SPLIT]: 2,\n\t\t\t});\n\t\t});\n\n\t\tit(\"Local delete shadows remote\", () => {\n\t\t\tconst remoteClient = makeRemoteClient({ clientId: 35 });\n\t\t\tlet remoteSequenceNumber = currentSequenceNumber;\n\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t3,\n\t\t\t\t6,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tconst count = countOperations(mergeTree);\n\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t4,\n\t\t\t\t5,\n\t\t\t\tremoteClient.perspectiveAt({ refSeq: remoteSequenceNumber }),\n\t\t\t\tremoteClient.stampAt({ seq: ++remoteSequenceNumber }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tassert.deepStrictEqual(count, {\n\t\t\t\t/* MergeTreeDeltaType.REMOVE is absent as it should not be fired. */\n\t\t\t\t[MergeTreeMaintenanceType.SPLIT]: 2,\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
@@ -55,19 +55,22 @@ describe("MergeTree.markRangeRemoved", () => {
55
55
  const localDeleteMessage = client.makeOpMessage(client.removeRangeLocal(0, client.getLength()), ++seq, originalSeq /* refSeq */);
56
56
  node_assert_1.strict.equal(client.getText(), "");
57
57
  (0, segmentInfos_js_1.assertRemoved)(segment);
58
- node_assert_1.strict.equal(segment.removedSeq, constants_js_1.UnassignedSequenceNumber);
59
- (0, node_assert_1.strict)(segment.localRemovedSeq !== undefined);
60
- const expectedLocalRemovedSeq = segment.localRemovedSeq;
58
+ const localRemoveInfo = segment.removes[0];
59
+ node_assert_1.strict.equal(localRemoveInfo.seq, constants_js_1.UnassignedSequenceNumber);
60
+ (0, node_assert_1.strict)(localRemoveInfo.localSeq !== undefined);
61
61
  client.applyMsg(remoteDeleteMessage);
62
- node_assert_1.strict.equal(segment.removedSeq, segmentExpectedRemovedSeq);
63
- node_assert_1.strict.equal(segment.localRemovedSeq, expectedLocalRemovedSeq);
62
+ const remoteRemoveInfo = segment.removes[0];
63
+ node_assert_1.strict.deepEqual(segment.removes[1], localRemoveInfo);
64
+ node_assert_1.strict.equal(remoteRemoveInfo.seq, segmentExpectedRemovedSeq);
64
65
  node_assert_1.strict.equal(client.getText(), "");
65
66
  // localRemovedSeq should remain on the segment until the local removal has been acked.
66
67
  // This ensures there's enough information to determine segment length in the case of
67
68
  // reconnect.
68
69
  client.applyMsg(localDeleteMessage);
69
- node_assert_1.strict.equal(segment.removedSeq, segmentExpectedRemovedSeq);
70
- node_assert_1.strict.equal(segment.localRemovedSeq, undefined);
70
+ const finalRemoveInfo = segment.removes[0];
71
+ node_assert_1.strict.equal(segment.removes.length, 2);
72
+ node_assert_1.strict.equal(finalRemoveInfo.seq, segmentExpectedRemovedSeq);
73
+ node_assert_1.strict.equal(finalRemoveInfo.localSeq, undefined);
71
74
  node_assert_1.strict.equal(client.getText(), "");
72
75
  });
73
76
  it("remote remove followed by remote insert", () => {
@@ -1 +1 @@
1
- {"version":3,"file":"mergeTree.markRangeRemoved.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.markRangeRemoved.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { UnassignedSequenceNumber } from \"../constants.js\";\nimport type { ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { createInsertSegmentOp, createRemoveRangeOp } from \"../opBuilder.js\";\nimport { assertRemoved } from \"../segmentInfos.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\n\ndescribe(\"MergeTree.markRangeRemoved\", () => {\n\tlet client: TestClient;\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\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});\n\n\tit(\"local remove followed by local insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local insert followed by local remove\", () => {\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"texthello world\");\n\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by local insert\", () => {\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote overlapping remove\", () => {\n\t\tconst originalSeq = client.getCurrentSeq();\n\t\tlet seq = originalSeq;\n\t\tconst remoteDeleteMessage = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t++seq,\n\t\t\tundefined,\n\t\t\t\"remote\",\n\t\t);\n\t\tconst segmentExpectedRemovedSeq = seq;\n\t\tconst { segment } = client.getContainingSegment<ISegmentPrivate>(0);\n\t\tassert(segment !== undefined, \"expected to find segment\");\n\t\tconst localDeleteMessage = client.makeOpMessage(\n\t\t\tclient.removeRangeLocal(0, client.getLength()),\n\t\t\t++seq,\n\t\t\toriginalSeq /* refSeq */,\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\t\tassertRemoved(segment);\n\t\tassert.equal(segment.removedSeq, UnassignedSequenceNumber);\n\t\tassert(segment.localRemovedSeq !== undefined);\n\t\tconst expectedLocalRemovedSeq = segment.localRemovedSeq;\n\n\t\tclient.applyMsg(remoteDeleteMessage);\n\t\tassert.equal(segment.removedSeq, segmentExpectedRemovedSeq);\n\t\tassert.equal(segment.localRemovedSeq, expectedLocalRemovedSeq);\n\t\tassert.equal(client.getText(), \"\");\n\n\t\t// localRemovedSeq should remain on the segment until the local removal has been acked.\n\t\t// This ensures there's enough information to determine segment length in the case of\n\t\t// reconnect.\n\t\tclient.applyMsg(localDeleteMessage);\n\t\tassert.equal(segment.removedSeq, segmentExpectedRemovedSeq);\n\t\tassert.equal(segment.localRemovedSeq, undefined);\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by remote insert\", () => {\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tclient.applyMsg(removeMsg);\n\t\tclient.applyMsg(insertMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"remote insert followed by remote remove\", () => {\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tclient.applyMsg(insertMsg);\n\t\tclient.applyMsg(removeMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local and remote clients race to insert at position of removed segment\", () => {\n\t\t// Note: This test constructs its own TestClients to avoid being initialized with \"hello world\".\n\n\t\t// First we run through the ops from the perspective of a passive observer (i.e., all operations are remote).\n\t\tconst expected = new TestClient();\n\t\texpected.startOrUpdateCollaboration(\"3\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"a\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"1\",\n\t\t\t);\n\t\t\texpected.removeRangeRemote(0, 1, ++seq, /* refSeq: */ 0, /* longClientId: */ \"1\");\n\t\t\tconst refSeqAt2 = expected.getCurrentSeq();\n\n\t\t\t// In parallel, Client 2 inserted \"x\" without knowledge of Client 1's insertion/removal.\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Client 1 inserts \"c\" having received acks for its own edits, but has not yet having\n\t\t\t// observed the insertion of \"X\" from client 2.\n\t\t\texpected.insertTextRemote(0, \"c\", undefined, ++seq, refSeqAt2, /* longClientId: */ \"1\");\n\t\t}\n\n\t\t// Next, we run through the same sequence from the perspective of client 1:\n\t\tconst actual = new TestClient();\n\t\tactual.startOrUpdateCollaboration(\"1\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\tconst op1 = actual.insertTextLocal(0, \"a\")!;\n\t\t\tconst op2 = actual.removeRangeLocal(0, 1);\n\n\t\t\t// Client 1 receives ACKs for op1 and op2.\n\t\t\tactual.applyMsg(actual.makeOpMessage(op1, ++seq, /* refSeq: */ 0));\n\t\t\tactual.applyMsg(actual.makeOpMessage(op2, ++seq, /* refSeq: */ 0));\n\t\t\tconst refSeqAt2 = actual.getCurrentSeq();\n\n\t\t\t// Client 1 locally inserts \"c\".\n\t\t\tconst op4 = actual.insertTextLocal(0, \"c\");\n\n\t\t\t// Client 1 then processes the parallel insertion of \"X\" from Client 2 at refSeq=0\n\t\t\tactual.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Finally, client 1 receives the ack for its insertion of \"c\".\n\t\t\tactual.applyMsg(actual.makeOpMessage(op4, ++seq, refSeqAt2));\n\t\t}\n\n\t\tassert.equal(actual.getText(), expected.getText());\n\t});\n});\n"]}
1
+ {"version":3,"file":"mergeTree.markRangeRemoved.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.markRangeRemoved.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { UnassignedSequenceNumber } from \"../constants.js\";\nimport type { ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { createInsertSegmentOp, createRemoveRangeOp } from \"../opBuilder.js\";\nimport { assertRemoved } from \"../segmentInfos.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\n\ndescribe(\"MergeTree.markRangeRemoved\", () => {\n\tlet client: TestClient;\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\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});\n\n\tit(\"local remove followed by local insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local insert followed by local remove\", () => {\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"texthello world\");\n\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by local insert\", () => {\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote overlapping remove\", () => {\n\t\tconst originalSeq = client.getCurrentSeq();\n\t\tlet seq = originalSeq;\n\t\tconst remoteDeleteMessage = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t++seq,\n\t\t\tundefined,\n\t\t\t\"remote\",\n\t\t);\n\t\tconst segmentExpectedRemovedSeq = seq;\n\t\tconst { segment } = client.getContainingSegment<ISegmentPrivate>(0);\n\t\tassert(segment !== undefined, \"expected to find segment\");\n\t\tconst localDeleteMessage = client.makeOpMessage(\n\t\t\tclient.removeRangeLocal(0, client.getLength()),\n\t\t\t++seq,\n\t\t\toriginalSeq /* refSeq */,\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\t\tassertRemoved(segment);\n\t\tconst localRemoveInfo = segment.removes[0];\n\t\tassert.equal(localRemoveInfo.seq, UnassignedSequenceNumber);\n\t\tassert(localRemoveInfo.localSeq !== undefined);\n\n\t\tclient.applyMsg(remoteDeleteMessage);\n\t\tconst remoteRemoveInfo = segment.removes[0];\n\t\tassert.deepEqual(segment.removes[1], localRemoveInfo);\n\t\tassert.equal(remoteRemoveInfo.seq, segmentExpectedRemovedSeq);\n\t\tassert.equal(client.getText(), \"\");\n\n\t\t// localRemovedSeq should remain on the segment until the local removal has been acked.\n\t\t// This ensures there's enough information to determine segment length in the case of\n\t\t// reconnect.\n\t\tclient.applyMsg(localDeleteMessage);\n\t\tconst finalRemoveInfo = segment.removes[0];\n\t\tassert.equal(segment.removes.length, 2);\n\t\tassert.equal(finalRemoveInfo.seq, segmentExpectedRemovedSeq);\n\t\tassert.equal(finalRemoveInfo.localSeq, undefined);\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by remote insert\", () => {\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tclient.applyMsg(removeMsg);\n\t\tclient.applyMsg(insertMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"remote insert followed by remote remove\", () => {\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tclient.applyMsg(insertMsg);\n\t\tclient.applyMsg(removeMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local and remote clients race to insert at position of removed segment\", () => {\n\t\t// Note: This test constructs its own TestClients to avoid being initialized with \"hello world\".\n\n\t\t// First we run through the ops from the perspective of a passive observer (i.e., all operations are remote).\n\t\tconst expected = new TestClient();\n\t\texpected.startOrUpdateCollaboration(\"3\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"a\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"1\",\n\t\t\t);\n\t\t\texpected.removeRangeRemote(0, 1, ++seq, /* refSeq: */ 0, /* longClientId: */ \"1\");\n\t\t\tconst refSeqAt2 = expected.getCurrentSeq();\n\n\t\t\t// In parallel, Client 2 inserted \"x\" without knowledge of Client 1's insertion/removal.\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Client 1 inserts \"c\" having received acks for its own edits, but has not yet having\n\t\t\t// observed the insertion of \"X\" from client 2.\n\t\t\texpected.insertTextRemote(0, \"c\", undefined, ++seq, refSeqAt2, /* longClientId: */ \"1\");\n\t\t}\n\n\t\t// Next, we run through the same sequence from the perspective of client 1:\n\t\tconst actual = new TestClient();\n\t\tactual.startOrUpdateCollaboration(\"1\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\tconst op1 = actual.insertTextLocal(0, \"a\")!;\n\t\t\tconst op2 = actual.removeRangeLocal(0, 1);\n\n\t\t\t// Client 1 receives ACKs for op1 and op2.\n\t\t\tactual.applyMsg(actual.makeOpMessage(op1, ++seq, /* refSeq: */ 0));\n\t\t\tactual.applyMsg(actual.makeOpMessage(op2, ++seq, /* refSeq: */ 0));\n\t\t\tconst refSeqAt2 = actual.getCurrentSeq();\n\n\t\t\t// Client 1 locally inserts \"c\".\n\t\t\tconst op4 = actual.insertTextLocal(0, \"c\");\n\n\t\t\t// Client 1 then processes the parallel insertion of \"X\" from Client 2 at refSeq=0\n\t\t\tactual.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Finally, client 1 receives the ack for its insertion of \"c\".\n\t\t\tactual.applyMsg(actual.makeOpMessage(op4, ++seq, refSeqAt2));\n\t\t}\n\n\t\tassert.equal(actual.getText(), expected.getText());\n\t});\n});\n"]}
@@ -5,31 +5,19 @@
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const node_assert_1 = require("node:assert");
8
- const constants_js_1 = require("../constants.js");
9
8
  const mergeTree_js_1 = require("../mergeTree.js");
10
9
  const mergeTreeNodeWalk_js_1 = require("../mergeTreeNodeWalk.js");
11
10
  const mergeTreeNodes_js_1 = require("../mergeTreeNodes.js");
12
11
  const textSegment_js_1 = require("../textSegment.js");
13
- const testUtils_js_1 = require("./testUtils.js");
14
- const localClientId = 17;
15
12
  describe("MergeTree walks", () => {
16
13
  let mergeTree;
17
14
  beforeEach(() => {
18
15
  let initialText = "0";
19
16
  mergeTree = new mergeTree_js_1.MergeTree();
20
- mergeTree.insertSegments(0, [textSegment_js_1.TextSegment.make(initialText)], constants_js_1.UniversalSequenceNumber, constants_js_1.LocalClientId, constants_js_1.UniversalSequenceNumber, undefined);
17
+ mergeTree.insertSegments(0, [textSegment_js_1.TextSegment.make(initialText)], mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
21
18
  for (let i = 1; i < mergeTreeNodes_js_1.MaxNodesInBlock * mergeTreeNodes_js_1.MaxNodesInBlock; i++) {
22
19
  const text = i.toString();
23
- (0, testUtils_js_1.insertText)({
24
- mergeTree,
25
- pos: mergeTree.getLength(constants_js_1.UniversalSequenceNumber, localClientId),
26
- refSeq: constants_js_1.UniversalSequenceNumber,
27
- clientId: localClientId,
28
- seq: constants_js_1.UniversalSequenceNumber,
29
- text,
30
- props: undefined,
31
- opArgs: undefined,
32
- });
20
+ mergeTree.insertSegments(mergeTree.getLength(mergeTree.localPerspective), [textSegment_js_1.TextSegment.make(text)], mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
33
21
  initialText += text;
34
22
  }
35
23
  });
@@ -1 +1 @@
1
- {"version":3,"file":"mergeTree.walk.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.walk.spec.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAEH,6CAA+C;AAE/C,kDAAyE;AACzE,kDAA4C;AAC5C,kEAA+D;AAC/D,4DAAmE;AACnE,sDAAgD;AAEhD,iDAA4C;AAE5C,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAChC,IAAI,SAAoB,CAAC;IACzB,UAAU,CAAC,GAAG,EAAE;QACf,IAAI,WAAW,GAAG,GAAG,CAAC;QACtB,SAAS,GAAG,IAAI,wBAAS,EAAE,CAAC;QAC5B,SAAS,CAAC,cAAc,CACvB,CAAC,EACD,CAAC,4BAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,EAC/B,sCAAuB,EACvB,4BAAa,EACb,sCAAuB,EACvB,SAAS,CACT,CAAC;QACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,mCAAe,GAAG,mCAAe,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5D,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC1B,IAAA,yBAAU,EAAC;gBACV,SAAS;gBACT,GAAG,EAAE,SAAS,CAAC,SAAS,CAAC,sCAAuB,EAAE,aAAa,CAAC;gBAChE,MAAM,EAAE,sCAAuB;gBAC/B,QAAQ,EAAE,aAAa;gBACvB,GAAG,EAAE,sCAAuB;gBAC5B,IAAI;gBACJ,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,SAAS;aACjB,CAAC,CAAC;YACH,WAAW,IAAI,IAAI,CAAC;QACrB,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACrC,QAAQ,CAAC,CAAC,sBAAsB,CAAC,KAAiB;YACjD,MAAM,KAAK,CAAC;YACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAChC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBACrB,KAAK,CAAC,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;gBACtC,CAAC;YACF,CAAC;QACF,CAAC;QAED,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;YAClC,KAAK,MAAM,KAAK,IAAI,sBAAsB,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5D,IAAI,iBAAiB,GAAG,KAAK,CAAC;gBAC9B,IAAA,2CAAoB,EAAC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;oBACnC,iBAAiB,GAAG,IAAI,CAAC;oBACzB,IAAI,OAAO,GAA2B,GAAG,CAAC,MAAM,CAAC;oBACjD,OAAO,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;wBACnD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;oBAC1B,CAAC;oBACD,IAAA,oBAAM,EAAC,OAAO,KAAK,KAAK,EAAE,iDAAiD,CAAC,CAAC;oBAC7E,OAAO,IAAI,CAAC;gBACb,CAAC,CAAC,CAAC;gBACH,IAAA,oBAAM,EAAC,iBAAiB,EAAE,+BAA+B,CAAC,CAAC;YAC5D,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","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 { LocalClientId, UniversalSequenceNumber } from \"../constants.js\";\nimport { MergeTree } from \"../mergeTree.js\";\nimport { walkAllChildSegments } from \"../mergeTreeNodeWalk.js\";\nimport { MergeBlock, MaxNodesInBlock } from \"../mergeTreeNodes.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { insertText } from \"./testUtils.js\";\n\nconst localClientId = 17;\n\ndescribe(\"MergeTree walks\", () => {\n\tlet mergeTree: MergeTree;\n\tbeforeEach(() => {\n\t\tlet initialText = \"0\";\n\t\tmergeTree = new MergeTree();\n\t\tmergeTree.insertSegments(\n\t\t\t0,\n\t\t\t[TextSegment.make(initialText)],\n\t\t\tUniversalSequenceNumber,\n\t\t\tLocalClientId,\n\t\t\tUniversalSequenceNumber,\n\t\t\tundefined,\n\t\t);\n\t\tfor (let i = 1; i < MaxNodesInBlock * MaxNodesInBlock; i++) {\n\t\t\tconst text = i.toString();\n\t\t\tinsertText({\n\t\t\t\tmergeTree,\n\t\t\t\tpos: mergeTree.getLength(UniversalSequenceNumber, localClientId),\n\t\t\t\trefSeq: UniversalSequenceNumber,\n\t\t\t\tclientId: localClientId,\n\t\t\t\tseq: UniversalSequenceNumber,\n\t\t\t\ttext,\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: undefined,\n\t\t\t});\n\t\t\tinitialText += text;\n\t\t}\n\t});\n\n\tdescribe(\"walkAllChildSegments\", () => {\n\t\tfunction* getAllDescendantBlocks(block: MergeBlock): Iterable<MergeBlock> {\n\t\t\tyield block;\n\t\t\tfor (let i = 0; i < block.childCount; i++) {\n\t\t\t\tconst child = block.children[i];\n\t\t\t\tif (!child.isLeaf()) {\n\t\t\t\t\tyield* getAllDescendantBlocks(child);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tit(\"visits only descendants\", () => {\n\t\t\tfor (const block of getAllDescendantBlocks(mergeTree.root)) {\n\t\t\t\tlet walkedAnySegments = false;\n\t\t\t\twalkAllChildSegments(block, (seg) => {\n\t\t\t\t\twalkedAnySegments = true;\n\t\t\t\t\tlet current: MergeBlock | undefined = seg.parent;\n\t\t\t\t\twhile (current !== block && current !== undefined) {\n\t\t\t\t\t\tcurrent = current.parent;\n\t\t\t\t\t}\n\t\t\t\t\tassert(current === block, \"Expected all visited segments to be descendants\");\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\t\t\t\tassert(walkedAnySegments, \"Walk should have hit segments\");\n\t\t\t}\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"mergeTree.walk.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.walk.spec.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAEH,6CAA+C;AAE/C,kDAA4C;AAC5C,kEAA+D;AAC/D,4DAAmE;AACnE,sDAAgD;AAEhD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAChC,IAAI,SAAoB,CAAC;IACzB,UAAU,CAAC,GAAG,EAAE;QACf,IAAI,WAAW,GAAG,GAAG,CAAC;QACtB,SAAS,GAAG,IAAI,wBAAS,EAAE,CAAC;QAC5B,SAAS,CAAC,cAAc,CACvB,CAAC,EACD,CAAC,4BAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,EAC/B,SAAS,CAAC,gBAAgB,EAC1B,SAAS,CAAC,YAAY,CAAC,2BAA2B,EAAE,EACpD,SAAS,CACT,CAAC;QACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,mCAAe,GAAG,mCAAe,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5D,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC1B,SAAS,CAAC,cAAc,CACvB,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAC/C,CAAC,4BAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EACxB,SAAS,CAAC,gBAAgB,EAC1B,SAAS,CAAC,YAAY,CAAC,2BAA2B,EAAE,EACpD,SAAS,CACT,CAAC;YACF,WAAW,IAAI,IAAI,CAAC;QACrB,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACrC,QAAQ,CAAC,CAAC,sBAAsB,CAAC,KAAiB;YACjD,MAAM,KAAK,CAAC;YACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAChC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBACrB,KAAK,CAAC,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;gBACtC,CAAC;YACF,CAAC;QACF,CAAC;QAED,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;YAClC,KAAK,MAAM,KAAK,IAAI,sBAAsB,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5D,IAAI,iBAAiB,GAAG,KAAK,CAAC;gBAC9B,IAAA,2CAAoB,EAAC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;oBACnC,iBAAiB,GAAG,IAAI,CAAC;oBACzB,IAAI,OAAO,GAA2B,GAAG,CAAC,MAAM,CAAC;oBACjD,OAAO,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;wBACnD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;oBAC1B,CAAC;oBACD,IAAA,oBAAM,EAAC,OAAO,KAAK,KAAK,EAAE,iDAAiD,CAAC,CAAC;oBAC7E,OAAO,IAAI,CAAC;gBACb,CAAC,CAAC,CAAC;gBACH,IAAA,oBAAM,EAAC,iBAAiB,EAAE,+BAA+B,CAAC,CAAC;YAC5D,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","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 { MergeTree } from \"../mergeTree.js\";\nimport { walkAllChildSegments } from \"../mergeTreeNodeWalk.js\";\nimport { MergeBlock, MaxNodesInBlock } from \"../mergeTreeNodes.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\ndescribe(\"MergeTree walks\", () => {\n\tlet mergeTree: MergeTree;\n\tbeforeEach(() => {\n\t\tlet initialText = \"0\";\n\t\tmergeTree = new MergeTree();\n\t\tmergeTree.insertSegments(\n\t\t\t0,\n\t\t\t[TextSegment.make(initialText)],\n\t\t\tmergeTree.localPerspective,\n\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\tundefined,\n\t\t);\n\t\tfor (let i = 1; i < MaxNodesInBlock * MaxNodesInBlock; i++) {\n\t\t\tconst text = i.toString();\n\t\t\tmergeTree.insertSegments(\n\t\t\t\tmergeTree.getLength(mergeTree.localPerspective),\n\t\t\t\t[TextSegment.make(text)],\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\tinitialText += text;\n\t\t}\n\t});\n\n\tdescribe(\"walkAllChildSegments\", () => {\n\t\tfunction* getAllDescendantBlocks(block: MergeBlock): Iterable<MergeBlock> {\n\t\t\tyield block;\n\t\t\tfor (let i = 0; i < block.childCount; i++) {\n\t\t\t\tconst child = block.children[i];\n\t\t\t\tif (!child.isLeaf()) {\n\t\t\t\t\tyield* getAllDescendantBlocks(child);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tit(\"visits only descendants\", () => {\n\t\t\tfor (const block of getAllDescendantBlocks(mergeTree.root)) {\n\t\t\t\tlet walkedAnySegments = false;\n\t\t\t\twalkAllChildSegments(block, (seg) => {\n\t\t\t\t\twalkedAnySegments = true;\n\t\t\t\t\tlet current: MergeBlock | undefined = seg.parent;\n\t\t\t\t\twhile (current !== block && current !== undefined) {\n\t\t\t\t\t\tcurrent = current.parent;\n\t\t\t\t\t}\n\t\t\t\t\tassert(current === block, \"Expected all visited segments to be descendants\");\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\t\t\t\tassert(walkedAnySegments, \"Walk should have hit segments\");\n\t\t\t}\n\t\t});\n\t});\n});\n"]}
@@ -98,8 +98,8 @@ const insertAtRefPos = (client, opStart, opEnd, random) => {
98
98
  if (segs.length > 0) {
99
99
  const text = client.longClientId.repeat(random.integer(1, 3));
100
100
  const seg = random.pick(segs);
101
- const movedOrRemoved = (0, segmentInfos_js_1.toRemovalInfo)(seg) ?? (0, segmentInfos_js_1.toMoveInfo)(seg);
102
- const lref = client.createLocalReferencePosition(seg, movedOrRemoved ? 0 : random.integer(0, seg.cachedLength - 1), movedOrRemoved
101
+ const removed = (0, segmentInfos_js_1.toRemovalInfo)(seg);
102
+ const lref = client.createLocalReferencePosition(seg, removed ? 0 : random.integer(0, seg.cachedLength - 1), removed
103
103
  ? ops_js_1.ReferenceType.SlideOnRemove
104
104
  : random.pick([
105
105
  ops_js_1.ReferenceType.Simple,
@@ -1 +1 @@
1
- {"version":3,"file":"mergeTreeOperationRunner.js","sourceRoot":"","sources":["../../src/test/mergeTreeOperationRunner.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\";\nimport * as fs from \"node:fs\";\n\nimport { IRandom } from \"@fluid-private/stochastic-test-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport { walkAllChildSegments } from \"../mergeTreeNodeWalk.js\";\nimport { ISegmentPrivate, SegmentGroup } from \"../mergeTreeNodes.js\";\nimport { IMergeTreeOp, MergeTreeDeltaType, ReferenceType } from \"../ops.js\";\nimport { toMoveInfo, toRemovalInfo } from \"../segmentInfos.js\";\nimport { Side } from \"../sequencePlace.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { _dirname } from \"./dirname.cjs\";\nimport { TestClient } from \"./testClient.js\";\nimport { TestClientLogger } from \"./testClientLogger.js\";\n\nexport type TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => IMergeTreeOp[] | IMergeTreeOp | undefined;\n\nexport const removeRange: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n) => client.removeRangeLocal(opStart, opEnd);\n\nexport const obliterateRange: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n) => client.obliterateRangeLocal(opStart, opEnd);\n\nexport const obliterateRangeSided: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tlet startSide: Side;\n\tlet endSide: Side;\n\n\tconst oblEnd = random.integer(opStart, client.getLength() - 1);\n\t// TODO: to create zero length obliterate ops, change '<=' to '<'.\n\t// Doing so may cause different failures than those without zero length.\n\t// AB#19930\n\tif (oblEnd - opStart <= 1) {\n\t\tstartSide = Side.Before;\n\t\tendSide = Side.After;\n\t} else {\n\t\tstartSide = random.pick([Side.Before, Side.After]);\n\t\tendSide = random.pick([Side.Before, Side.After]);\n\t}\n\n\tconst start = { pos: opStart, side: startSide };\n\tconst end = { pos: oblEnd, side: endSide };\n\treturn client.obliterateRangeLocal(start, end);\n};\n\nexport const annotateRange: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tif (random.bool()) {\n\t\treturn client.annotateRangeLocal(opStart, opEnd, {\n\t\t\t[random.integer(1, 5)]: client.longClientId,\n\t\t});\n\t} else {\n\t\tconst max = random.pick([undefined, random.integer(-10, 100)]);\n\t\tconst min = random.pick([undefined, random.integer(-100, 10)]);\n\t\treturn client.annotateAdjustRangeLocal(opStart, opEnd, {\n\t\t\t[random.integer(0, 2).toString()]: {\n\t\t\t\tdelta: random.integer(-5, 5),\n\t\t\t\tmin: (min ?? max ?? 0) > (max ?? 0) ? undefined : min,\n\t\t\t\tmax,\n\t\t\t},\n\t\t});\n\t}\n};\n\nexport const insertAtRefPos: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tconst segs: ISegmentPrivate[] = [];\n\t// gather all the segments at the pos, including removed segments\n\twalkAllChildSegments(client.mergeTree.root, (seg) => {\n\t\tconst pos = client.getPosition(seg);\n\t\tif (pos >= opStart) {\n\t\t\tif (pos <= opStart) {\n\t\t\t\tsegs.push(seg);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t});\n\tif (segs.length > 0) {\n\t\tconst text = client.longClientId!.repeat(random.integer(1, 3));\n\t\tconst seg = random.pick(segs);\n\t\tconst movedOrRemoved = toRemovalInfo(seg) ?? toMoveInfo(seg);\n\t\tconst lref = client.createLocalReferencePosition(\n\t\t\tseg,\n\t\t\tmovedOrRemoved ? 0 : random.integer(0, seg.cachedLength - 1),\n\t\t\tmovedOrRemoved\n\t\t\t\t? ReferenceType.SlideOnRemove\n\t\t\t\t: random.pick([\n\t\t\t\t\t\tReferenceType.Simple,\n\t\t\t\t\t\tReferenceType.SlideOnRemove,\n\t\t\t\t\t\tReferenceType.Transient,\n\t\t\t\t\t]),\n\t\t\tundefined,\n\t\t);\n\n\t\treturn client.insertAtReferencePositionLocal(lref, TextSegment.make(text));\n\t}\n};\n\nexport const insert: TestOperation = (\n\tclient: TestClient,\n\t_start: number,\n\t_end: number,\n\trandom: IRandom,\n) => {\n\t// Note: the _start param is generated using exclusive range. This provides more coverage by allowing\n\t// insertion at the end.\n\tconst start = random.integer(0, client.getLength());\n\tconst text = client.longClientId!.repeat(random.integer(1, 3));\n\treturn client.insertTextLocal(start, text);\n};\n\nconst generateInsert = (client: TestClient, random: IRandom): IMergeTreeOp | undefined => {\n\tconst len = client.getLength();\n\tconst text = client.longClientId!.repeat(random.integer(1, 3));\n\treturn client.insertTextLocal(random.integer(0, len), text);\n};\n\nexport interface IConfigRange {\n\tmin: number;\n\tmax: number;\n\tgrowthFunc?: (input: number) => number;\n}\n\nexport function doOverRange(\n\trange: IConfigRange,\n\tdefaultGrowthFunc: (input: number) => number,\n\tdoAction: (current: number) => void,\n): void {\n\tlet lastCurrent = Number.NaN;\n\tfor (\n\t\tlet current = range.min;\n\t\tcurrent <= range.max;\n\t\tcurrent = (range.growthFunc ?? defaultGrowthFunc)(current)\n\t) {\n\t\t// let growth funcs be simple\n\t\t// especially around 0 and 1\n\t\t// if the value didn't change,\n\t\t// just increment it\n\t\tif (current === lastCurrent) {\n\t\t\tcurrent++;\n\t\t}\n\t\tif (current <= range.max) {\n\t\t\tlastCurrent = current;\n\t\t\tdoAction(current);\n\t\t}\n\t}\n}\n\nexport function resolveRange(\n\trange: IConfigRange,\n\tdefaultGrowthFunc: (input: number) => number,\n): number[] {\n\tconst results: number[] = [];\n\tdoOverRange(range, range.growthFunc ?? defaultGrowthFunc, (num) => {\n\t\tresults.push(num);\n\t});\n\treturn results;\n}\n\nexport function resolveRanges<T extends object>(\n\tranges: T,\n\tdefaultGrowthFunc: (input: number) => number,\n): ResolvedRanges<T> {\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\tconst resolvedRanges: ResolvedRanges<T> = {} as ResolvedRanges<T>;\n\tfor (const [key, value] of Object.entries(ranges)) {\n\t\tif (isConfigRange(value)) {\n\t\t\tresolvedRanges[key] = resolveRange(value, defaultGrowthFunc);\n\t\t}\n\t}\n\treturn resolvedRanges;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction isConfigRange(t: any): t is IConfigRange {\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\treturn typeof t === \"object\" && typeof t.min === \"number\" && typeof t.max === \"number\";\n}\n\ntype ReplaceRangeWith<T, TReplace> = T extends { min: number; max: number } ? TReplace : never;\n\ntype RangePropertyNames<T> = {\n\t[K in keyof T]-?: T[K] extends IConfigRange ? K : never;\n}[keyof T];\n\ntype PickFromRanges<T> = {\n\t[K in RangePropertyNames<T>]: ReplaceRangeWith<T[K], number>;\n};\n\ntype ResolvedRanges<T> = {\n\t[K in RangePropertyNames<T>]: ReplaceRangeWith<T[K], number[]>;\n};\n\ninterface ProvidesGrowthFunc {\n\tgrowthFunc: (input: number) => number;\n}\n\nexport function doOverRanges<T extends ProvidesGrowthFunc>(\n\tranges: T,\n\tdoAction: (selection: PickFromRanges<T>, description: string) => void,\n): void {\n\tconst rangeEntries: [string, IConfigRange][] = [];\n\tfor (const [key, value] of Object.entries(ranges)) {\n\t\tif (isConfigRange(value)) {\n\t\t\trangeEntries.push([key, value]);\n\t\t}\n\t}\n\n\tconst doOverRangesHelper = (selections: [string, number][]): void => {\n\t\tif (selections.length === rangeEntries.length) {\n\t\t\tconst selectionsObj = {};\n\t\t\tfor (const [key, value] of selections) {\n\t\t\t\tselectionsObj[key] = value;\n\t\t\t}\n\t\t\tconst description = selections.map(([key, value]) => `${key}:${value}`).join(\"_\");\n\t\t\tdoAction(selectionsObj as PickFromRanges<T>, description);\n\t\t} else {\n\t\t\tconst [key, value] = rangeEntries[selections.length];\n\t\t\tdoOverRange(value, value.growthFunc ?? ranges.growthFunc, (selection) => {\n\t\t\t\tselections.push([key, selection]);\n\t\t\t\tdoOverRangesHelper(selections);\n\t\t\t\tselections.pop();\n\t\t\t});\n\t\t}\n\t};\n\n\tdoOverRangesHelper([]);\n}\n\nexport interface IMergeTreeOperationRunnerConfig {\n\treadonly rounds: number;\n\treadonly opsPerRoundRange: IConfigRange;\n\treadonly incrementalLog?: boolean;\n\treadonly operations: readonly TestOperation[];\n\treadonly applyOpDuringGeneration?: boolean;\n\tgrowthFunc(input: number): number;\n\tresultsFilePostfix?: string;\n\tinsertText?: (client: TestClient, random: IRandom) => IMergeTreeOp | undefined;\n\tupdateEndpoints?: (client: TestClient, random: IRandom) => { start: number; end: number };\n}\n\nexport interface ReplayGroup {\n\tmsgs: ISequencedDocumentMessage[];\n\tinitialText: string;\n\tresultText: string;\n\tseq: number;\n}\n\nexport const replayResultsPath = `${_dirname}/../../src/test/results`;\n\nexport function runMergeTreeOperationRunner(\n\trandom: IRandom,\n\tstartingSeq: number,\n\tclients: readonly TestClient[],\n\tminLength: number,\n\tconfig: IMergeTreeOperationRunnerConfig,\n\tapply: ApplyMessagesFn = applyMessages,\n): number {\n\tlet seq = startingSeq;\n\tconst results: ReplayGroup[] = [];\n\n\tlet fakeTime = 1725916319097;\n\n\tdoOverRange(config.opsPerRoundRange, config.growthFunc, (opsPerRound) => {\n\t\tif (config.incrementalLog) {\n\t\t\tconsole.log(\n\t\t\t\t`MinLength: ${minLength} Clients: ${clients.length} Ops: ${opsPerRound} Seq: ${seq}`,\n\t\t\t);\n\t\t}\n\t\tfor (let round = 0; round < config.rounds; round++) {\n\t\t\tconst initialText = clients[0].getText();\n\t\t\tconst logger = new TestClientLogger(\n\t\t\t\tclients,\n\t\t\t\t`Clients: ${clients.length} Ops: ${opsPerRound} Round: ${round}`,\n\t\t\t);\n\t\t\tconst messageData = generateOperationMessagesForClients(\n\t\t\t\trandom,\n\t\t\t\tseq,\n\t\t\t\tclients,\n\t\t\t\tlogger,\n\t\t\t\topsPerRound,\n\t\t\t\tminLength,\n\t\t\t\tconfig.operations,\n\t\t\t\tconfig.applyOpDuringGeneration,\n\t\t\t\tconfig.insertText,\n\t\t\t);\n\t\t\tseq = apply(messageData[0][0].sequenceNumber - 1, messageData, clients, logger, random);\n\t\t\tconst resultText = logger.validate();\n\t\t\tresults.push({\n\t\t\t\tinitialText,\n\t\t\t\tresultText,\n\t\t\t\tmsgs: messageData.map((md) => ({ ...md[0], timestamp: fakeTime++ })),\n\t\t\t\tseq,\n\t\t\t});\n\t\t\tlogger.dispose();\n\t\t}\n\t});\n\n\tif (config.resultsFilePostfix !== undefined) {\n\t\tconst resultsFilePath = `${replayResultsPath}/len_${minLength}-clients_${clients.length}-${config.resultsFilePostfix}`;\n\t\tfs.writeFileSync(resultsFilePath, JSON.stringify(results, undefined, \"\\t\"));\n\t}\n\n\treturn seq;\n}\n\nexport function generateOperationMessagesForClients(\n\trandom: IRandom,\n\tstartingSeq: number,\n\tclients: readonly TestClient[],\n\tlogger: TestClientLogger,\n\topsPerRound: number,\n\tminLength: number,\n\toperations: readonly TestOperation[],\n\tapplyOpDuringGeneration?: boolean,\n\tinsertText?: (client: TestClient, random: IRandom) => IMergeTreeOp | undefined,\n): [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][] {\n\tconst minimumSequenceNumber = startingSeq;\n\tlet runningSeq = startingSeq;\n\tconst messages: [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][] = [];\n\n\tfor (let i = 0; i < opsPerRound; i++) {\n\t\t// pick a client greater than 0, client 0 only applies remote ops\n\t\t// and is our baseline\n\t\tconst client = clients[random.integer(1, clients.length - 1)];\n\n\t\tif (applyOpDuringGeneration === true && messages.length > 0 && random.bool()) {\n\t\t\tconst toApply = messages\n\t\t\t\t.filter(([msg]) => msg.sequenceNumber > client.getCollabWindow().currentSeq)\n\t\t\t\t.slice(0, random.integer(1, 3));\n\t\t\tapplyMessages(toApply[0][0].sequenceNumber - 1, toApply, [client], logger);\n\t\t}\n\n\t\tconst len = client.getLength();\n\t\tconst sg = client.peekPendingSegmentGroups();\n\t\tlet opOrOps: IMergeTreeOp[] | IMergeTreeOp | undefined;\n\t\tif (len === 0 || len < minLength) {\n\t\t\topOrOps =\n\t\t\t\tinsertText === undefined ? generateInsert(client, random) : insertText(client, random);\n\t\t} else {\n\t\t\tlet opIndex = random.integer(0, operations.length - 1);\n\t\t\tconst start = random.integer(0, len - 1);\n\t\t\tconst end = random.integer(start + 1, len);\n\n\t\t\tfor (let y = 0; y < operations.length && opOrOps === undefined; y++) {\n\t\t\t\topOrOps = operations[opIndex](client, start, end, random);\n\t\t\t\topIndex++;\n\t\t\t\topIndex %= operations.length;\n\t\t\t}\n\t\t}\n\t\tif (opOrOps !== undefined) {\n\t\t\t// Pre-check to avoid logger.toString() in the string template\n\t\t\tif (sg === client.peekPendingSegmentGroups()) {\n\t\t\t\tassert.notEqual(\n\t\t\t\t\tsg,\n\t\t\t\t\tclient.peekPendingSegmentGroups(),\n\t\t\t\t\t`op created but segment group not enqueued.${logger}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst ops = Array.isArray(opOrOps) ? opOrOps : [opOrOps];\n\t\t\tconst totalIndividualOps = ops\n\t\t\t\t.map((o) => (o.type === MergeTreeDeltaType.GROUP ? o.ops.length : 1))\n\t\t\t\t.reduce((a, b) => a + b, 0);\n\t\t\tlet allSegmentGroups = client.peekPendingSegmentGroups(totalIndividualOps)!;\n\t\t\tif (!Array.isArray(allSegmentGroups)) {\n\t\t\t\tallSegmentGroups = [allSegmentGroups];\n\t\t\t}\n\t\t\tassert(Array.isArray(allSegmentGroups), \"Expected array of segment groups\");\n\t\t\tfor (const op of ops) {\n\t\t\t\tconst message = client.makeOpMessage(op, ++runningSeq);\n\t\t\t\tmessage.minimumSequenceNumber = minimumSequenceNumber;\n\t\t\t\tconst segmentGroups = allSegmentGroups.splice(\n\t\t\t\t\t0,\n\t\t\t\t\top.type === MergeTreeDeltaType.GROUP ? op.ops.length : 1,\n\t\t\t\t);\n\t\t\t\tmessages.push([\n\t\t\t\t\tmessage,\n\t\t\t\t\top.type === MergeTreeDeltaType.GROUP ? segmentGroups : segmentGroups[0],\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst maxProcessedSeq = Math.max(...clients.map((c) => c.getCollabWindow().currentSeq));\n\tif (messages.length > 0) {\n\t\tconst index = messages.findIndex(([msg]) => msg.sequenceNumber === maxProcessedSeq);\n\t\tif (index !== -1) {\n\t\t\tconst apply = messages.splice(0, index + 1);\n\t\t\tapplyMessages(apply[0][0].sequenceNumber - 1, apply, clients, logger);\n\t\t}\n\t}\n\n\treturn messages;\n}\n\nexport function generateClientNames(): string[] {\n\tconst clientNames: string[] = [];\n\tfunction addClientNames(startChar: string, count: number): void {\n\t\tconst startCode = startChar.codePointAt(0);\n\t\tif (startCode === undefined) {\n\t\t\tthrow new Error(\"startCode must be a single character\");\n\t\t}\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tclientNames.push(String.fromCodePoint(startCode + i));\n\t\t}\n\t}\n\n\taddClientNames(\"A\", 26);\n\taddClientNames(\"a\", 26);\n\taddClientNames(\"0\", 17);\n\n\treturn clientNames;\n}\n\ntype ApplyMessagesFn = (\n\tstartingSeq: number,\n\tmessageData: [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][],\n\tclients: readonly TestClient[],\n\tlogger: TestClientLogger,\n\trandom: IRandom,\n) => number;\n\nexport function applyMessages(\n\tstartingSeq: number,\n\tmessageData: [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][],\n\tclients: readonly TestClient[],\n\tlogger: TestClientLogger,\n): number {\n\tlet seq = startingSeq;\n\ttry {\n\t\t// log and apply all the ops created in the round\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-for-of\n\t\tfor (let i = 0; i < messageData.length; i++) {\n\t\t\tconst [message] = messageData[i];\n\t\t\tmessage.sequenceNumber = ++seq;\n\t\t\tfor (const c of clients) {\n\t\t\t\tif (c.getCollabWindow().currentSeq < message.sequenceNumber) {\n\t\t\t\t\tc.applyMsg(message);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tthrow logger.addLogsToError(error);\n\t}\n\treturn seq;\n}\n"]}
1
+ {"version":3,"file":"mergeTreeOperationRunner.js","sourceRoot":"","sources":["../../src/test/mergeTreeOperationRunner.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\";\nimport * as fs from \"node:fs\";\n\nimport { IRandom } from \"@fluid-private/stochastic-test-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport { walkAllChildSegments } from \"../mergeTreeNodeWalk.js\";\nimport { ISegmentPrivate, SegmentGroup } from \"../mergeTreeNodes.js\";\nimport { IMergeTreeOp, MergeTreeDeltaType, ReferenceType } from \"../ops.js\";\nimport { toRemovalInfo } from \"../segmentInfos.js\";\nimport { Side } from \"../sequencePlace.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { _dirname } from \"./dirname.cjs\";\nimport { TestClient } from \"./testClient.js\";\nimport { TestClientLogger } from \"./testClientLogger.js\";\n\nexport type TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => IMergeTreeOp[] | IMergeTreeOp | undefined;\n\nexport const removeRange: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n) => client.removeRangeLocal(opStart, opEnd);\n\nexport const obliterateRange: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n) => client.obliterateRangeLocal(opStart, opEnd);\n\nexport const obliterateRangeSided: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tlet startSide: Side;\n\tlet endSide: Side;\n\n\tconst oblEnd = random.integer(opStart, client.getLength() - 1);\n\t// TODO: to create zero length obliterate ops, change '<=' to '<'.\n\t// Doing so may cause different failures than those without zero length.\n\t// AB#19930\n\tif (oblEnd - opStart <= 1) {\n\t\tstartSide = Side.Before;\n\t\tendSide = Side.After;\n\t} else {\n\t\tstartSide = random.pick([Side.Before, Side.After]);\n\t\tendSide = random.pick([Side.Before, Side.After]);\n\t}\n\n\tconst start = { pos: opStart, side: startSide };\n\tconst end = { pos: oblEnd, side: endSide };\n\treturn client.obliterateRangeLocal(start, end);\n};\n\nexport const annotateRange: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tif (random.bool()) {\n\t\treturn client.annotateRangeLocal(opStart, opEnd, {\n\t\t\t[random.integer(1, 5)]: client.longClientId,\n\t\t});\n\t} else {\n\t\tconst max = random.pick([undefined, random.integer(-10, 100)]);\n\t\tconst min = random.pick([undefined, random.integer(-100, 10)]);\n\t\treturn client.annotateAdjustRangeLocal(opStart, opEnd, {\n\t\t\t[random.integer(0, 2).toString()]: {\n\t\t\t\tdelta: random.integer(-5, 5),\n\t\t\t\tmin: (min ?? max ?? 0) > (max ?? 0) ? undefined : min,\n\t\t\t\tmax,\n\t\t\t},\n\t\t});\n\t}\n};\n\nexport const insertAtRefPos: TestOperation = (\n\tclient: TestClient,\n\topStart: number,\n\topEnd: number,\n\trandom: IRandom,\n) => {\n\tconst segs: ISegmentPrivate[] = [];\n\t// gather all the segments at the pos, including removed segments\n\twalkAllChildSegments(client.mergeTree.root, (seg) => {\n\t\tconst pos = client.getPosition(seg);\n\t\tif (pos >= opStart) {\n\t\t\tif (pos <= opStart) {\n\t\t\t\tsegs.push(seg);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t});\n\tif (segs.length > 0) {\n\t\tconst text = client.longClientId!.repeat(random.integer(1, 3));\n\t\tconst seg = random.pick(segs);\n\t\tconst removed = toRemovalInfo(seg);\n\t\tconst lref = client.createLocalReferencePosition(\n\t\t\tseg,\n\t\t\tremoved ? 0 : random.integer(0, seg.cachedLength - 1),\n\t\t\tremoved\n\t\t\t\t? ReferenceType.SlideOnRemove\n\t\t\t\t: random.pick([\n\t\t\t\t\t\tReferenceType.Simple,\n\t\t\t\t\t\tReferenceType.SlideOnRemove,\n\t\t\t\t\t\tReferenceType.Transient,\n\t\t\t\t\t]),\n\t\t\tundefined,\n\t\t);\n\n\t\treturn client.insertAtReferencePositionLocal(lref, TextSegment.make(text));\n\t}\n};\n\nexport const insert: TestOperation = (\n\tclient: TestClient,\n\t_start: number,\n\t_end: number,\n\trandom: IRandom,\n) => {\n\t// Note: the _start param is generated using exclusive range. This provides more coverage by allowing\n\t// insertion at the end.\n\tconst start = random.integer(0, client.getLength());\n\tconst text = client.longClientId!.repeat(random.integer(1, 3));\n\treturn client.insertTextLocal(start, text);\n};\n\nconst generateInsert = (client: TestClient, random: IRandom): IMergeTreeOp | undefined => {\n\tconst len = client.getLength();\n\tconst text = client.longClientId!.repeat(random.integer(1, 3));\n\treturn client.insertTextLocal(random.integer(0, len), text);\n};\n\nexport interface IConfigRange {\n\tmin: number;\n\tmax: number;\n\tgrowthFunc?: (input: number) => number;\n}\n\nexport function doOverRange(\n\trange: IConfigRange,\n\tdefaultGrowthFunc: (input: number) => number,\n\tdoAction: (current: number) => void,\n): void {\n\tlet lastCurrent = Number.NaN;\n\tfor (\n\t\tlet current = range.min;\n\t\tcurrent <= range.max;\n\t\tcurrent = (range.growthFunc ?? defaultGrowthFunc)(current)\n\t) {\n\t\t// let growth funcs be simple\n\t\t// especially around 0 and 1\n\t\t// if the value didn't change,\n\t\t// just increment it\n\t\tif (current === lastCurrent) {\n\t\t\tcurrent++;\n\t\t}\n\t\tif (current <= range.max) {\n\t\t\tlastCurrent = current;\n\t\t\tdoAction(current);\n\t\t}\n\t}\n}\n\nexport function resolveRange(\n\trange: IConfigRange,\n\tdefaultGrowthFunc: (input: number) => number,\n): number[] {\n\tconst results: number[] = [];\n\tdoOverRange(range, range.growthFunc ?? defaultGrowthFunc, (num) => {\n\t\tresults.push(num);\n\t});\n\treturn results;\n}\n\nexport function resolveRanges<T extends object>(\n\tranges: T,\n\tdefaultGrowthFunc: (input: number) => number,\n): ResolvedRanges<T> {\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\tconst resolvedRanges: ResolvedRanges<T> = {} as ResolvedRanges<T>;\n\tfor (const [key, value] of Object.entries(ranges)) {\n\t\tif (isConfigRange(value)) {\n\t\t\tresolvedRanges[key] = resolveRange(value, defaultGrowthFunc);\n\t\t}\n\t}\n\treturn resolvedRanges;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction isConfigRange(t: any): t is IConfigRange {\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\treturn typeof t === \"object\" && typeof t.min === \"number\" && typeof t.max === \"number\";\n}\n\ntype ReplaceRangeWith<T, TReplace> = T extends { min: number; max: number } ? TReplace : never;\n\ntype RangePropertyNames<T> = {\n\t[K in keyof T]-?: T[K] extends IConfigRange ? K : never;\n}[keyof T];\n\ntype PickFromRanges<T> = {\n\t[K in RangePropertyNames<T>]: ReplaceRangeWith<T[K], number>;\n};\n\ntype ResolvedRanges<T> = {\n\t[K in RangePropertyNames<T>]: ReplaceRangeWith<T[K], number[]>;\n};\n\ninterface ProvidesGrowthFunc {\n\tgrowthFunc: (input: number) => number;\n}\n\nexport function doOverRanges<T extends ProvidesGrowthFunc>(\n\tranges: T,\n\tdoAction: (selection: PickFromRanges<T>, description: string) => void,\n): void {\n\tconst rangeEntries: [string, IConfigRange][] = [];\n\tfor (const [key, value] of Object.entries(ranges)) {\n\t\tif (isConfigRange(value)) {\n\t\t\trangeEntries.push([key, value]);\n\t\t}\n\t}\n\n\tconst doOverRangesHelper = (selections: [string, number][]): void => {\n\t\tif (selections.length === rangeEntries.length) {\n\t\t\tconst selectionsObj = {};\n\t\t\tfor (const [key, value] of selections) {\n\t\t\t\tselectionsObj[key] = value;\n\t\t\t}\n\t\t\tconst description = selections.map(([key, value]) => `${key}:${value}`).join(\"_\");\n\t\t\tdoAction(selectionsObj as PickFromRanges<T>, description);\n\t\t} else {\n\t\t\tconst [key, value] = rangeEntries[selections.length];\n\t\t\tdoOverRange(value, value.growthFunc ?? ranges.growthFunc, (selection) => {\n\t\t\t\tselections.push([key, selection]);\n\t\t\t\tdoOverRangesHelper(selections);\n\t\t\t\tselections.pop();\n\t\t\t});\n\t\t}\n\t};\n\n\tdoOverRangesHelper([]);\n}\n\nexport interface IMergeTreeOperationRunnerConfig {\n\treadonly rounds: number;\n\treadonly opsPerRoundRange: IConfigRange;\n\treadonly incrementalLog?: boolean;\n\treadonly operations: readonly TestOperation[];\n\treadonly applyOpDuringGeneration?: boolean;\n\tgrowthFunc(input: number): number;\n\tresultsFilePostfix?: string;\n\tinsertText?: (client: TestClient, random: IRandom) => IMergeTreeOp | undefined;\n\tupdateEndpoints?: (client: TestClient, random: IRandom) => { start: number; end: number };\n}\n\nexport interface ReplayGroup {\n\tmsgs: ISequencedDocumentMessage[];\n\tinitialText: string;\n\tresultText: string;\n\tseq: number;\n}\n\nexport const replayResultsPath = `${_dirname}/../../src/test/results`;\n\nexport function runMergeTreeOperationRunner(\n\trandom: IRandom,\n\tstartingSeq: number,\n\tclients: readonly TestClient[],\n\tminLength: number,\n\tconfig: IMergeTreeOperationRunnerConfig,\n\tapply: ApplyMessagesFn = applyMessages,\n): number {\n\tlet seq = startingSeq;\n\tconst results: ReplayGroup[] = [];\n\n\tlet fakeTime = 1725916319097;\n\n\tdoOverRange(config.opsPerRoundRange, config.growthFunc, (opsPerRound) => {\n\t\tif (config.incrementalLog) {\n\t\t\tconsole.log(\n\t\t\t\t`MinLength: ${minLength} Clients: ${clients.length} Ops: ${opsPerRound} Seq: ${seq}`,\n\t\t\t);\n\t\t}\n\t\tfor (let round = 0; round < config.rounds; round++) {\n\t\t\tconst initialText = clients[0].getText();\n\t\t\tconst logger = new TestClientLogger(\n\t\t\t\tclients,\n\t\t\t\t`Clients: ${clients.length} Ops: ${opsPerRound} Round: ${round}`,\n\t\t\t);\n\t\t\tconst messageData = generateOperationMessagesForClients(\n\t\t\t\trandom,\n\t\t\t\tseq,\n\t\t\t\tclients,\n\t\t\t\tlogger,\n\t\t\t\topsPerRound,\n\t\t\t\tminLength,\n\t\t\t\tconfig.operations,\n\t\t\t\tconfig.applyOpDuringGeneration,\n\t\t\t\tconfig.insertText,\n\t\t\t);\n\t\t\tseq = apply(messageData[0][0].sequenceNumber - 1, messageData, clients, logger, random);\n\t\t\tconst resultText = logger.validate();\n\t\t\tresults.push({\n\t\t\t\tinitialText,\n\t\t\t\tresultText,\n\t\t\t\tmsgs: messageData.map((md) => ({ ...md[0], timestamp: fakeTime++ })),\n\t\t\t\tseq,\n\t\t\t});\n\t\t\tlogger.dispose();\n\t\t}\n\t});\n\n\tif (config.resultsFilePostfix !== undefined) {\n\t\tconst resultsFilePath = `${replayResultsPath}/len_${minLength}-clients_${clients.length}-${config.resultsFilePostfix}`;\n\t\tfs.writeFileSync(resultsFilePath, JSON.stringify(results, undefined, \"\\t\"));\n\t}\n\n\treturn seq;\n}\n\nexport function generateOperationMessagesForClients(\n\trandom: IRandom,\n\tstartingSeq: number,\n\tclients: readonly TestClient[],\n\tlogger: TestClientLogger,\n\topsPerRound: number,\n\tminLength: number,\n\toperations: readonly TestOperation[],\n\tapplyOpDuringGeneration?: boolean,\n\tinsertText?: (client: TestClient, random: IRandom) => IMergeTreeOp | undefined,\n): [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][] {\n\tconst minimumSequenceNumber = startingSeq;\n\tlet runningSeq = startingSeq;\n\tconst messages: [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][] = [];\n\n\tfor (let i = 0; i < opsPerRound; i++) {\n\t\t// pick a client greater than 0, client 0 only applies remote ops\n\t\t// and is our baseline\n\t\tconst client = clients[random.integer(1, clients.length - 1)];\n\n\t\tif (applyOpDuringGeneration === true && messages.length > 0 && random.bool()) {\n\t\t\tconst toApply = messages\n\t\t\t\t.filter(([msg]) => msg.sequenceNumber > client.getCollabWindow().currentSeq)\n\t\t\t\t.slice(0, random.integer(1, 3));\n\t\t\tapplyMessages(toApply[0][0].sequenceNumber - 1, toApply, [client], logger);\n\t\t}\n\n\t\tconst len = client.getLength();\n\t\tconst sg = client.peekPendingSegmentGroups();\n\t\tlet opOrOps: IMergeTreeOp[] | IMergeTreeOp | undefined;\n\t\tif (len === 0 || len < minLength) {\n\t\t\topOrOps =\n\t\t\t\tinsertText === undefined ? generateInsert(client, random) : insertText(client, random);\n\t\t} else {\n\t\t\tlet opIndex = random.integer(0, operations.length - 1);\n\t\t\tconst start = random.integer(0, len - 1);\n\t\t\tconst end = random.integer(start + 1, len);\n\n\t\t\tfor (let y = 0; y < operations.length && opOrOps === undefined; y++) {\n\t\t\t\topOrOps = operations[opIndex](client, start, end, random);\n\t\t\t\topIndex++;\n\t\t\t\topIndex %= operations.length;\n\t\t\t}\n\t\t}\n\t\tif (opOrOps !== undefined) {\n\t\t\t// Pre-check to avoid logger.toString() in the string template\n\t\t\tif (sg === client.peekPendingSegmentGroups()) {\n\t\t\t\tassert.notEqual(\n\t\t\t\t\tsg,\n\t\t\t\t\tclient.peekPendingSegmentGroups(),\n\t\t\t\t\t`op created but segment group not enqueued.${logger}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst ops = Array.isArray(opOrOps) ? opOrOps : [opOrOps];\n\t\t\tconst totalIndividualOps = ops\n\t\t\t\t.map((o) => (o.type === MergeTreeDeltaType.GROUP ? o.ops.length : 1))\n\t\t\t\t.reduce((a, b) => a + b, 0);\n\t\t\tlet allSegmentGroups = client.peekPendingSegmentGroups(totalIndividualOps)!;\n\t\t\tif (!Array.isArray(allSegmentGroups)) {\n\t\t\t\tallSegmentGroups = [allSegmentGroups];\n\t\t\t}\n\t\t\tassert(Array.isArray(allSegmentGroups), \"Expected array of segment groups\");\n\t\t\tfor (const op of ops) {\n\t\t\t\tconst message = client.makeOpMessage(op, ++runningSeq);\n\t\t\t\tmessage.minimumSequenceNumber = minimumSequenceNumber;\n\t\t\t\tconst segmentGroups = allSegmentGroups.splice(\n\t\t\t\t\t0,\n\t\t\t\t\top.type === MergeTreeDeltaType.GROUP ? op.ops.length : 1,\n\t\t\t\t);\n\t\t\t\tmessages.push([\n\t\t\t\t\tmessage,\n\t\t\t\t\top.type === MergeTreeDeltaType.GROUP ? segmentGroups : segmentGroups[0],\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst maxProcessedSeq = Math.max(...clients.map((c) => c.getCollabWindow().currentSeq));\n\tif (messages.length > 0) {\n\t\tconst index = messages.findIndex(([msg]) => msg.sequenceNumber === maxProcessedSeq);\n\t\tif (index !== -1) {\n\t\t\tconst apply = messages.splice(0, index + 1);\n\t\t\tapplyMessages(apply[0][0].sequenceNumber - 1, apply, clients, logger);\n\t\t}\n\t}\n\n\treturn messages;\n}\n\nexport function generateClientNames(): string[] {\n\tconst clientNames: string[] = [];\n\tfunction addClientNames(startChar: string, count: number): void {\n\t\tconst startCode = startChar.codePointAt(0);\n\t\tif (startCode === undefined) {\n\t\t\tthrow new Error(\"startCode must be a single character\");\n\t\t}\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tclientNames.push(String.fromCodePoint(startCode + i));\n\t\t}\n\t}\n\n\taddClientNames(\"A\", 26);\n\taddClientNames(\"a\", 26);\n\taddClientNames(\"0\", 17);\n\n\treturn clientNames;\n}\n\ntype ApplyMessagesFn = (\n\tstartingSeq: number,\n\tmessageData: [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][],\n\tclients: readonly TestClient[],\n\tlogger: TestClientLogger,\n\trandom: IRandom,\n) => number;\n\nexport function applyMessages(\n\tstartingSeq: number,\n\tmessageData: [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][],\n\tclients: readonly TestClient[],\n\tlogger: TestClientLogger,\n): number {\n\tlet seq = startingSeq;\n\ttry {\n\t\t// log and apply all the ops created in the round\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-for-of\n\t\tfor (let i = 0; i < messageData.length; i++) {\n\t\t\tconst [message] = messageData[i];\n\t\t\tmessage.sequenceNumber = ++seq;\n\t\t\tfor (const c of clients) {\n\t\t\t\tif (c.getCollabWindow().currentSeq < message.sequenceNumber) {\n\t\t\t\t\tc.applyMsg(message);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tthrow logger.addLogsToError(error);\n\t}\n\treturn seq;\n}\n"]}