@fluidframework/merge-tree 2.20.0 → 2.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/.eslintrc.cjs +0 -1
  2. package/CHANGELOG.md +8 -0
  3. package/README.md +1 -0
  4. package/dist/attributionCollection.js +5 -7
  5. package/dist/attributionCollection.js.map +1 -1
  6. package/dist/localReference.js +6 -8
  7. package/dist/localReference.js.map +1 -1
  8. package/dist/mergeTree.d.ts.map +1 -1
  9. package/dist/mergeTree.js +69 -34
  10. package/dist/mergeTree.js.map +1 -1
  11. package/dist/mergeTreeNodes.d.ts +15 -4
  12. package/dist/mergeTreeNodes.d.ts.map +1 -1
  13. package/dist/mergeTreeNodes.js +1 -1
  14. package/dist/mergeTreeNodes.js.map +1 -1
  15. package/dist/partialLengths.d.ts +114 -144
  16. package/dist/partialLengths.d.ts.map +1 -1
  17. package/dist/partialLengths.js +431 -525
  18. package/dist/partialLengths.js.map +1 -1
  19. package/dist/perspective.d.ts +10 -1
  20. package/dist/perspective.d.ts.map +1 -1
  21. package/dist/perspective.js +10 -1
  22. package/dist/perspective.js.map +1 -1
  23. package/dist/properties.d.ts.map +1 -1
  24. package/dist/properties.js +2 -3
  25. package/dist/properties.js.map +1 -1
  26. package/dist/revertibles.js +3 -3
  27. package/dist/revertibles.js.map +1 -1
  28. package/dist/segmentInfos.d.ts +3 -0
  29. package/dist/segmentInfos.d.ts.map +1 -1
  30. package/dist/segmentInfos.js.map +1 -1
  31. package/dist/segmentPropertiesManager.js +3 -3
  32. package/dist/segmentPropertiesManager.js.map +1 -1
  33. package/dist/snapshotLoader.js +2 -2
  34. package/dist/snapshotLoader.js.map +1 -1
  35. package/dist/sortedSegmentSet.d.ts +5 -3
  36. package/dist/sortedSegmentSet.d.ts.map +1 -1
  37. package/dist/sortedSegmentSet.js +33 -41
  38. package/dist/sortedSegmentSet.js.map +1 -1
  39. package/dist/sortedSet.d.ts +20 -3
  40. package/dist/sortedSet.d.ts.map +1 -1
  41. package/dist/sortedSet.js +23 -14
  42. package/dist/sortedSet.js.map +1 -1
  43. package/dist/test/Snapshot.perf.spec.js +1 -1
  44. package/dist/test/Snapshot.perf.spec.js.map +1 -1
  45. package/dist/test/client.applyMsg.spec.js +20 -0
  46. package/dist/test/client.applyMsg.spec.js.map +1 -1
  47. package/dist/test/client.applyStashedOpFarm.spec.js +1 -1
  48. package/dist/test/client.applyStashedOpFarm.spec.js.map +1 -1
  49. package/dist/test/client.attributionFarm.spec.js +1 -1
  50. package/dist/test/client.attributionFarm.spec.js.map +1 -1
  51. package/dist/test/client.localReference.spec.js +48 -0
  52. package/dist/test/client.localReference.spec.js.map +1 -1
  53. package/dist/test/client.obliterateFarm.spec.d.ts +12 -0
  54. package/dist/test/client.obliterateFarm.spec.d.ts.map +1 -0
  55. package/dist/test/client.obliterateFarm.spec.js +89 -0
  56. package/dist/test/client.obliterateFarm.spec.js.map +1 -0
  57. package/dist/test/client.reconnectFarm.spec.js +1 -1
  58. package/dist/test/client.reconnectFarm.spec.js.map +1 -1
  59. package/dist/test/client.searchForMarker.spec.js +2 -2
  60. package/dist/test/client.searchForMarker.spec.js.map +1 -1
  61. package/dist/test/mergeTreeOperationRunner.d.ts +7 -2
  62. package/dist/test/mergeTreeOperationRunner.d.ts.map +1 -1
  63. package/dist/test/mergeTreeOperationRunner.js +31 -14
  64. package/dist/test/mergeTreeOperationRunner.js.map +1 -1
  65. package/dist/test/obliterate.concurrent.spec.js +45 -1
  66. package/dist/test/obliterate.concurrent.spec.js.map +1 -1
  67. package/dist/test/obliterate.rangeExpansion.spec.js +81 -5
  68. package/dist/test/obliterate.rangeExpansion.spec.js.map +1 -1
  69. package/dist/test/obliterate.spec.js +3 -3
  70. package/dist/test/obliterate.spec.js.map +1 -1
  71. package/dist/test/obliterateOperations.d.ts +15 -0
  72. package/dist/test/obliterateOperations.d.ts.map +1 -0
  73. package/dist/test/obliterateOperations.js +132 -0
  74. package/dist/test/obliterateOperations.js.map +1 -0
  75. package/dist/test/partialSyncHelper.d.ts +42 -0
  76. package/dist/test/partialSyncHelper.d.ts.map +1 -0
  77. package/dist/test/partialSyncHelper.js +96 -0
  78. package/dist/test/partialSyncHelper.js.map +1 -0
  79. package/dist/test/revertibles.spec.js +3 -3
  80. package/dist/test/revertibles.spec.js.map +1 -1
  81. package/dist/test/sortedSegmentSet.spec.js +21 -0
  82. package/dist/test/sortedSegmentSet.spec.js.map +1 -1
  83. package/dist/test/testClient.d.ts +1 -1
  84. package/dist/test/testClient.d.ts.map +1 -1
  85. package/dist/test/testClient.js +1 -0
  86. package/dist/test/testClient.js.map +1 -1
  87. package/dist/test/testUtils.js +2 -2
  88. package/dist/test/testUtils.js.map +1 -1
  89. package/lib/attributionCollection.js +5 -7
  90. package/lib/attributionCollection.js.map +1 -1
  91. package/lib/localReference.js +6 -8
  92. package/lib/localReference.js.map +1 -1
  93. package/lib/mergeTree.d.ts.map +1 -1
  94. package/lib/mergeTree.js +69 -34
  95. package/lib/mergeTree.js.map +1 -1
  96. package/lib/mergeTreeNodes.d.ts +15 -4
  97. package/lib/mergeTreeNodes.d.ts.map +1 -1
  98. package/lib/mergeTreeNodes.js +1 -1
  99. package/lib/mergeTreeNodes.js.map +1 -1
  100. package/lib/partialLengths.d.ts +114 -144
  101. package/lib/partialLengths.d.ts.map +1 -1
  102. package/lib/partialLengths.js +432 -525
  103. package/lib/partialLengths.js.map +1 -1
  104. package/lib/perspective.d.ts +10 -1
  105. package/lib/perspective.d.ts.map +1 -1
  106. package/lib/perspective.js +10 -1
  107. package/lib/perspective.js.map +1 -1
  108. package/lib/properties.d.ts.map +1 -1
  109. package/lib/properties.js +2 -3
  110. package/lib/properties.js.map +1 -1
  111. package/lib/revertibles.js +3 -3
  112. package/lib/revertibles.js.map +1 -1
  113. package/lib/segmentInfos.d.ts +3 -0
  114. package/lib/segmentInfos.d.ts.map +1 -1
  115. package/lib/segmentInfos.js.map +1 -1
  116. package/lib/segmentPropertiesManager.js +3 -3
  117. package/lib/segmentPropertiesManager.js.map +1 -1
  118. package/lib/snapshotLoader.js +2 -2
  119. package/lib/snapshotLoader.js.map +1 -1
  120. package/lib/sortedSegmentSet.d.ts +5 -3
  121. package/lib/sortedSegmentSet.d.ts.map +1 -1
  122. package/lib/sortedSegmentSet.js +33 -41
  123. package/lib/sortedSegmentSet.js.map +1 -1
  124. package/lib/sortedSet.d.ts +20 -3
  125. package/lib/sortedSet.d.ts.map +1 -1
  126. package/lib/sortedSet.js +23 -14
  127. package/lib/sortedSet.js.map +1 -1
  128. package/lib/test/Snapshot.perf.spec.js +1 -1
  129. package/lib/test/Snapshot.perf.spec.js.map +1 -1
  130. package/lib/test/client.applyMsg.spec.js +20 -0
  131. package/lib/test/client.applyMsg.spec.js.map +1 -1
  132. package/lib/test/client.applyStashedOpFarm.spec.js +1 -1
  133. package/lib/test/client.applyStashedOpFarm.spec.js.map +1 -1
  134. package/lib/test/client.attributionFarm.spec.js +1 -1
  135. package/lib/test/client.attributionFarm.spec.js.map +1 -1
  136. package/lib/test/client.localReference.spec.js +48 -0
  137. package/lib/test/client.localReference.spec.js.map +1 -1
  138. package/lib/test/client.obliterateFarm.spec.d.ts +12 -0
  139. package/lib/test/client.obliterateFarm.spec.d.ts.map +1 -0
  140. package/lib/test/client.obliterateFarm.spec.js +88 -0
  141. package/lib/test/client.obliterateFarm.spec.js.map +1 -0
  142. package/lib/test/client.reconnectFarm.spec.js +1 -1
  143. package/lib/test/client.reconnectFarm.spec.js.map +1 -1
  144. package/lib/test/client.searchForMarker.spec.js +2 -2
  145. package/lib/test/client.searchForMarker.spec.js.map +1 -1
  146. package/lib/test/mergeTreeOperationRunner.d.ts +7 -2
  147. package/lib/test/mergeTreeOperationRunner.d.ts.map +1 -1
  148. package/lib/test/mergeTreeOperationRunner.js +31 -14
  149. package/lib/test/mergeTreeOperationRunner.js.map +1 -1
  150. package/lib/test/obliterate.concurrent.spec.js +45 -1
  151. package/lib/test/obliterate.concurrent.spec.js.map +1 -1
  152. package/lib/test/obliterate.rangeExpansion.spec.js +81 -5
  153. package/lib/test/obliterate.rangeExpansion.spec.js.map +1 -1
  154. package/lib/test/obliterate.spec.js +3 -3
  155. package/lib/test/obliterate.spec.js.map +1 -1
  156. package/lib/test/obliterateOperations.d.ts +15 -0
  157. package/lib/test/obliterateOperations.d.ts.map +1 -0
  158. package/lib/test/obliterateOperations.js +123 -0
  159. package/lib/test/obliterateOperations.js.map +1 -0
  160. package/lib/test/partialSyncHelper.d.ts +42 -0
  161. package/lib/test/partialSyncHelper.d.ts.map +1 -0
  162. package/lib/test/partialSyncHelper.js +92 -0
  163. package/lib/test/partialSyncHelper.js.map +1 -0
  164. package/lib/test/revertibles.spec.js +3 -3
  165. package/lib/test/revertibles.spec.js.map +1 -1
  166. package/lib/test/sortedSegmentSet.spec.js +21 -0
  167. package/lib/test/sortedSegmentSet.spec.js.map +1 -1
  168. package/lib/test/testClient.d.ts +1 -1
  169. package/lib/test/testClient.d.ts.map +1 -1
  170. package/lib/test/testClient.js +1 -0
  171. package/lib/test/testClient.js.map +1 -1
  172. package/lib/test/testUtils.js +2 -2
  173. package/lib/test/testUtils.js.map +1 -1
  174. package/package.json +21 -79
  175. package/src/mergeTree.ts +80 -28
  176. package/src/mergeTreeNodes.ts +15 -4
  177. package/src/partialLengths.ts +559 -776
  178. package/src/perspective.ts +10 -1
  179. package/src/properties.ts +2 -3
  180. package/src/segmentInfos.ts +3 -0
  181. package/src/snapshotLoader.ts +1 -1
  182. package/src/sortedSegmentSet.ts +41 -50
  183. package/src/sortedSet.ts +32 -16
@@ -1 +1 @@
1
- {"version":3,"file":"testClient.js","sourceRoot":"","sources":["../../src/test/testClient.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 { Trace } from \"@fluid-internal/client-utils\";\nimport { makeRandom } from \"@fluid-private/stochastic-test-utils\";\nimport { IFluidDataStoreRuntime } from \"@fluidframework/datastore-definitions/internal\";\nimport { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport {\n\tITree,\n\tMessageType,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { AttributionKey } from \"@fluidframework/runtime-definitions/internal\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils/internal\";\nimport { MockStorage } from \"@fluidframework/test-runtime-utils/internal\";\n\nimport { MergeTreeTextHelper } from \"../MergeTreeTextHelper.js\";\nimport { Client } from \"../client.js\";\nimport { DoublyLinkedList } from \"../collections/index.js\";\nimport { UnassignedSequenceNumber } from \"../constants.js\";\nimport { IMergeTreeOptions, ReferencePosition } from \"../index.js\";\nimport { MergeTree, getSlideToSegoff } from \"../mergeTree.js\";\nimport {\n\tbackwardExcursion,\n\tforwardExcursion,\n\twalkAllChildSegments,\n} from \"../mergeTreeNodeWalk.js\";\nimport {\n\tMergeBlock,\n\tISegmentPrivate,\n\tMarker,\n\tMaxNodesInBlock,\n\ttype SegmentGroup,\n\tassertSegmentLeaf,\n} from \"../mergeTreeNodes.js\";\nimport {\n\tcreateAnnotateRangeOp,\n\tcreateInsertSegmentOp,\n\tcreateRemoveRangeOp,\n} from \"../opBuilder.js\";\nimport {\n\tIJSONSegment,\n\tIMarkerDef,\n\tIMergeTreeOp,\n\tMergeTreeDeltaType,\n\tReferenceType,\n\ttype IMergeTreeInsertMsg,\n} from \"../ops.js\";\nimport { PropertySet } from \"../properties.js\";\nimport { DetachedReferencePosition, refHasTileLabel } from \"../referencePositions.js\";\nimport { MergeTreeRevertibleDriver } from \"../revertibles.js\";\nimport {\n\tassertInserted,\n\tassertMergeNode,\n\tisInserted,\n\tisMoved,\n\tisRemoved,\n} from \"../segmentInfos.js\";\nimport { SnapshotLegacy } from \"../snapshotlegacy.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestSerializer } from \"./testSerializer.js\";\nimport { nodeOrdinalsHaveIntegrity } from \"./testUtils.js\";\n\nexport function specToSegment(spec: IJSONSegment): ISegmentPrivate {\n\tconst maybeText = TextSegment.fromJSONObject(spec);\n\tif (maybeText) {\n\t\treturn maybeText;\n\t}\n\n\tconst maybeMarker = Marker.fromJSONObject(spec);\n\tif (maybeMarker) {\n\t\treturn maybeMarker;\n\t}\n\n\tthrow new Error(`Unrecognized IJSONSegment type: '${JSON.stringify(spec)}'`);\n}\n\nconst random = makeRandom(0xdeadbeef, 0xfeedbed);\n\nexport class TestClient extends Client {\n\tpublic static searchChunkSize = 256;\n\tpublic static readonly serializer = new TestSerializer();\n\tpublic measureOps = false;\n\tpublic accumTime = 0;\n\tpublic accumWindowTime = 0;\n\tpublic accumWindow = 0;\n\tpublic accumOps = 0;\n\tpublic maxWindowTime = 0;\n\n\t/**\n\t * Used for in-memory testing. This will queue a reference string for each client message.\n\t */\n\tpublic static useCheckQ = false;\n\n\tpublic static async createFromClientSnapshot(\n\t\tclient1: TestClient,\n\t\tnewLongClientId: string,\n\t): Promise<TestClient> {\n\t\tconst snapshot = new SnapshotLegacy(\n\t\t\tclient1.mergeTree,\n\t\t\tcreateChildLogger({ namespace: \"fluid:snapshot\" }),\n\t\t);\n\t\tsnapshot.extractSync();\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst summaryTree = snapshot.emit([], TestClient.serializer, undefined!).summary;\n\t\treturn TestClient.createFromSummary(\n\t\t\tsummaryTree,\n\t\t\tnewLongClientId,\n\t\t\tclient1.specToSegment,\n\t\t\tclient1.mergeTree.options,\n\t\t);\n\t}\n\n\tpublic static async createFromSnapshot(\n\t\tsnapshotTree: ITree,\n\t\tnewLongClientId: string,\n\t\tspecToSeg: (spec: IJSONSegment) => ISegmentPrivate,\n\t\toptions?: PropertySet,\n\t): Promise<TestClient> {\n\t\treturn TestClient.createFromStorage(\n\t\t\tnew MockStorage(snapshotTree),\n\t\t\tnewLongClientId,\n\t\t\tspecToSeg,\n\t\t\toptions,\n\t\t);\n\t}\n\n\tpublic static async createFromSummary(\n\t\tsummaryTree: ISummaryTree,\n\t\tnewLongClientId: string,\n\t\tspecToSeg: (spec: IJSONSegment) => ISegmentPrivate,\n\t\toptions?: PropertySet,\n\t): Promise<TestClient> {\n\t\treturn TestClient.createFromStorage(\n\t\t\tMockStorage.createFromSummary(summaryTree),\n\t\t\tnewLongClientId,\n\t\t\tspecToSeg,\n\t\t\toptions,\n\t\t);\n\t}\n\n\tpublic static async createFromStorage(\n\t\tstorage: MockStorage,\n\t\tnewLongClientId: string,\n\t\tspecToSeg: (spec: IJSONSegment) => ISegmentPrivate,\n\t\toptions?: PropertySet,\n\t): Promise<TestClient> {\n\t\tconst client2 = new TestClient(options, specToSeg);\n\t\tconst { catchupOpsP } = await client2.load(\n\t\t\t{\n\t\t\t\tlogger: client2.logger,\n\t\t\t\tclientId: newLongClientId,\n\t\t\t} as unknown as IFluidDataStoreRuntime,\n\t\t\tstorage,\n\t\t\tTestClient.serializer,\n\t\t);\n\t\tawait catchupOpsP;\n\t\treturn client2;\n\t}\n\n\tpublic readonly mergeTree: MergeTree;\n\n\tpublic readonly checkQ: DoublyLinkedList<string> = new DoublyLinkedList<string>();\n\tprotected readonly q: DoublyLinkedList<ISequencedDocumentMessage> =\n\t\tnew DoublyLinkedList<ISequencedDocumentMessage>();\n\n\tprivate readonly textHelper: MergeTreeTextHelper;\n\tconstructor(\n\t\toptions?: IMergeTreeOptions & PropertySet,\n\t\tspecToSeg = specToSegment,\n\t\tgetMinInFlightRefSeq: () => number | undefined = (): undefined => undefined,\n\t) {\n\t\tsuper(\n\t\t\tspecToSeg,\n\t\t\tcreateChildLogger({ namespace: \"fluid:testClient\" }),\n\t\t\toptions,\n\t\t\tgetMinInFlightRefSeq,\n\t\t);\n\t\tthis.mergeTree = (this as Record<\"_mergeTree\", MergeTree>)._mergeTree;\n\t\tthis.textHelper = new MergeTreeTextHelper(this.mergeTree);\n\n\t\t// Validate by default\n\t\tthis.on(\"delta\", (o, d) => {\n\t\t\t// assert.notEqual(d.deltaSegments.length, 0);\n\t\t\tfor (const s of d.deltaSegments) {\n\t\t\t\tif (d.operation === MergeTreeDeltaType.INSERT) {\n\t\t\t\t\tassertMergeNode(s.segment);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic getText(start?: number, end?: number): string {\n\t\treturn this.textHelper.getText(this.getCurrentSeq(), this.getClientId(), \"\", start, end);\n\t}\n\n\tpublic enqueueTestString(): void {\n\t\tthis.checkQ.push(this.getText());\n\t}\n\tpublic getMessageCount(): number {\n\t\treturn this.q.length;\n\t}\n\tpublic enqueueMsg(msg: ISequencedDocumentMessage): void {\n\t\tthis.q.push(msg);\n\t}\n\tpublic dequeueMsg(): ISequencedDocumentMessage | undefined {\n\t\treturn this.q.shift()?.data;\n\t}\n\tpublic applyMessages(msgCount: number): boolean {\n\t\tlet currMsgCount = msgCount;\n\t\twhile (currMsgCount > 0) {\n\t\t\tconst msg = this.dequeueMsg();\n\t\t\tif (msg) {\n\t\t\t\tthis.applyMsg(msg);\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcurrMsgCount--;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tpublic insertTextLocal(\n\t\tpos: number,\n\t\ttext: string,\n\t\tprops?: PropertySet,\n\t): IMergeTreeInsertMsg | undefined {\n\t\tconst segment = TextSegment.make(text, props);\n\t\treturn this.insertSegmentLocal(pos, segment);\n\t}\n\n\tpublic insertTextRemote(\n\t\tpos: number,\n\t\ttext: string,\n\t\tprops: PropertySet | undefined,\n\t\tseq: number,\n\t\trefSeq: number,\n\t\tlongClientId: string,\n\t): void {\n\t\tconst segment = TextSegment.make(text, props);\n\t\tthis.applyMsg(\n\t\t\tthis.makeOpMessage(createInsertSegmentOp(pos, segment), seq, refSeq, longClientId),\n\t\t);\n\t}\n\n\tpublic removeRangeRemote(\n\t\tstart: number,\n\t\tend: number,\n\t\tseq: number,\n\t\trefSeq: number,\n\t\tlongClientId: string,\n\t): void {\n\t\tthis.applyMsg(\n\t\t\tthis.makeOpMessage(createRemoveRangeOp(start, end), seq, refSeq, longClientId),\n\t\t);\n\t}\n\n\tpublic annotateRangeRemote(\n\t\tstart: number,\n\t\tend: number,\n\t\tprops: PropertySet,\n\t\tseq: number,\n\t\trefSeq: number,\n\t\tlongClientId: string,\n\t): void {\n\t\tthis.applyMsg(\n\t\t\tthis.makeOpMessage(createAnnotateRangeOp(start, end, props), seq, refSeq, longClientId),\n\t\t);\n\t}\n\n\tpublic insertMarkerLocal(\n\t\tpos: number,\n\t\tbehaviors: ReferenceType,\n\t\tprops?: PropertySet,\n\t): IMergeTreeInsertMsg | undefined {\n\t\tconst segment = Marker.make(behaviors, props);\n\n\t\treturn this.insertSegmentLocal(pos, segment);\n\t}\n\n\tpublic insertMarkerRemote(\n\t\tpos: number,\n\t\tmarkerDef: IMarkerDef,\n\t\tprops: PropertySet,\n\t\tseq: number,\n\t\trefSeq: number,\n\t\tlongClientId: string,\n\t): void {\n\t\tconst segment = Marker.make(markerDef.refType ?? ReferenceType.Tile, props);\n\n\t\tthis.applyMsg(\n\t\t\tthis.makeOpMessage(createInsertSegmentOp(pos, segment), seq, refSeq, longClientId),\n\t\t);\n\t}\n\n\tpublic relText(clientId: number, refSeq: number): string {\n\t\treturn `cli: ${this.getLongClientId(\n\t\t\tclientId,\n\t\t)} refSeq: ${refSeq}: ${this.textHelper.getText(refSeq, clientId)}`;\n\t}\n\n\tpublic makeOpMessage(\n\t\top: IMergeTreeOp | undefined,\n\t\tseq: number = UnassignedSequenceNumber,\n\t\trefSeq: number = this.getCurrentSeq(),\n\t\tlongClientId?: string,\n\t\tminSeqNumber = 0,\n\t): ISequencedDocumentMessage {\n\t\tif (op === undefined) {\n\t\t\tthrow new Error(\"op cannot be undefined\");\n\t\t}\n\t\tconst msg: ISequencedDocumentMessage = {\n\t\t\tclientId: longClientId ?? this.longClientId ?? \"\",\n\t\t\tclientSequenceNumber: 1,\n\t\t\tcontents: op,\n\t\t\tmetadata: undefined,\n\t\t\tminimumSequenceNumber: minSeqNumber,\n\t\t\treferenceSequenceNumber: refSeq,\n\t\t\tsequenceNumber: seq,\n\t\t\ttimestamp: Date.now(),\n\t\t\ttraces: [],\n\t\t\ttype: MessageType.Operation,\n\t\t};\n\t\treturn msg;\n\t}\n\n\tpublic validate(): void {\n\t\tassert(nodeOrdinalsHaveIntegrity(this.mergeTree.root));\n\t}\n\n\tpublic searchFromPos(\n\t\tpos: number,\n\t\ttarget: RegExp,\n\t): { text: string; pos: number } | undefined {\n\t\tlet start = pos;\n\t\tlet chunk = \"\";\n\t\twhile (start < this.getLength()) {\n\t\t\tchunk = this.getText(start, start + TestClient.searchChunkSize);\n\n\t\t\tconst result = chunk.match(target);\n\t\t\tif (result?.index) {\n\t\t\t\treturn { text: result[0], pos: result.index + start };\n\t\t\t}\n\t\t\tstart += TestClient.searchChunkSize;\n\t\t}\n\t}\n\n\tpublic findRandomWord(): { text: string; pos: number } | undefined {\n\t\tconst len = this.getLength();\n\t\tconst pos = random.integer(0, len);\n\t\tconst nextWord = this.searchFromPos(pos, /\\s\\w+\\b/);\n\t\treturn nextWord;\n\t}\n\n\tpublic debugDumpTree(tree: MergeTree): void {\n\t\t// want the segment's content and the state of insert/remove\n\t\tconst test: string[] = [];\n\t\twalkAllChildSegments(tree.root, (segment: ISegmentPrivate) => {\n\t\t\tconst prefixes: (string | undefined | number)[] = [];\n\t\t\tassertInserted(segment);\n\t\t\tprefixes.push(\n\t\t\t\tsegment.seq === UnassignedSequenceNumber ? `L${segment.localSeq}` : segment.seq,\n\t\t\t);\n\t\t\tif (isRemoved(segment)) {\n\t\t\t\tprefixes.push(\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber\n\t\t\t\t\t\t? `L${segment.localRemovedSeq}`\n\t\t\t\t\t\t: segment.removedSeq,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\t\ttest.push(`${prefixes.join(\",\")}:${(segment as any).text}`);\n\t\t});\n\t}\n\n\t/**\n\t * Rebases a (local) position from the perspective `{ seq: seqNumberFrom, localSeq }` to the perspective\n\t * of the current sequence number. This is desirable when rebasing operations for reconnection. Perform\n\t * slow-path computations in this function without leveraging the merge-tree's structure\n\t */\n\tpublic rebasePosition(pos: number, seqNumberFrom: number, localSeq: number): number {\n\t\tlet segment: ISegmentPrivate | undefined;\n\t\tlet posAccumulated = 0;\n\t\tlet offset = pos;\n\t\tconst isInsertedInView = (seg: ISegmentPrivate): boolean =>\n\t\t\tisInserted(seg) &&\n\t\t\t((seg.seq !== UnassignedSequenceNumber && seg.seq <= seqNumberFrom) ||\n\t\t\t\t(seg.localSeq !== undefined && seg.localSeq <= localSeq));\n\n\t\tconst isRemovedFromView = (s: ISegmentPrivate): boolean =>\n\t\t\tisRemoved(s) &&\n\t\t\t((s.removedSeq !== UnassignedSequenceNumber && s.removedSeq <= seqNumberFrom) ||\n\t\t\t\t(s.localRemovedSeq !== undefined && s.localRemovedSeq <= localSeq));\n\n\t\twalkAllChildSegments(this.mergeTree.root, (seg) => {\n\t\t\tassertInserted(seg);\n\t\t\tsegment = seg;\n\n\t\t\tif (isInsertedInView(seg) && !isRemovedFromView(seg)) {\n\t\t\t\tposAccumulated += seg.cachedLength;\n\t\t\t\tif (offset >= seg.cachedLength) {\n\t\t\t\t\toffset -= seg.cachedLength;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Keep going while we've yet to reach the segment at the desired position\n\t\t\treturn posAccumulated <= pos;\n\t\t});\n\n\t\tassert(segment !== undefined, \"No segment found\");\n\t\tconst segoff = getSlideToSegoff({ segment, offset }) ?? segment;\n\t\tif (segoff.segment === undefined || segoff.offset === undefined) {\n\t\t\treturn DetachedReferencePosition;\n\t\t}\n\n\t\treturn this.findReconnectionPosition(segoff.segment, localSeq) + segoff.offset;\n\t}\n\n\tpublic findReconnectionPosition(segment: ISegmentPrivate, localSeq: number): number {\n\t\tconst fasterComputedPosition = super.findReconnectionPosition(segment, localSeq);\n\n\t\tlet segmentPosition = 0;\n\t\tconst isInsertedInView = (seg: ISegmentPrivate): boolean =>\n\t\t\tisInserted(seg) && (seg.localSeq === undefined || seg.localSeq <= localSeq);\n\t\tconst isRemovedFromView = (s: ISegmentPrivate): boolean =>\n\t\t\tisRemoved(s) &&\n\t\t\t(s.removedSeq !== UnassignedSequenceNumber ||\n\t\t\t\t(s.localRemovedSeq !== undefined && s.localRemovedSeq <= localSeq));\n\t\tconst isMovedFromView = (s: ISegmentPrivate): boolean =>\n\t\t\tisMoved(s) &&\n\t\t\t(s.movedSeq !== UnassignedSequenceNumber ||\n\t\t\t\t(s.localMovedSeq !== undefined && s.localMovedSeq <= localSeq));\n\t\t/*\n Walk the segments up to the current segment, and calculate its\n position taking into account local segments that were modified,\n after the current segment.\n */\n\t\twalkAllChildSegments(this.mergeTree.root, (seg) => {\n\t\t\t// If we've found the desired segment, terminate the walk and return 'segmentPosition'.\n\t\t\tif (seg === segment) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Otherwise, advance segmentPosition if the segment has been inserted and not removed\n\t\t\t// with respect to the given 'localSeq'.\n\t\t\t//\n\t\t\t// Note that all ACKed / remote ops are applied and we only need concern ourself with\n\t\t\t// determining if locally pending ops fall before/after the given 'localSeq'.\n\t\t\tif (isInsertedInView(seg) && !isRemovedFromView(seg) && !isMovedFromView(seg)) {\n\t\t\t\tsegmentPosition += seg.cachedLength;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t});\n\n\t\tassert.equal(\n\t\t\tfasterComputedPosition,\n\t\t\tsegmentPosition,\n\t\t\t\"Expected fast-path computation to match result from walk all segments\",\n\t\t);\n\t\treturn segmentPosition;\n\t}\n\n\t/**\n\t * Validates segments either all have attribution information or none of them.\n\t * If no segment has attribution information, returns undefined.\n\t *\n\t * @param channel - Attribution channel name to request information from.\n\t * @returns an array of all attribution seq#s from the current perspective.\n\t * The `i`th entry of the array is the attribution key for the character at position `i`.\n\t */\n\tpublic getAllAttributionSeqs(channel?: string): (number | AttributionKey | undefined)[] {\n\t\tconst seqs: (number | AttributionKey | undefined)[] = [];\n\t\tthis.walkAllSegments((segment) => {\n\t\t\tfor (let i = 0; i < segment.cachedLength; i++) {\n\t\t\t\tconst key = segment.attribution?.getAtOffset(i, channel);\n\t\t\t\tseqs.push(key?.type === \"op\" ? key.seq : key);\n\t\t\t}\n\t\t\treturn true;\n\t\t});\n\n\t\treturn seqs;\n\t}\n\n\tpublic peekPendingSegmentGroups(): SegmentGroup | undefined;\n\tpublic peekPendingSegmentGroups(count: number): SegmentGroup | SegmentGroup[] | undefined;\n\tpublic peekPendingSegmentGroups(\n\t\tcount: number = 1,\n\t): SegmentGroup | SegmentGroup[] | undefined {\n\t\treturn super.peekPendingSegmentGroups(count) as SegmentGroup | SegmentGroup[] | undefined;\n\t}\n\n\t/**\n\t * Override and add some test only metrics\n\t */\n\tpublic applyMsg(msg: ISequencedDocumentMessage, local: boolean = false): void {\n\t\tlet traceStart: Trace | undefined;\n\t\tif (this.measureOps) {\n\t\t\ttraceStart = Trace.start();\n\t\t}\n\n\t\tsuper.applyMsg(msg, local);\n\n\t\tif (traceStart) {\n\t\t\tthis.accumTime += elapsedMicroseconds(traceStart);\n\t\t\tthis.accumOps++;\n\t\t\tthis.accumWindow += this.getCurrentSeq() - this.getCollabWindow().minSeq;\n\t\t}\n\t}\n\n\t/**\n\t * Override and add some test only metrics\n\t */\n\tupdateMinSeq(minSeq: number): void {\n\t\tlet trace: Trace | undefined;\n\t\tif (this.measureOps) {\n\t\t\ttrace = Trace.start();\n\t\t}\n\n\t\tsuper.updateMinSeq(minSeq);\n\t\tif (trace) {\n\t\t\tconst elapsed = elapsedMicroseconds(trace);\n\t\t\tthis.accumWindowTime += elapsed;\n\t\t\tif (elapsed > this.maxWindowTime) {\n\t\t\t\tthis.maxWindowTime = elapsed;\n\t\t\t}\n\t\t}\n\t}\n\n\tslowSearchForMarker(\n\t\tstartPos: number,\n\t\tmarkerLabel: string,\n\t\tforwards = true,\n\t): ReferencePosition | undefined {\n\t\tlet foundMarker: Marker | undefined;\n\n\t\tconst { segment } = this.getContainingSegment<ISegmentPrivate>(startPos);\n\t\tassertSegmentLeaf(segment);\n\t\tif (Marker.is(segment)) {\n\t\t\tif (refHasTileLabel(segment, markerLabel)) {\n\t\t\t\tfoundMarker = segment;\n\t\t\t}\n\t\t} else {\n\t\t\tif (forwards) {\n\t\t\t\tforwardExcursion(segment, (seg) => {\n\t\t\t\t\tif (Marker.is(seg) && refHasTileLabel(seg, markerLabel)) {\n\t\t\t\t\t\tfoundMarker = seg;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tbackwardExcursion(segment, (seg) => {\n\t\t\t\t\tif (Marker.is(seg) && refHasTileLabel(seg, markerLabel)) {\n\t\t\t\t\t\tfoundMarker = seg;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn foundMarker;\n\t}\n}\n\nfunction elapsedMicroseconds(trace: Trace): number {\n\treturn trace.trace().duration * 1000;\n}\n\n// the client doesn't submit ops, so this adds a callback to capture them\nexport type TestClientRevertibleDriver = MergeTreeRevertibleDriver &\n\tPartial<{ submitOpCallback?: (op: IMergeTreeOp | undefined) => void }>;\n\nexport const createRevertDriver = (client: TestClient): TestClientRevertibleDriver => {\n\treturn {\n\t\tremoveRange(start: number, end: number): void {\n\t\t\tconst op = client.removeRangeLocal(start, end);\n\t\t\tthis.submitOpCallback?.(op);\n\t\t},\n\t\tannotateRange(start: number, end: number, props: PropertySet): void {\n\t\t\tconst op = client.annotateRangeLocal(start, end, props);\n\t\t\tthis.submitOpCallback?.(op);\n\t\t},\n\t\tinsertFromSpec(pos: number, spec: IJSONSegment): void {\n\t\t\tconst op = client.insertSegmentLocal(pos, client.specToSegment(spec));\n\t\t\tthis.submitOpCallback?.(op);\n\t\t},\n\t};\n};\n\nexport interface MergeTreeStats {\n\tmaxHeight: number;\n\tnodeCount: number;\n\tleafCount: number;\n\tremovedLeafCount: number;\n\tliveCount: number;\n\thisto: number[];\n\twindowTime?: number;\n\tpackTime?: number;\n\tordTime?: number;\n\tmaxOrdTime?: number;\n}\n\nexport function getStats(tree: MergeTree): MergeTreeStats {\n\tconst nodeGetStats = (block: MergeBlock): MergeTreeStats => {\n\t\tconst stats: MergeTreeStats = {\n\t\t\tmaxHeight: 0,\n\t\t\tnodeCount: 0,\n\t\t\tleafCount: 0,\n\t\t\tremovedLeafCount: 0,\n\t\t\tliveCount: 0,\n\t\t\thisto: [],\n\t\t};\n\t\tfor (let k = 0; k < MaxNodesInBlock; k++) {\n\t\t\tstats.histo[k] = 0;\n\t\t}\n\t\tfor (let i = 0; i < block.childCount; i++) {\n\t\t\tconst child = block.children[i];\n\t\t\tlet height = 1;\n\t\t\tif (child.isLeaf()) {\n\t\t\t\tstats.leafCount++;\n\t\t\t\tconst segment = child;\n\t\t\t\tif (isRemoved(segment)) {\n\t\t\t\t\tstats.removedLeafCount++;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst childStats = nodeGetStats(child);\n\t\t\t\theight = 1 + childStats.maxHeight;\n\t\t\t\tstats.nodeCount += childStats.nodeCount;\n\t\t\t\tstats.leafCount += childStats.leafCount;\n\t\t\t\tstats.removedLeafCount += childStats.removedLeafCount;\n\t\t\t\tstats.liveCount += childStats.liveCount;\n\t\t\t\tfor (let j = 0; j < MaxNodesInBlock; j++) {\n\t\t\t\t\tstats.histo[j] += childStats.histo[j];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (height > stats.maxHeight) {\n\t\t\t\tstats.maxHeight = height;\n\t\t\t}\n\t\t}\n\t\tstats.histo[block.childCount]++;\n\t\tstats.nodeCount++;\n\t\tstats.liveCount += block.childCount;\n\t\treturn stats;\n\t};\n\tconst rootStats = nodeGetStats(tree.root);\n\treturn rootStats;\n}\n"]}
1
+ {"version":3,"file":"testClient.js","sourceRoot":"","sources":["../../src/test/testClient.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 { Trace } from \"@fluid-internal/client-utils\";\nimport { makeRandom } from \"@fluid-private/stochastic-test-utils\";\nimport { IFluidDataStoreRuntime } from \"@fluidframework/datastore-definitions/internal\";\nimport { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport {\n\tITree,\n\tMessageType,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { AttributionKey } from \"@fluidframework/runtime-definitions/internal\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils/internal\";\nimport { MockStorage } from \"@fluidframework/test-runtime-utils/internal\";\n\nimport { MergeTreeTextHelper } from \"../MergeTreeTextHelper.js\";\nimport { Client } from \"../client.js\";\nimport { DoublyLinkedList } from \"../collections/index.js\";\nimport { UnassignedSequenceNumber } from \"../constants.js\";\nimport { IMergeTreeOptions, ReferencePosition } from \"../index.js\";\nimport { MergeTree, getSlideToSegoff } from \"../mergeTree.js\";\nimport {\n\tbackwardExcursion,\n\tforwardExcursion,\n\twalkAllChildSegments,\n} from \"../mergeTreeNodeWalk.js\";\nimport {\n\tMergeBlock,\n\tISegmentPrivate,\n\tMarker,\n\tMaxNodesInBlock,\n\ttype SegmentGroup,\n\tassertSegmentLeaf,\n} from \"../mergeTreeNodes.js\";\nimport {\n\tcreateAnnotateRangeOp,\n\tcreateInsertSegmentOp,\n\tcreateRemoveRangeOp,\n} from \"../opBuilder.js\";\nimport {\n\tIJSONSegment,\n\tIMarkerDef,\n\tIMergeTreeOp,\n\tMergeTreeDeltaType,\n\tReferenceType,\n\ttype IMergeTreeInsertMsg,\n} from \"../ops.js\";\nimport { PropertySet } from \"../properties.js\";\nimport { DetachedReferencePosition, refHasTileLabel } from \"../referencePositions.js\";\nimport { MergeTreeRevertibleDriver } from \"../revertibles.js\";\nimport {\n\tassertInserted,\n\tassertMergeNode,\n\tisInserted,\n\tisMoved,\n\tisRemoved,\n} from \"../segmentInfos.js\";\nimport { SnapshotLegacy } from \"../snapshotlegacy.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestSerializer } from \"./testSerializer.js\";\nimport { nodeOrdinalsHaveIntegrity } from \"./testUtils.js\";\n\nexport function specToSegment(spec: IJSONSegment): ISegmentPrivate {\n\tconst maybeText = TextSegment.fromJSONObject(spec);\n\tif (maybeText) {\n\t\treturn maybeText;\n\t}\n\n\tconst maybeMarker = Marker.fromJSONObject(spec);\n\tif (maybeMarker) {\n\t\treturn maybeMarker;\n\t}\n\n\tthrow new Error(`Unrecognized IJSONSegment type: '${JSON.stringify(spec)}'`);\n}\n\nconst random = makeRandom(0xdeadbeef, 0xfeedbed);\n\nexport class TestClient extends Client {\n\tpublic static searchChunkSize = 256;\n\tpublic static readonly serializer = new TestSerializer();\n\tpublic measureOps = false;\n\tpublic accumTime = 0;\n\tpublic accumWindowTime = 0;\n\tpublic accumWindow = 0;\n\tpublic accumOps = 0;\n\tpublic maxWindowTime = 0;\n\n\t/**\n\t * Used for in-memory testing. This will queue a reference string for each client message.\n\t */\n\tpublic static useCheckQ = false;\n\n\tpublic static async createFromClientSnapshot(\n\t\tclient1: TestClient,\n\t\tnewLongClientId: string,\n\t): Promise<TestClient> {\n\t\tconst snapshot = new SnapshotLegacy(\n\t\t\tclient1.mergeTree,\n\t\t\tcreateChildLogger({ namespace: \"fluid:snapshot\" }),\n\t\t);\n\t\tsnapshot.extractSync();\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst summaryTree = snapshot.emit([], TestClient.serializer, undefined!).summary;\n\t\treturn TestClient.createFromSummary(\n\t\t\tsummaryTree,\n\t\t\tnewLongClientId,\n\t\t\tclient1.specToSegment,\n\t\t\tclient1.mergeTree.options,\n\t\t);\n\t}\n\n\tpublic static async createFromSnapshot(\n\t\tsnapshotTree: ITree,\n\t\tnewLongClientId: string,\n\t\tspecToSeg: (spec: IJSONSegment) => ISegmentPrivate,\n\t\toptions?: PropertySet,\n\t): Promise<TestClient> {\n\t\treturn TestClient.createFromStorage(\n\t\t\tnew MockStorage(snapshotTree),\n\t\t\tnewLongClientId,\n\t\t\tspecToSeg,\n\t\t\toptions,\n\t\t);\n\t}\n\n\tpublic static async createFromSummary(\n\t\tsummaryTree: ISummaryTree,\n\t\tnewLongClientId: string,\n\t\tspecToSeg: (spec: IJSONSegment) => ISegmentPrivate,\n\t\toptions?: PropertySet,\n\t): Promise<TestClient> {\n\t\treturn TestClient.createFromStorage(\n\t\t\tMockStorage.createFromSummary(summaryTree),\n\t\t\tnewLongClientId,\n\t\t\tspecToSeg,\n\t\t\toptions,\n\t\t);\n\t}\n\n\tpublic static async createFromStorage(\n\t\tstorage: MockStorage,\n\t\tnewLongClientId: string,\n\t\tspecToSeg: (spec: IJSONSegment) => ISegmentPrivate,\n\t\toptions?: PropertySet,\n\t): Promise<TestClient> {\n\t\tconst client2 = new TestClient(options, specToSeg);\n\t\tconst { catchupOpsP } = await client2.load(\n\t\t\t{\n\t\t\t\tlogger: client2.logger,\n\t\t\t\tclientId: newLongClientId,\n\t\t\t} as unknown as IFluidDataStoreRuntime,\n\t\t\tstorage,\n\t\t\tTestClient.serializer,\n\t\t);\n\t\tawait catchupOpsP;\n\t\treturn client2;\n\t}\n\n\tpublic readonly mergeTree: MergeTree;\n\n\tpublic readonly checkQ: DoublyLinkedList<string> = new DoublyLinkedList<string>();\n\tprotected readonly q: DoublyLinkedList<ISequencedDocumentMessage> =\n\t\tnew DoublyLinkedList<ISequencedDocumentMessage>();\n\n\tprivate readonly textHelper: MergeTreeTextHelper;\n\tconstructor(\n\t\toptions?: IMergeTreeOptions & PropertySet,\n\t\tspecToSeg = specToSegment,\n\t\tgetMinInFlightRefSeq: () => number | undefined = (): undefined => undefined,\n\t) {\n\t\tsuper(\n\t\t\tspecToSeg,\n\t\t\tcreateChildLogger({ namespace: \"fluid:testClient\" }),\n\t\t\toptions,\n\t\t\tgetMinInFlightRefSeq,\n\t\t);\n\t\tthis.mergeTree = (this as Record<\"_mergeTree\", MergeTree>)._mergeTree;\n\t\tthis.textHelper = new MergeTreeTextHelper(this.mergeTree);\n\n\t\t// Validate by default\n\t\tthis.on(\"delta\", (o, d) => {\n\t\t\t// assert.notEqual(d.deltaSegments.length, 0);\n\t\t\tfor (const s of d.deltaSegments) {\n\t\t\t\tif (d.operation === MergeTreeDeltaType.INSERT) {\n\t\t\t\t\tassertMergeNode(s.segment);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic getText(start?: number, end?: number): string {\n\t\treturn this.textHelper.getText(this.getCurrentSeq(), this.getClientId(), \"\", start, end);\n\t}\n\n\tpublic enqueueTestString(): void {\n\t\tthis.checkQ.push(this.getText());\n\t}\n\tpublic getMessageCount(): number {\n\t\treturn this.q.length;\n\t}\n\tpublic enqueueMsg(msg: ISequencedDocumentMessage): void {\n\t\tthis.q.push(msg);\n\t}\n\tpublic dequeueMsg(): ISequencedDocumentMessage | undefined {\n\t\treturn this.q.shift()?.data;\n\t}\n\tpublic applyMessages(msgCount: number): boolean {\n\t\tlet currMsgCount = msgCount;\n\t\twhile (currMsgCount > 0) {\n\t\t\tconst msg = this.dequeueMsg();\n\t\t\tif (msg) {\n\t\t\t\tthis.applyMsg(msg);\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcurrMsgCount--;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tpublic insertTextLocal(\n\t\tpos: number,\n\t\ttext: string,\n\t\tprops?: PropertySet,\n\t): IMergeTreeInsertMsg | undefined {\n\t\tconst segment = TextSegment.make(text, props);\n\t\treturn this.insertSegmentLocal(pos, segment);\n\t}\n\n\tpublic insertTextRemote(\n\t\tpos: number,\n\t\ttext: string,\n\t\tprops: PropertySet | undefined,\n\t\tseq: number,\n\t\trefSeq: number,\n\t\tlongClientId: string,\n\t): void {\n\t\tconst segment = TextSegment.make(text, props);\n\t\tthis.applyMsg(\n\t\t\tthis.makeOpMessage(createInsertSegmentOp(pos, segment), seq, refSeq, longClientId),\n\t\t);\n\t}\n\n\tpublic removeRangeRemote(\n\t\tstart: number,\n\t\tend: number,\n\t\tseq: number,\n\t\trefSeq: number,\n\t\tlongClientId: string,\n\t): void {\n\t\tthis.applyMsg(\n\t\t\tthis.makeOpMessage(createRemoveRangeOp(start, end), seq, refSeq, longClientId),\n\t\t);\n\t}\n\n\tpublic annotateRangeRemote(\n\t\tstart: number,\n\t\tend: number,\n\t\tprops: PropertySet,\n\t\tseq: number,\n\t\trefSeq: number,\n\t\tlongClientId: string,\n\t): void {\n\t\tthis.applyMsg(\n\t\t\tthis.makeOpMessage(createAnnotateRangeOp(start, end, props), seq, refSeq, longClientId),\n\t\t);\n\t}\n\n\tpublic insertMarkerLocal(\n\t\tpos: number,\n\t\tbehaviors: ReferenceType,\n\t\tprops?: PropertySet,\n\t): IMergeTreeInsertMsg | undefined {\n\t\tconst segment = Marker.make(behaviors, props);\n\n\t\treturn this.insertSegmentLocal(pos, segment);\n\t}\n\n\tpublic insertMarkerRemote(\n\t\tpos: number,\n\t\tmarkerDef: IMarkerDef,\n\t\tprops: PropertySet,\n\t\tseq: number,\n\t\trefSeq: number,\n\t\tlongClientId: string,\n\t): void {\n\t\tconst segment = Marker.make(markerDef.refType ?? ReferenceType.Tile, props);\n\n\t\tthis.applyMsg(\n\t\t\tthis.makeOpMessage(createInsertSegmentOp(pos, segment), seq, refSeq, longClientId),\n\t\t);\n\t}\n\n\tpublic relText(clientId: number, refSeq: number): string {\n\t\treturn `cli: ${this.getLongClientId(\n\t\t\tclientId,\n\t\t)} refSeq: ${refSeq}: ${this.textHelper.getText(refSeq, clientId)}`;\n\t}\n\n\tpublic makeOpMessage(\n\t\top: IMergeTreeOp | undefined,\n\t\tseq: number = UnassignedSequenceNumber,\n\t\trefSeq: number = this.getCurrentSeq(),\n\t\tlongClientId?: string,\n\t\tminSeqNumber = 0,\n\t): ISequencedDocumentMessage {\n\t\tif (op === undefined) {\n\t\t\tthrow new Error(\"op cannot be undefined\");\n\t\t}\n\t\tconst msg: ISequencedDocumentMessage = {\n\t\t\tclientId: longClientId ?? this.longClientId ?? \"\",\n\t\t\tclientSequenceNumber: 1,\n\t\t\tcontents: op,\n\t\t\tmetadata: undefined,\n\t\t\tminimumSequenceNumber: minSeqNumber,\n\t\t\treferenceSequenceNumber: refSeq,\n\t\t\tsequenceNumber: seq,\n\t\t\ttimestamp: Date.now(),\n\t\t\ttraces: [],\n\t\t\ttype: MessageType.Operation,\n\t\t};\n\t\treturn msg;\n\t}\n\n\tpublic validate(): void {\n\t\tassert(nodeOrdinalsHaveIntegrity(this.mergeTree.root));\n\t}\n\n\tpublic searchFromPos(\n\t\tpos: number,\n\t\ttarget: RegExp,\n\t): { text: string; pos: number } | undefined {\n\t\tlet start = pos;\n\t\tlet chunk = \"\";\n\t\twhile (start < this.getLength()) {\n\t\t\tchunk = this.getText(start, start + TestClient.searchChunkSize);\n\n\t\t\tconst result = chunk.match(target);\n\t\t\tif (result?.index) {\n\t\t\t\treturn { text: result[0], pos: result.index + start };\n\t\t\t}\n\t\t\tstart += TestClient.searchChunkSize;\n\t\t}\n\t}\n\n\tpublic findRandomWord(): { text: string; pos: number } | undefined {\n\t\tconst len = this.getLength();\n\t\tconst pos = random.integer(0, len);\n\t\tconst nextWord = this.searchFromPos(pos, /\\s\\w+\\b/);\n\t\treturn nextWord;\n\t}\n\n\tpublic debugDumpTree(tree: MergeTree): string[] {\n\t\t// want the segment's content and the state of insert/remove\n\t\tconst test: string[] = [];\n\t\twalkAllChildSegments(tree.root, (segment: ISegmentPrivate) => {\n\t\t\tconst prefixes: (string | undefined | number)[] = [];\n\t\t\tassertInserted(segment);\n\t\t\tprefixes.push(\n\t\t\t\tsegment.seq === UnassignedSequenceNumber ? `L${segment.localSeq}` : segment.seq,\n\t\t\t);\n\t\t\tif (isRemoved(segment)) {\n\t\t\t\tprefixes.push(\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber\n\t\t\t\t\t\t? `L${segment.localRemovedSeq}`\n\t\t\t\t\t\t: segment.removedSeq,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\t\ttest.push(`${prefixes.join(\",\")}:${(segment as any).text}`);\n\t\t});\n\t\treturn test;\n\t}\n\n\t/**\n\t * Rebases a (local) position from the perspective `{ seq: seqNumberFrom, localSeq }` to the perspective\n\t * of the current sequence number. This is desirable when rebasing operations for reconnection. Perform\n\t * slow-path computations in this function without leveraging the merge-tree's structure\n\t */\n\tpublic rebasePosition(pos: number, seqNumberFrom: number, localSeq: number): number {\n\t\tlet segment: ISegmentPrivate | undefined;\n\t\tlet posAccumulated = 0;\n\t\tlet offset = pos;\n\t\tconst isInsertedInView = (seg: ISegmentPrivate): boolean =>\n\t\t\tisInserted(seg) &&\n\t\t\t((seg.seq !== UnassignedSequenceNumber && seg.seq <= seqNumberFrom) ||\n\t\t\t\t(seg.localSeq !== undefined && seg.localSeq <= localSeq));\n\n\t\tconst isRemovedFromView = (s: ISegmentPrivate): boolean =>\n\t\t\tisRemoved(s) &&\n\t\t\t((s.removedSeq !== UnassignedSequenceNumber && s.removedSeq <= seqNumberFrom) ||\n\t\t\t\t(s.localRemovedSeq !== undefined && s.localRemovedSeq <= localSeq));\n\n\t\twalkAllChildSegments(this.mergeTree.root, (seg) => {\n\t\t\tassertInserted(seg);\n\t\t\tsegment = seg;\n\n\t\t\tif (isInsertedInView(seg) && !isRemovedFromView(seg)) {\n\t\t\t\tposAccumulated += seg.cachedLength;\n\t\t\t\tif (offset >= seg.cachedLength) {\n\t\t\t\t\toffset -= seg.cachedLength;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Keep going while we've yet to reach the segment at the desired position\n\t\t\treturn posAccumulated <= pos;\n\t\t});\n\n\t\tassert(segment !== undefined, \"No segment found\");\n\t\tconst segoff = getSlideToSegoff({ segment, offset }) ?? segment;\n\t\tif (segoff.segment === undefined || segoff.offset === undefined) {\n\t\t\treturn DetachedReferencePosition;\n\t\t}\n\n\t\treturn this.findReconnectionPosition(segoff.segment, localSeq) + segoff.offset;\n\t}\n\n\tpublic findReconnectionPosition(segment: ISegmentPrivate, localSeq: number): number {\n\t\tconst fasterComputedPosition = super.findReconnectionPosition(segment, localSeq);\n\n\t\tlet segmentPosition = 0;\n\t\tconst isInsertedInView = (seg: ISegmentPrivate): boolean =>\n\t\t\tisInserted(seg) && (seg.localSeq === undefined || seg.localSeq <= localSeq);\n\t\tconst isRemovedFromView = (s: ISegmentPrivate): boolean =>\n\t\t\tisRemoved(s) &&\n\t\t\t(s.removedSeq !== UnassignedSequenceNumber ||\n\t\t\t\t(s.localRemovedSeq !== undefined && s.localRemovedSeq <= localSeq));\n\t\tconst isMovedFromView = (s: ISegmentPrivate): boolean =>\n\t\t\tisMoved(s) &&\n\t\t\t(s.movedSeq !== UnassignedSequenceNumber ||\n\t\t\t\t(s.localMovedSeq !== undefined && s.localMovedSeq <= localSeq));\n\t\t/*\n Walk the segments up to the current segment, and calculate its\n position taking into account local segments that were modified,\n after the current segment.\n */\n\t\twalkAllChildSegments(this.mergeTree.root, (seg) => {\n\t\t\t// If we've found the desired segment, terminate the walk and return 'segmentPosition'.\n\t\t\tif (seg === segment) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Otherwise, advance segmentPosition if the segment has been inserted and not removed\n\t\t\t// with respect to the given 'localSeq'.\n\t\t\t//\n\t\t\t// Note that all ACKed / remote ops are applied and we only need concern ourself with\n\t\t\t// determining if locally pending ops fall before/after the given 'localSeq'.\n\t\t\tif (isInsertedInView(seg) && !isRemovedFromView(seg) && !isMovedFromView(seg)) {\n\t\t\t\tsegmentPosition += seg.cachedLength;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t});\n\n\t\tassert.equal(\n\t\t\tfasterComputedPosition,\n\t\t\tsegmentPosition,\n\t\t\t\"Expected fast-path computation to match result from walk all segments\",\n\t\t);\n\t\treturn segmentPosition;\n\t}\n\n\t/**\n\t * Validates segments either all have attribution information or none of them.\n\t * If no segment has attribution information, returns undefined.\n\t *\n\t * @param channel - Attribution channel name to request information from.\n\t * @returns an array of all attribution seq#s from the current perspective.\n\t * The `i`th entry of the array is the attribution key for the character at position `i`.\n\t */\n\tpublic getAllAttributionSeqs(channel?: string): (number | AttributionKey | undefined)[] {\n\t\tconst seqs: (number | AttributionKey | undefined)[] = [];\n\t\tthis.walkAllSegments((segment) => {\n\t\t\tfor (let i = 0; i < segment.cachedLength; i++) {\n\t\t\t\tconst key = segment.attribution?.getAtOffset(i, channel);\n\t\t\t\tseqs.push(key?.type === \"op\" ? key.seq : key);\n\t\t\t}\n\t\t\treturn true;\n\t\t});\n\n\t\treturn seqs;\n\t}\n\n\tpublic peekPendingSegmentGroups(): SegmentGroup | undefined;\n\tpublic peekPendingSegmentGroups(count: number): SegmentGroup | SegmentGroup[] | undefined;\n\tpublic peekPendingSegmentGroups(\n\t\tcount: number = 1,\n\t): SegmentGroup | SegmentGroup[] | undefined {\n\t\treturn super.peekPendingSegmentGroups(count) as SegmentGroup | SegmentGroup[] | undefined;\n\t}\n\n\t/**\n\t * Override and add some test only metrics\n\t */\n\tpublic applyMsg(msg: ISequencedDocumentMessage, local: boolean = false): void {\n\t\tlet traceStart: Trace | undefined;\n\t\tif (this.measureOps) {\n\t\t\ttraceStart = Trace.start();\n\t\t}\n\n\t\tsuper.applyMsg(msg, local);\n\n\t\tif (traceStart) {\n\t\t\tthis.accumTime += elapsedMicroseconds(traceStart);\n\t\t\tthis.accumOps++;\n\t\t\tthis.accumWindow += this.getCurrentSeq() - this.getCollabWindow().minSeq;\n\t\t}\n\t}\n\n\t/**\n\t * Override and add some test only metrics\n\t */\n\tupdateMinSeq(minSeq: number): void {\n\t\tlet trace: Trace | undefined;\n\t\tif (this.measureOps) {\n\t\t\ttrace = Trace.start();\n\t\t}\n\n\t\tsuper.updateMinSeq(minSeq);\n\t\tif (trace) {\n\t\t\tconst elapsed = elapsedMicroseconds(trace);\n\t\t\tthis.accumWindowTime += elapsed;\n\t\t\tif (elapsed > this.maxWindowTime) {\n\t\t\t\tthis.maxWindowTime = elapsed;\n\t\t\t}\n\t\t}\n\t}\n\n\tslowSearchForMarker(\n\t\tstartPos: number,\n\t\tmarkerLabel: string,\n\t\tforwards = true,\n\t): ReferencePosition | undefined {\n\t\tlet foundMarker: Marker | undefined;\n\n\t\tconst { segment } = this.getContainingSegment<ISegmentPrivate>(startPos);\n\t\tassertSegmentLeaf(segment);\n\t\tif (Marker.is(segment)) {\n\t\t\tif (refHasTileLabel(segment, markerLabel)) {\n\t\t\t\tfoundMarker = segment;\n\t\t\t}\n\t\t} else {\n\t\t\tif (forwards) {\n\t\t\t\tforwardExcursion(segment, (seg) => {\n\t\t\t\t\tif (Marker.is(seg) && refHasTileLabel(seg, markerLabel)) {\n\t\t\t\t\t\tfoundMarker = seg;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tbackwardExcursion(segment, (seg) => {\n\t\t\t\t\tif (Marker.is(seg) && refHasTileLabel(seg, markerLabel)) {\n\t\t\t\t\t\tfoundMarker = seg;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn foundMarker;\n\t}\n}\n\nfunction elapsedMicroseconds(trace: Trace): number {\n\treturn trace.trace().duration * 1000;\n}\n\n// the client doesn't submit ops, so this adds a callback to capture them\nexport type TestClientRevertibleDriver = MergeTreeRevertibleDriver &\n\tPartial<{ submitOpCallback?: (op: IMergeTreeOp | undefined) => void }>;\n\nexport const createRevertDriver = (client: TestClient): TestClientRevertibleDriver => {\n\treturn {\n\t\tremoveRange(start: number, end: number): void {\n\t\t\tconst op = client.removeRangeLocal(start, end);\n\t\t\tthis.submitOpCallback?.(op);\n\t\t},\n\t\tannotateRange(start: number, end: number, props: PropertySet): void {\n\t\t\tconst op = client.annotateRangeLocal(start, end, props);\n\t\t\tthis.submitOpCallback?.(op);\n\t\t},\n\t\tinsertFromSpec(pos: number, spec: IJSONSegment): void {\n\t\t\tconst op = client.insertSegmentLocal(pos, client.specToSegment(spec));\n\t\t\tthis.submitOpCallback?.(op);\n\t\t},\n\t};\n};\n\nexport interface MergeTreeStats {\n\tmaxHeight: number;\n\tnodeCount: number;\n\tleafCount: number;\n\tremovedLeafCount: number;\n\tliveCount: number;\n\thisto: number[];\n\twindowTime?: number;\n\tpackTime?: number;\n\tordTime?: number;\n\tmaxOrdTime?: number;\n}\n\nexport function getStats(tree: MergeTree): MergeTreeStats {\n\tconst nodeGetStats = (block: MergeBlock): MergeTreeStats => {\n\t\tconst stats: MergeTreeStats = {\n\t\t\tmaxHeight: 0,\n\t\t\tnodeCount: 0,\n\t\t\tleafCount: 0,\n\t\t\tremovedLeafCount: 0,\n\t\t\tliveCount: 0,\n\t\t\thisto: [],\n\t\t};\n\t\tfor (let k = 0; k < MaxNodesInBlock; k++) {\n\t\t\tstats.histo[k] = 0;\n\t\t}\n\t\tfor (let i = 0; i < block.childCount; i++) {\n\t\t\tconst child = block.children[i];\n\t\t\tlet height = 1;\n\t\t\tif (child.isLeaf()) {\n\t\t\t\tstats.leafCount++;\n\t\t\t\tconst segment = child;\n\t\t\t\tif (isRemoved(segment)) {\n\t\t\t\t\tstats.removedLeafCount++;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst childStats = nodeGetStats(child);\n\t\t\t\theight = 1 + childStats.maxHeight;\n\t\t\t\tstats.nodeCount += childStats.nodeCount;\n\t\t\t\tstats.leafCount += childStats.leafCount;\n\t\t\t\tstats.removedLeafCount += childStats.removedLeafCount;\n\t\t\t\tstats.liveCount += childStats.liveCount;\n\t\t\t\tfor (let j = 0; j < MaxNodesInBlock; j++) {\n\t\t\t\t\tstats.histo[j] += childStats.histo[j];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (height > stats.maxHeight) {\n\t\t\t\tstats.maxHeight = height;\n\t\t\t}\n\t\t}\n\t\tstats.histo[block.childCount]++;\n\t\tstats.nodeCount++;\n\t\tstats.liveCount += block.childCount;\n\t\treturn stats;\n\t};\n\tconst rootStats = nodeGetStats(tree.root);\n\treturn rootStats;\n}\n"]}
@@ -141,11 +141,11 @@ export function validateRefCount(collection) {
141
141
  * fuzz tests).
142
142
  */
143
143
  export function useStrictPartialLengthChecks() {
144
- beforeEach(() => {
144
+ beforeEach("Enable strict partial lengths", () => {
145
145
  PartialSequenceLengths.options.verifier = verifyPartialLengths;
146
146
  PartialSequenceLengths.options.verifyExpected = verifyExpectedPartialLengths;
147
147
  });
148
- afterEach(() => {
148
+ afterEach("Disable strict partial lengths", () => {
149
149
  PartialSequenceLengths.options.verifier = undefined;
150
150
  PartialSequenceLengths.options.verifyExpected = undefined;
151
151
  });
@@ -1 +1 @@
1
- {"version":3,"file":"testUtils.js","sourceRoot":"","sources":["../../src/test/testUtils.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\";\nimport fs from \"node:fs\";\n\nimport { UnassignedSequenceNumber } from \"../constants.js\";\nimport { LocalReferenceCollection } from \"../localReference.js\";\nimport { MergeTree } from \"../mergeTree.js\";\nimport {\n\tIMergeTreeDeltaOpArgs,\n\ttype IMergeTreeDeltaCallbackArgs,\n\ttype IMergeTreeMaintenanceCallbackArgs,\n} from \"../mergeTreeDeltaCallback.js\";\nimport { walkAllChildSegments } from \"../mergeTreeNodeWalk.js\";\nimport { MergeBlock, ISegmentPrivate, Marker } from \"../mergeTreeNodes.js\";\nimport { ReferenceType } from \"../ops.js\";\nimport {\n\tPartialSequenceLengths,\n\tverifyExpectedPartialLengths,\n\tverifyPartialLengths,\n} from \"../partialLengths.js\";\nimport { PropertySet } from \"../properties.js\";\nimport * as info from \"../segmentInfos.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { loadText } from \"./text.js\";\n\nexport function loadTextFromFile(\n\tfilename: string,\n\tmergeTree: MergeTree,\n\tsegLimit = 0,\n): MergeTree {\n\tconst content = fs.readFileSync(filename, \"utf8\");\n\treturn loadText(content, mergeTree, segLimit);\n}\n\nexport function loadTextFromFileWithMarkers(\n\tfilename: string,\n\tmergeTree: MergeTree,\n\tsegLimit = 0,\n): MergeTree {\n\tconst content = fs.readFileSync(filename, \"utf8\");\n\treturn loadText(content, mergeTree, segLimit, true);\n}\n\ninterface InsertMarkerArgs {\n\tmergeTree: MergeTree;\n\tpos: number;\n\trefSeq: number;\n\tclientId: number;\n\tseq: number;\n\tbehaviors: ReferenceType;\n\tprops: PropertySet | undefined;\n\topArgs: IMergeTreeDeltaOpArgs;\n}\n\nexport function insertMarker({\n\tmergeTree,\n\tpos,\n\trefSeq,\n\tclientId,\n\tseq,\n\tbehaviors,\n\tprops,\n\topArgs,\n}: InsertMarkerArgs): void {\n\tmergeTree.insertSegments(\n\t\tpos,\n\t\t[Marker.make(behaviors, props)],\n\t\trefSeq,\n\t\tclientId,\n\t\tseq,\n\t\topArgs,\n\t);\n}\n\ninterface InsertTextArgs {\n\tmergeTree: MergeTree;\n\tpos: number;\n\trefSeq: number;\n\tclientId: number;\n\tseq: number;\n\ttext: string;\n\tprops?: PropertySet;\n\topArgs?: IMergeTreeDeltaOpArgs;\n}\n\nexport function insertText({\n\tmergeTree,\n\tpos,\n\trefSeq,\n\tclientId,\n\tseq,\n\ttext,\n\tprops,\n\topArgs,\n}: InsertTextArgs): void {\n\tmergeTree.insertSegments(\n\t\tpos,\n\t\t[TextSegment.make(text, props)],\n\t\trefSeq,\n\t\tclientId,\n\t\tseq,\n\t\topArgs,\n\t);\n}\n\ninterface InsertSegmentsArgs {\n\tmergeTree: MergeTree;\n\tpos: number;\n\tsegments: ISegmentPrivate[];\n\trefSeq: number;\n\tclientId: number;\n\tseq: number;\n\topArgs: IMergeTreeDeltaOpArgs | undefined;\n}\n\nexport function insertSegments({\n\tmergeTree,\n\tpos,\n\tsegments,\n\trefSeq,\n\tclientId,\n\tseq,\n\topArgs,\n}: InsertSegmentsArgs): void {\n\tmergeTree.insertSegments(pos, segments, refSeq, clientId, seq, opArgs);\n}\n\ninterface MarkRangeRemovedArgs {\n\tmergeTree: MergeTree;\n\tstart: number;\n\tend: number;\n\trefSeq: number;\n\tclientId: number;\n\tseq: number;\n\toverwrite: boolean;\n\topArgs: IMergeTreeDeltaOpArgs;\n}\n\nexport function markRangeRemoved({\n\tmergeTree,\n\tstart,\n\tend,\n\trefSeq,\n\tclientId,\n\tseq,\n\topArgs,\n}: MarkRangeRemovedArgs): void {\n\tmergeTree.markRangeRemoved(start, end, refSeq, clientId, seq, opArgs);\n}\n\nexport function obliterateRange({\n\tmergeTree,\n\tstart,\n\tend,\n\trefSeq,\n\tclientId,\n\tseq,\n\topArgs,\n}: {\n\tmergeTree: MergeTree;\n\tstart: number;\n\tend: number;\n\trefSeq: number;\n\tclientId: number;\n\tseq: number;\n\topArgs: IMergeTreeDeltaOpArgs;\n}): void {\n\tmergeTree.obliterateRange(start, end, refSeq, clientId, seq, opArgs);\n}\n\nexport function nodeOrdinalsHaveIntegrity(block: MergeBlock): boolean {\n\tconst olen = block.ordinal.length;\n\tfor (let i = 0; i < block.childCount; i++) {\n\t\tif (block.children[i].ordinal) {\n\t\t\tif (olen !== block.children[i].ordinal.length - 1) {\n\t\t\t\tconsole.log(\"node integrity issue\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (i > 0 && block.children[i].ordinal <= block.children[i - 1].ordinal) {\n\t\t\t\tconsole.log(\"node sib integrity issue\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!block.children[i].isLeaf()) {\n\t\t\t\treturn nodeOrdinalsHaveIntegrity(block.children[i] as MergeBlock);\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.log(`node child ordinal not set ${i}`);\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Returns an object that tallies each delta and maintenance operation observed\n * for the given 'mergeTree'.\n */\nexport function countOperations(mergeTree: MergeTree): object {\n\tconst counts = {};\n\n\tassert.strictEqual(mergeTree.mergeTreeDeltaCallback, undefined);\n\tassert.strictEqual(mergeTree.mergeTreeMaintenanceCallback, undefined);\n\n\tconst fn = (\n\t\tdeltaArgs: IMergeTreeDeltaCallbackArgs | IMergeTreeMaintenanceCallbackArgs,\n\t): void => {\n\t\tconst previous = counts[deltaArgs.operation] as undefined | number;\n\t\tcounts[deltaArgs.operation] = previous === undefined ? 1 : previous + 1;\n\t};\n\n\tmergeTree.mergeTreeDeltaCallback = (opArgs, deltaArgs): void => {\n\t\tfn(deltaArgs);\n\t};\n\tmergeTree.mergeTreeMaintenanceCallback = fn;\n\n\treturn counts;\n}\n\nfunction getPartialLengths(\n\tclientId: number,\n\tseq: number,\n\tmergeTree: MergeTree,\n\tlocalSeq?: number,\n\tmergeBlock: MergeBlock = mergeTree.root,\n): {\n\tpartialLen: number | undefined;\n\tactualLen: number;\n} {\n\tconst partialLen = mergeBlock.partialLengths?.getPartialLength(seq, clientId, localSeq);\n\n\tlet actualLen = 0;\n\n\tconst isInserted = (segment: ISegmentPrivate): boolean =>\n\t\tinfo.isInserted(segment) &&\n\t\t((segment.seq !== UnassignedSequenceNumber && segment.seq <= seq) ||\n\t\t\t(localSeq !== undefined &&\n\t\t\t\tsegment.seq === UnassignedSequenceNumber &&\n\t\t\t\tsegment.localSeq !== undefined &&\n\t\t\t\tsegment.localSeq <= localSeq));\n\n\tconst isRemoved = (segment: ISegmentPrivate): boolean =>\n\t\tinfo.isRemoved(segment) &&\n\t\t((localSeq !== undefined &&\n\t\t\tsegment.removedSeq === UnassignedSequenceNumber &&\n\t\t\tsegment.localRemovedSeq !== undefined &&\n\t\t\tsegment.localRemovedSeq <= localSeq) ||\n\t\t\t(segment.removedSeq !== UnassignedSequenceNumber && segment.removedSeq <= seq));\n\n\tconst isMoved = (segment: ISegmentPrivate): boolean =>\n\t\tinfo.isMoved(segment) &&\n\t\t((localSeq !== undefined &&\n\t\t\tsegment.movedSeq === UnassignedSequenceNumber &&\n\t\t\tsegment.localMovedSeq !== undefined &&\n\t\t\tsegment.localMovedSeq <= localSeq) ||\n\t\t\t(segment.movedSeq !== UnassignedSequenceNumber && segment.movedSeq <= seq));\n\n\twalkAllChildSegments(mergeBlock, (segment) => {\n\t\tif (isInserted(segment) && !isRemoved(segment) && !isMoved(segment)) {\n\t\t\tactualLen += segment.cachedLength;\n\t\t}\n\t\treturn true;\n\t});\n\n\treturn {\n\t\tpartialLen,\n\t\tactualLen,\n\t};\n}\n\nexport function validatePartialLengths(\n\tclientId: number,\n\tmergeTree: MergeTree,\n\texpectedValues?: { seq: number; len: number; localSeq?: number }[],\n\tlocalSeq?: number,\n\tmergeBlock: MergeBlock = mergeTree.root,\n): void {\n\tmergeTree.computeLocalPartials(0);\n\tfor (\n\t\tlet i = mergeTree.collabWindow.minSeq + 1;\n\t\ti <= mergeTree.collabWindow.currentSeq;\n\t\ti++\n\t) {\n\t\tconst { partialLen, actualLen } = getPartialLengths(\n\t\t\tclientId,\n\t\t\ti,\n\t\t\tmergeTree,\n\t\t\tlocalSeq,\n\t\t\tmergeBlock,\n\t\t);\n\n\t\tif (partialLen && partialLen < 0) {\n\t\t\tassert.fail(\"Negative partial length returned\");\n\t\t}\n\t\tassert.equal(partialLen, actualLen);\n\t}\n\n\tif (!expectedValues) {\n\t\treturn;\n\t}\n\n\tfor (const { seq, len, localSeq: expectedLocalSeq } of expectedValues) {\n\t\tconst { partialLen, actualLen } = getPartialLengths(\n\t\t\tclientId,\n\t\t\tseq,\n\t\t\tmergeTree,\n\t\t\texpectedLocalSeq ?? localSeq,\n\t\t\tmergeBlock,\n\t\t);\n\n\t\tassert.equal(partialLen, len);\n\t\tassert.equal(actualLen, len);\n\t}\n}\n\nexport function validateRefCount(collection?: LocalReferenceCollection): void {\n\tif (!collection) {\n\t\treturn;\n\t}\n\n\tconst expectedLength = [...collection].length;\n\n\t// eslint-disable-next-line @typescript-eslint/dot-notation\n\tassert.equal(collection[\"refCount\"], expectedLength);\n}\n\n/**\n * Enable stricter partial length assertions inside tests\n *\n * Note that these assertions can be expensive, and so should not be enabled in\n * production code or tests that run through thousands of ops (e.g. the SharedString\n * fuzz tests).\n */\nexport function useStrictPartialLengthChecks(): void {\n\tbeforeEach(() => {\n\t\tPartialSequenceLengths.options.verifier = verifyPartialLengths;\n\t\tPartialSequenceLengths.options.verifyExpected = verifyExpectedPartialLengths;\n\t});\n\n\tafterEach(() => {\n\t\tPartialSequenceLengths.options.verifier = undefined;\n\t\tPartialSequenceLengths.options.verifyExpected = undefined;\n\t});\n}\n"]}
1
+ {"version":3,"file":"testUtils.js","sourceRoot":"","sources":["../../src/test/testUtils.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\";\nimport fs from \"node:fs\";\n\nimport { UnassignedSequenceNumber } from \"../constants.js\";\nimport { LocalReferenceCollection } from \"../localReference.js\";\nimport { MergeTree } from \"../mergeTree.js\";\nimport {\n\tIMergeTreeDeltaOpArgs,\n\ttype IMergeTreeDeltaCallbackArgs,\n\ttype IMergeTreeMaintenanceCallbackArgs,\n} from \"../mergeTreeDeltaCallback.js\";\nimport { walkAllChildSegments } from \"../mergeTreeNodeWalk.js\";\nimport { MergeBlock, ISegmentPrivate, Marker } from \"../mergeTreeNodes.js\";\nimport { ReferenceType } from \"../ops.js\";\nimport {\n\tPartialSequenceLengths,\n\tverifyExpectedPartialLengths,\n\tverifyPartialLengths,\n} from \"../partialLengths.js\";\nimport { PropertySet } from \"../properties.js\";\nimport * as info from \"../segmentInfos.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { loadText } from \"./text.js\";\n\nexport function loadTextFromFile(\n\tfilename: string,\n\tmergeTree: MergeTree,\n\tsegLimit = 0,\n): MergeTree {\n\tconst content = fs.readFileSync(filename, \"utf8\");\n\treturn loadText(content, mergeTree, segLimit);\n}\n\nexport function loadTextFromFileWithMarkers(\n\tfilename: string,\n\tmergeTree: MergeTree,\n\tsegLimit = 0,\n): MergeTree {\n\tconst content = fs.readFileSync(filename, \"utf8\");\n\treturn loadText(content, mergeTree, segLimit, true);\n}\n\ninterface InsertMarkerArgs {\n\tmergeTree: MergeTree;\n\tpos: number;\n\trefSeq: number;\n\tclientId: number;\n\tseq: number;\n\tbehaviors: ReferenceType;\n\tprops: PropertySet | undefined;\n\topArgs: IMergeTreeDeltaOpArgs;\n}\n\nexport function insertMarker({\n\tmergeTree,\n\tpos,\n\trefSeq,\n\tclientId,\n\tseq,\n\tbehaviors,\n\tprops,\n\topArgs,\n}: InsertMarkerArgs): void {\n\tmergeTree.insertSegments(\n\t\tpos,\n\t\t[Marker.make(behaviors, props)],\n\t\trefSeq,\n\t\tclientId,\n\t\tseq,\n\t\topArgs,\n\t);\n}\n\ninterface InsertTextArgs {\n\tmergeTree: MergeTree;\n\tpos: number;\n\trefSeq: number;\n\tclientId: number;\n\tseq: number;\n\ttext: string;\n\tprops?: PropertySet;\n\topArgs?: IMergeTreeDeltaOpArgs;\n}\n\nexport function insertText({\n\tmergeTree,\n\tpos,\n\trefSeq,\n\tclientId,\n\tseq,\n\ttext,\n\tprops,\n\topArgs,\n}: InsertTextArgs): void {\n\tmergeTree.insertSegments(\n\t\tpos,\n\t\t[TextSegment.make(text, props)],\n\t\trefSeq,\n\t\tclientId,\n\t\tseq,\n\t\topArgs,\n\t);\n}\n\ninterface InsertSegmentsArgs {\n\tmergeTree: MergeTree;\n\tpos: number;\n\tsegments: ISegmentPrivate[];\n\trefSeq: number;\n\tclientId: number;\n\tseq: number;\n\topArgs: IMergeTreeDeltaOpArgs | undefined;\n}\n\nexport function insertSegments({\n\tmergeTree,\n\tpos,\n\tsegments,\n\trefSeq,\n\tclientId,\n\tseq,\n\topArgs,\n}: InsertSegmentsArgs): void {\n\tmergeTree.insertSegments(pos, segments, refSeq, clientId, seq, opArgs);\n}\n\ninterface MarkRangeRemovedArgs {\n\tmergeTree: MergeTree;\n\tstart: number;\n\tend: number;\n\trefSeq: number;\n\tclientId: number;\n\tseq: number;\n\toverwrite: boolean;\n\topArgs: IMergeTreeDeltaOpArgs;\n}\n\nexport function markRangeRemoved({\n\tmergeTree,\n\tstart,\n\tend,\n\trefSeq,\n\tclientId,\n\tseq,\n\topArgs,\n}: MarkRangeRemovedArgs): void {\n\tmergeTree.markRangeRemoved(start, end, refSeq, clientId, seq, opArgs);\n}\n\nexport function obliterateRange({\n\tmergeTree,\n\tstart,\n\tend,\n\trefSeq,\n\tclientId,\n\tseq,\n\topArgs,\n}: {\n\tmergeTree: MergeTree;\n\tstart: number;\n\tend: number;\n\trefSeq: number;\n\tclientId: number;\n\tseq: number;\n\topArgs: IMergeTreeDeltaOpArgs;\n}): void {\n\tmergeTree.obliterateRange(start, end, refSeq, clientId, seq, opArgs);\n}\n\nexport function nodeOrdinalsHaveIntegrity(block: MergeBlock): boolean {\n\tconst olen = block.ordinal.length;\n\tfor (let i = 0; i < block.childCount; i++) {\n\t\tif (block.children[i].ordinal) {\n\t\t\tif (olen !== block.children[i].ordinal.length - 1) {\n\t\t\t\tconsole.log(\"node integrity issue\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (i > 0 && block.children[i].ordinal <= block.children[i - 1].ordinal) {\n\t\t\t\tconsole.log(\"node sib integrity issue\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!block.children[i].isLeaf()) {\n\t\t\t\treturn nodeOrdinalsHaveIntegrity(block.children[i] as MergeBlock);\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.log(`node child ordinal not set ${i}`);\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Returns an object that tallies each delta and maintenance operation observed\n * for the given 'mergeTree'.\n */\nexport function countOperations(mergeTree: MergeTree): object {\n\tconst counts = {};\n\n\tassert.strictEqual(mergeTree.mergeTreeDeltaCallback, undefined);\n\tassert.strictEqual(mergeTree.mergeTreeMaintenanceCallback, undefined);\n\n\tconst fn = (\n\t\tdeltaArgs: IMergeTreeDeltaCallbackArgs | IMergeTreeMaintenanceCallbackArgs,\n\t): void => {\n\t\tconst previous = counts[deltaArgs.operation] as undefined | number;\n\t\tcounts[deltaArgs.operation] = previous === undefined ? 1 : previous + 1;\n\t};\n\n\tmergeTree.mergeTreeDeltaCallback = (opArgs, deltaArgs): void => {\n\t\tfn(deltaArgs);\n\t};\n\tmergeTree.mergeTreeMaintenanceCallback = fn;\n\n\treturn counts;\n}\n\nfunction getPartialLengths(\n\tclientId: number,\n\tseq: number,\n\tmergeTree: MergeTree,\n\tlocalSeq?: number,\n\tmergeBlock: MergeBlock = mergeTree.root,\n): {\n\tpartialLen: number | undefined;\n\tactualLen: number;\n} {\n\tconst partialLen = mergeBlock.partialLengths?.getPartialLength(seq, clientId, localSeq);\n\n\tlet actualLen = 0;\n\n\tconst isInserted = (segment: ISegmentPrivate): boolean =>\n\t\tinfo.isInserted(segment) &&\n\t\t((segment.seq !== UnassignedSequenceNumber && segment.seq <= seq) ||\n\t\t\t(localSeq !== undefined &&\n\t\t\t\tsegment.seq === UnassignedSequenceNumber &&\n\t\t\t\tsegment.localSeq !== undefined &&\n\t\t\t\tsegment.localSeq <= localSeq));\n\n\tconst isRemoved = (segment: ISegmentPrivate): boolean =>\n\t\tinfo.isRemoved(segment) &&\n\t\t((localSeq !== undefined &&\n\t\t\tsegment.removedSeq === UnassignedSequenceNumber &&\n\t\t\tsegment.localRemovedSeq !== undefined &&\n\t\t\tsegment.localRemovedSeq <= localSeq) ||\n\t\t\t(segment.removedSeq !== UnassignedSequenceNumber && segment.removedSeq <= seq));\n\n\tconst isMoved = (segment: ISegmentPrivate): boolean =>\n\t\tinfo.isMoved(segment) &&\n\t\t((localSeq !== undefined &&\n\t\t\tsegment.movedSeq === UnassignedSequenceNumber &&\n\t\t\tsegment.localMovedSeq !== undefined &&\n\t\t\tsegment.localMovedSeq <= localSeq) ||\n\t\t\t(segment.movedSeq !== UnassignedSequenceNumber && segment.movedSeq <= seq));\n\n\twalkAllChildSegments(mergeBlock, (segment) => {\n\t\tif (isInserted(segment) && !isRemoved(segment) && !isMoved(segment)) {\n\t\t\tactualLen += segment.cachedLength;\n\t\t}\n\t\treturn true;\n\t});\n\n\treturn {\n\t\tpartialLen,\n\t\tactualLen,\n\t};\n}\n\nexport function validatePartialLengths(\n\tclientId: number,\n\tmergeTree: MergeTree,\n\texpectedValues?: { seq: number; len: number; localSeq?: number }[],\n\tlocalSeq?: number,\n\tmergeBlock: MergeBlock = mergeTree.root,\n): void {\n\tmergeTree.computeLocalPartials(0);\n\tfor (\n\t\tlet i = mergeTree.collabWindow.minSeq + 1;\n\t\ti <= mergeTree.collabWindow.currentSeq;\n\t\ti++\n\t) {\n\t\tconst { partialLen, actualLen } = getPartialLengths(\n\t\t\tclientId,\n\t\t\ti,\n\t\t\tmergeTree,\n\t\t\tlocalSeq,\n\t\t\tmergeBlock,\n\t\t);\n\n\t\tif (partialLen && partialLen < 0) {\n\t\t\tassert.fail(\"Negative partial length returned\");\n\t\t}\n\t\tassert.equal(partialLen, actualLen);\n\t}\n\n\tif (!expectedValues) {\n\t\treturn;\n\t}\n\n\tfor (const { seq, len, localSeq: expectedLocalSeq } of expectedValues) {\n\t\tconst { partialLen, actualLen } = getPartialLengths(\n\t\t\tclientId,\n\t\t\tseq,\n\t\t\tmergeTree,\n\t\t\texpectedLocalSeq ?? localSeq,\n\t\t\tmergeBlock,\n\t\t);\n\n\t\tassert.equal(partialLen, len);\n\t\tassert.equal(actualLen, len);\n\t}\n}\n\nexport function validateRefCount(collection?: LocalReferenceCollection): void {\n\tif (!collection) {\n\t\treturn;\n\t}\n\n\tconst expectedLength = [...collection].length;\n\n\t// eslint-disable-next-line @typescript-eslint/dot-notation\n\tassert.equal(collection[\"refCount\"], expectedLength);\n}\n\n/**\n * Enable stricter partial length assertions inside tests\n *\n * Note that these assertions can be expensive, and so should not be enabled in\n * production code or tests that run through thousands of ops (e.g. the SharedString\n * fuzz tests).\n */\nexport function useStrictPartialLengthChecks(): void {\n\tbeforeEach(\"Enable strict partial lengths\", () => {\n\t\tPartialSequenceLengths.options.verifier = verifyPartialLengths;\n\t\tPartialSequenceLengths.options.verifyExpected = verifyExpectedPartialLengths;\n\t});\n\n\tafterEach(\"Disable strict partial lengths\", () => {\n\t\tPartialSequenceLengths.options.verifier = undefined;\n\t\tPartialSequenceLengths.options.verifyExpected = undefined;\n\t});\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/merge-tree",
3
- "version": "2.20.0",
3
+ "version": "2.22.0",
4
4
  "description": "Merge tree",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -81,30 +81,30 @@
81
81
  "temp-directory": "nyc/.nyc_output"
82
82
  },
83
83
  "dependencies": {
84
- "@fluid-internal/client-utils": "~2.20.0",
85
- "@fluidframework/container-definitions": "~2.20.0",
86
- "@fluidframework/core-interfaces": "~2.20.0",
87
- "@fluidframework/core-utils": "~2.20.0",
88
- "@fluidframework/datastore-definitions": "~2.20.0",
89
- "@fluidframework/driver-definitions": "~2.20.0",
90
- "@fluidframework/runtime-definitions": "~2.20.0",
91
- "@fluidframework/runtime-utils": "~2.20.0",
92
- "@fluidframework/shared-object-base": "~2.20.0",
93
- "@fluidframework/telemetry-utils": "~2.20.0"
84
+ "@fluid-internal/client-utils": "~2.22.0",
85
+ "@fluidframework/container-definitions": "~2.22.0",
86
+ "@fluidframework/core-interfaces": "~2.22.0",
87
+ "@fluidframework/core-utils": "~2.22.0",
88
+ "@fluidframework/datastore-definitions": "~2.22.0",
89
+ "@fluidframework/driver-definitions": "~2.22.0",
90
+ "@fluidframework/runtime-definitions": "~2.22.0",
91
+ "@fluidframework/runtime-utils": "~2.22.0",
92
+ "@fluidframework/shared-object-base": "~2.22.0",
93
+ "@fluidframework/telemetry-utils": "~2.22.0"
94
94
  },
95
95
  "devDependencies": {
96
96
  "@arethetypeswrong/cli": "^0.17.1",
97
97
  "@biomejs/biome": "~1.9.3",
98
- "@fluid-internal/mocha-test-setup": "~2.20.0",
99
- "@fluid-private/stochastic-test-utils": "~2.20.0",
100
- "@fluid-private/test-pairwise-generator": "~2.20.0",
98
+ "@fluid-internal/mocha-test-setup": "~2.22.0",
99
+ "@fluid-private/stochastic-test-utils": "~2.22.0",
100
+ "@fluid-private/test-pairwise-generator": "~2.22.0",
101
101
  "@fluid-tools/benchmark": "^0.50.0",
102
102
  "@fluid-tools/build-cli": "^0.51.0",
103
103
  "@fluidframework/build-common": "^2.0.3",
104
104
  "@fluidframework/build-tools": "^0.51.0",
105
- "@fluidframework/eslint-config-fluid": "^5.6.0",
106
- "@fluidframework/merge-tree-previous": "npm:@fluidframework/merge-tree@2.13.0",
107
- "@fluidframework/test-runtime-utils": "~2.20.0",
105
+ "@fluidframework/eslint-config-fluid": "^5.7.3",
106
+ "@fluidframework/merge-tree-previous": "npm:@fluidframework/merge-tree@2.21.0",
107
+ "@fluidframework/test-runtime-utils": "~2.22.0",
108
108
  "@microsoft/api-extractor": "7.47.8",
109
109
  "@types/diff": "^3.5.1",
110
110
  "@types/mocha": "^10.0.10",
@@ -124,65 +124,7 @@
124
124
  "typescript": "~5.4.5"
125
125
  },
126
126
  "typeValidation": {
127
- "broken": {
128
- "Class_BaseSegment": {
129
- "backCompat": false
130
- },
131
- "Class_Marker": {
132
- "backCompat": false
133
- },
134
- "Class_TextSegment": {
135
- "backCompat": false
136
- },
137
- "Class_TrackingGroup": {
138
- "backCompat": false
139
- },
140
- "ClassStatics_BaseSegment": {
141
- "backCompat": false
142
- },
143
- "ClassStatics_Marker": {
144
- "backCompat": false
145
- },
146
- "ClassStatics_TextSegment": {
147
- "backCompat": false
148
- },
149
- "ClassStatics_TrackingGroup": {
150
- "backCompat": false
151
- },
152
- "Interface_IMergeTreeDeltaCallbackArgs": {
153
- "backCompat": false
154
- },
155
- "Interface_IMergeTreeMaintenanceCallbackArgs": {
156
- "backCompat": false
157
- },
158
- "Interface_IMergeTreeSegmentDelta": {
159
- "backCompat": false
160
- },
161
- "Interface_ISegment": {
162
- "backCompat": false
163
- },
164
- "Interface_ITrackingGroup": {
165
- "backCompat": false
166
- },
167
- "TypeAlias_MergeTreeDeltaRevertible": {
168
- "backCompat": false
169
- },
170
- "TypeAlias_Trackable": {
171
- "backCompat": false
172
- },
173
- "Interface_IMergeNodeCommon": {
174
- "forwardCompat": false,
175
- "backCompat": false
176
- },
177
- "Interface_IMoveInfo": {
178
- "forwardCompat": false,
179
- "backCompat": false
180
- },
181
- "Interface_IRemovalInfo": {
182
- "forwardCompat": false,
183
- "backCompat": false
184
- }
185
- },
127
+ "broken": {},
186
128
  "entrypoint": "legacy"
187
129
  },
188
130
  "scripts": {
@@ -214,7 +156,7 @@
214
156
  "ci:build:api-reports:current": "api-extractor run --config api-extractor/api-extractor.current.json",
215
157
  "ci:build:api-reports:legacy": "api-extractor run --config api-extractor/api-extractor.legacy.json",
216
158
  "ci:build:docs": "api-extractor run",
217
- "clean": "rimraf --glob dist lib \"*.d.ts\" \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
159
+ "clean": "rimraf --glob dist lib {alpha,beta,internal,legacy}.d.ts \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
218
160
  "eslint": "eslint --format stylish src",
219
161
  "eslint:fix": "eslint --format stylish src --fix",
220
162
  "format": "npm run format:biome",
@@ -229,8 +171,8 @@
229
171
  "test:benchmark:report": "mocha \"dist/test/*.perf.spec.*js\" --node-option unhandled-rejections=strict,expose-gc --exit --perfMode --fgrep @Benchmark -r @fluid-internal/mocha-test-setup --reporter @fluid-tools/benchmark/dist/MochaReporter.js --timeout 60000",
230
172
  "test:coverage": "c8 npm test",
231
173
  "test:mocha": "npm run test:mocha:esm && echo skipping cjs to avoid overhead - npm run test:mocha:cjs",
232
- "test:mocha:cjs": "mocha --recursive \"dist/test/**/*.spec.*js\" --exit",
233
- "test:mocha:esm": "mocha --recursive \"lib/test/**/*.spec.*js\" --exit",
174
+ "test:mocha:cjs": "mocha --recursive \"dist/test/**/*.spec.*js\"",
175
+ "test:mocha:esm": "mocha --recursive \"lib/test/**/*.spec.*js\"",
234
176
  "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
235
177
  "test:stress": "cross-env FUZZ_STRESS_RUN=1 FUZZ_TEST_COUNT=normal npm run test:mocha",
236
178
  "tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist",
package/src/mergeTree.ts CHANGED
@@ -593,6 +593,8 @@ export class MergeTree {
593
593
  public mergeTreeDeltaCallback?: MergeTreeDeltaCallback;
594
594
  public mergeTreeMaintenanceCallback?: MergeTreeMaintenanceCallback;
595
595
 
596
+ // TODO:AB#29553: This property doesn't seem to be adequately round-tripped through summarization.
597
+ // Specifically, it seems like we drop information about obliterates within the collab window for at least V1 summaries.
596
598
  private readonly obliterates = new Obliterates(this);
597
599
 
598
600
  public constructor(public options?: IMergeTreeOptionsInternal) {
@@ -1300,7 +1302,7 @@ export class MergeTree {
1300
1302
  pendingSegmentGroup.segments.map((pendingSegment: ISegmentLeaf) => {
1301
1303
  const overlappingRemove = !ackSegment(pendingSegment, pendingSegmentGroup, opArgs);
1302
1304
 
1303
- overwrite = overlappingRemove || overwrite;
1305
+ overwrite ||= overlappingRemove || toMoveInfo(pendingSegment) !== undefined;
1304
1306
 
1305
1307
  overlappingRemoves.push(overlappingRemove);
1306
1308
  if (MergeTree.options.zamboniSegments) {
@@ -1619,15 +1621,22 @@ export class MergeTree {
1619
1621
  ? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq!
1620
1622
  : ob.seq;
1621
1623
  if (normalizedObSeq > refSeq) {
1622
- if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
1623
- normalizedOldestSeq = normalizedObSeq;
1624
- oldest = ob;
1625
- movedClientIds.unshift(ob.clientId);
1626
- movedSeqs.unshift(ob.seq);
1627
- } else {
1628
- movedClientIds.push(ob.clientId);
1629
- movedSeqs.push(ob.seq);
1624
+ // Any obliterate from the same client that's inserting this segment cannot cause the segment to be marked as
1625
+ // obliterated (since that client must have performed the obliterate before this insertion).
1626
+ // We still need to consider such obliterates when determining the winning obliterate for the insertion point,
1627
+ // see `obliteratePrecedingInsertion` docs.
1628
+ if (clientId !== ob.clientId) {
1629
+ if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
1630
+ normalizedOldestSeq = normalizedObSeq;
1631
+ oldest = ob;
1632
+ movedClientIds.unshift(ob.clientId);
1633
+ movedSeqs.unshift(ob.seq);
1634
+ } else {
1635
+ movedClientIds.push(ob.clientId);
1636
+ movedSeqs.push(ob.seq);
1637
+ }
1630
1638
  }
1639
+
1631
1640
  if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
1632
1641
  normalizedNewestSeq = normalizedObSeq;
1633
1642
  newest = ob;
@@ -1635,6 +1644,10 @@ export class MergeTree {
1635
1644
  }
1636
1645
  }
1637
1646
 
1647
+ newSegment.obliteratePrecedingInsertion = newest;
1648
+ // See doc comment on obliteratePrecedingInsertion for more details: if the newest obliterate was performed
1649
+ // by the same client that's inserting this segment, we let them insert into this range and therefore don't
1650
+ // mark it obliterated.
1638
1651
  if (oldest && newest?.clientId !== clientId) {
1639
1652
  const moveInfo: IMoveInfo = {
1640
1653
  movedClientIds,
@@ -1656,10 +1669,18 @@ export class MergeTree {
1656
1669
  }
1657
1670
 
1658
1671
  if (newSegment.parent) {
1659
- this.blockUpdatePathLengths(newSegment.parent, seq, clientId);
1672
+ // The incremental update codepath in theory can handle most cases where segments are obliterated upon insertion,
1673
+ // but it's not idempotent with respect to segment insertion in the first place. Since we already update partial
1674
+ // lengths inside the inserting walk, we'd be at risk of double-counting the insertion in any case if we allow
1675
+ // incremental updates here.
1676
+ const newStructure = true;
1677
+ this.blockUpdatePathLengths(
1678
+ newSegment.parent,
1679
+ moveInfo.movedSeq,
1680
+ clientId,
1681
+ newStructure,
1682
+ );
1660
1683
  }
1661
- } else if (oldest && newest?.clientId === clientId) {
1662
- newSegment.prevObliterateByInserter = newest;
1663
1684
  }
1664
1685
 
1665
1686
  saveIfLocal(newSegment);
@@ -1682,8 +1703,8 @@ export class MergeTree {
1682
1703
  segment.segmentGroups.copyTo(next.segmentGroups);
1683
1704
  }
1684
1705
 
1685
- if (segment.prevObliterateByInserter) {
1686
- next.prevObliterateByInserter = segment.prevObliterateByInserter;
1706
+ if (segment.obliteratePrecedingInsertion) {
1707
+ next.obliteratePrecedingInsertion = segment.obliteratePrecedingInsertion;
1687
1708
  }
1688
1709
  copyPropertiesAndManager(segment, next);
1689
1710
  if (segment.localRefs) {
@@ -2050,7 +2071,8 @@ export class MergeTree {
2050
2071
  (start.side === Side.After && startPos === pos + segment.cachedLength) || // exclusive start segment
2051
2072
  (end.side === Side.Before &&
2052
2073
  endPos === pos &&
2053
- isSegmentPresent(segment, { refSeq, localSeq })) // exclusive end segment
2074
+ // TODO:AB#29765: The clientId check here should be handled by isSegmentPresent and/or PerspectiveImpl
2075
+ (segment.clientId === clientId || isSegmentPresent(segment, { refSeq, localSeq }))) // exclusive end segment
2054
2076
  ) {
2055
2077
  // We walk these segments because we want to also walk any concurrently inserted segments between here and the obliterated segments.
2056
2078
  // These segments are outside of the obliteration range though, so return true to keep walking.
@@ -2058,18 +2080,23 @@ export class MergeTree {
2058
2080
  }
2059
2081
  const existingMoveInfo = toMoveInfo(segment);
2060
2082
 
2061
- if (segment.prevObliterateByInserter?.seq === UnassignedSequenceNumber) {
2083
+ // The "last-to-obliterate-gets-to-insert" policy described by the doc comment on `obliteratePrecedingInsertion`
2084
+ // is mostly handled by logic at insertion time, but we need a small bit of handling here.
2085
+ // Specifically, we want to avoid marking a local-only segment as obliterated when we know one of our own local obliterates
2086
+ // will win against the obliterate we're processing, hence the early exit.
2087
+ if (
2088
+ segment.seq === UnassignedSequenceNumber &&
2089
+ segment.obliteratePrecedingInsertion?.seq === UnassignedSequenceNumber &&
2090
+ seq !== UnassignedSequenceNumber
2091
+ ) {
2062
2092
  // We chose to not obliterate this segment because we are aware of an unacked local obliteration.
2063
2093
  // The local obliterate has not been sequenced yet, so it is still the newest obliterate we are aware of.
2064
2094
  // Other clients will also choose not to obliterate this segment because the most recent obliteration has the same clientId
2065
2095
  return true;
2066
2096
  }
2067
2097
 
2068
- const wasMovedOnInsert =
2069
- clientId !== segment.clientId &&
2070
- segment.seq !== undefined &&
2071
- seq !== UnassignedSequenceNumber &&
2072
- (refSeq < segment.seq || segment.seq === UnassignedSequenceNumber);
2098
+ // Partial lengths incrementality is not supported for overlapping obliterate/removes.
2099
+ _overwrite ||= existingMoveInfo !== undefined || toRemovalInfo(segment) !== undefined;
2073
2100
 
2074
2101
  if (existingMoveInfo === undefined) {
2075
2102
  const movedSeg = overwriteInfo<IMoveInfo, ISegmentLeaf>(segment, {
@@ -2077,17 +2104,33 @@ export class MergeTree {
2077
2104
  movedSeq: seq,
2078
2105
  localMovedSeq: localSeq,
2079
2106
  movedSeqs: [seq],
2080
- wasMovedOnInsert,
2107
+ wasMovedOnInsert:
2108
+ segment.seq === UnassignedSequenceNumber && seq !== UnassignedSequenceNumber,
2081
2109
  });
2082
2110
 
2083
- if (!toRemovalInfo(movedSeg)) {
2111
+ const existingRemoval = toRemovalInfo(movedSeg);
2112
+ if (existingRemoval === undefined) {
2084
2113
  movedSegments.push(movedSeg);
2114
+ } else if (
2115
+ existingRemoval.removedSeq === UnassignedSequenceNumber &&
2116
+ segment.localRefs?.empty === false
2117
+ ) {
2118
+ // We removed this locally already so we don't need to event it again, but it might have references
2119
+ // that need sliding now that a move may have been acked.
2120
+ localOverlapWithRefs.push(segment);
2085
2121
  }
2086
2122
  } else {
2087
- _overwrite = true;
2088
- // never move wasMovedOnInsert from true to false
2089
- existingMoveInfo.wasMovedOnInsert ||= wasMovedOnInsert;
2090
2123
  if (existingMoveInfo.movedSeq === UnassignedSequenceNumber) {
2124
+ // Should not need explicit set here, but this should be implied:
2125
+ assert(
2126
+ !existingMoveInfo.wasMovedOnInsert,
2127
+ 0xab4 /* Local obliterate cannot have removed a segment as soon as it was inserted */,
2128
+ );
2129
+ assert(
2130
+ seq !== UnassignedSequenceNumber,
2131
+ 0xab5 /* Cannot obliterate the same segment locally twice */,
2132
+ );
2133
+ existingMoveInfo.wasMovedOnInsert = segment.seq === UnassignedSequenceNumber;
2091
2134
  // we moved this locally, but someone else moved it first
2092
2135
  // so put them at the head of the list
2093
2136
  // The list isn't ordered, but we keep the first move at the head
@@ -2227,6 +2270,8 @@ export class MergeTree {
2227
2270
  ): boolean => {
2228
2271
  const existingRemovalInfo = toRemovalInfo(segment);
2229
2272
 
2273
+ // Partial lengths incrementality is not supported for overlapping obliterate/removes.
2274
+ _overwrite ||= existingRemovalInfo !== undefined || toMoveInfo(segment) !== undefined;
2230
2275
  if (existingRemovalInfo === undefined) {
2231
2276
  const removed = overwriteInfo<IRemovalInfo, ISegmentLeaf>(segment, {
2232
2277
  removedClientIds: [clientId],
@@ -2234,11 +2279,18 @@ export class MergeTree {
2234
2279
  localRemovedSeq: localSeq,
2235
2280
  });
2236
2281
 
2237
- if (!toMoveInfo(removed)) {
2282
+ const existingMoveInfo = toMoveInfo(removed);
2283
+ if (existingMoveInfo === undefined) {
2238
2284
  removedSegments.push(removed);
2285
+ } else if (
2286
+ existingMoveInfo.movedSeq === UnassignedSequenceNumber &&
2287
+ segment.localRefs?.empty === false
2288
+ ) {
2289
+ // We moved this locally already so we don't need to event it again, but it might have references
2290
+ // that need sliding now that a remove may have been acked.
2291
+ localOverlapWithRefs.push(segment);
2239
2292
  }
2240
2293
  } else {
2241
- _overwrite = true;
2242
2294
  if (existingRemovalInfo.removedSeq === UnassignedSequenceNumber) {
2243
2295
  // we removed this locally, but someone else removed it first
2244
2296
  // so put them at the head of the list