@fluidframework/merge-tree 2.0.0-internal.8.0.0 → 2.0.0-rc.1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +0 -6
- package/api-extractor-esm.json +17 -0
- package/api-extractor-lint.json +1 -10
- package/api-extractor.json +0 -4
- package/api-report/merge-tree.api.md +4 -9
- package/dist/client.d.ts +0 -7
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +0 -7
- package/dist/client.js.map +1 -1
- package/dist/merge-tree-alpha.d.ts +27 -12
- package/dist/merge-tree-beta.d.ts +0 -16
- package/dist/merge-tree-public.d.ts +0 -16
- package/dist/merge-tree-untrimmed.d.ts +5 -29
- package/dist/mergeTree.d.ts +0 -17
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +0 -130
- package/dist/mergeTree.js.map +1 -1
- package/dist/ops.d.ts +1 -1
- package/dist/ops.js +1 -1
- package/dist/ops.js.map +1 -1
- package/dist/revertibles.d.ts +4 -4
- package/dist/revertibles.js +3 -3
- package/dist/revertibles.js.map +1 -1
- package/dist/test/Insertion.perf.spec.d.ts +6 -0
- package/dist/test/Insertion.perf.spec.d.ts.map +1 -0
- package/dist/test/Insertion.perf.spec.js +113 -0
- package/dist/test/Insertion.perf.spec.js.map +1 -0
- package/dist/test/PartialLengths.perf.spec.d.ts +6 -0
- package/dist/test/PartialLengths.perf.spec.d.ts.map +1 -0
- package/dist/test/PartialLengths.perf.spec.js +67 -0
- package/dist/test/PartialLengths.perf.spec.js.map +1 -0
- package/dist/test/Removal.perf.spec.d.ts +6 -0
- package/dist/test/Removal.perf.spec.d.ts.map +1 -0
- package/dist/test/Removal.perf.spec.js +166 -0
- package/dist/test/Removal.perf.spec.js.map +1 -0
- package/dist/test/Snapshot.perf.spec.d.ts +6 -0
- package/dist/test/Snapshot.perf.spec.d.ts.map +1 -0
- package/dist/test/Snapshot.perf.spec.js +33 -0
- package/dist/test/Snapshot.perf.spec.js.map +1 -0
- package/dist/test/attributionCollection.perf.spec.d.ts +6 -0
- package/dist/test/attributionCollection.perf.spec.d.ts.map +1 -0
- package/dist/test/attributionCollection.perf.spec.js +231 -0
- package/dist/test/attributionCollection.perf.spec.js.map +1 -0
- package/dist/test/attributionCollection.spec.d.ts +6 -0
- package/dist/test/attributionCollection.spec.d.ts.map +1 -0
- package/dist/test/attributionCollection.spec.js +486 -0
- package/dist/test/attributionCollection.spec.js.map +1 -0
- package/dist/test/attributionPolicy.spec.d.ts +6 -0
- package/dist/test/attributionPolicy.spec.d.ts.map +1 -0
- package/dist/test/attributionPolicy.spec.js +189 -0
- package/dist/test/attributionPolicy.spec.js.map +1 -0
- package/dist/test/beastTest.d.ts +54 -0
- package/dist/test/beastTest.d.ts.map +1 -0
- package/dist/test/beastTest.js +1333 -0
- package/dist/test/beastTest.js.map +1 -0
- package/dist/test/client.annotateMarker.spec.d.ts +6 -0
- package/dist/test/client.annotateMarker.spec.d.ts.map +1 -0
- package/dist/test/client.annotateMarker.spec.js +45 -0
- package/dist/test/client.annotateMarker.spec.js.map +1 -0
- package/dist/test/client.apis.d.ts +7 -0
- package/dist/test/client.apis.d.ts.map +1 -0
- package/dist/test/client.apis.js +72 -0
- package/dist/test/client.apis.js.map +1 -0
- package/dist/test/client.applyMsg.spec.d.ts +6 -0
- package/dist/test/client.applyMsg.spec.d.ts.map +1 -0
- package/dist/test/client.applyMsg.spec.js +500 -0
- package/dist/test/client.applyMsg.spec.js.map +1 -0
- package/dist/test/client.applyStashedOpFarm.spec.d.ts +12 -0
- package/dist/test/client.applyStashedOpFarm.spec.d.ts.map +1 -0
- package/dist/test/client.applyStashedOpFarm.spec.js +144 -0
- package/dist/test/client.applyStashedOpFarm.spec.js.map +1 -0
- package/dist/test/client.attributionFarm.spec.d.ts +7 -0
- package/dist/test/client.attributionFarm.spec.d.ts.map +1 -0
- package/dist/test/client.attributionFarm.spec.js +96 -0
- package/dist/test/client.attributionFarm.spec.js.map +1 -0
- package/dist/test/client.conflictFarm.spec.d.ts +15 -0
- package/dist/test/client.conflictFarm.spec.d.ts.map +1 -0
- package/dist/test/client.conflictFarm.spec.js +88 -0
- package/dist/test/client.conflictFarm.spec.js.map +1 -0
- package/dist/test/client.getPosition.spec.d.ts +6 -0
- package/dist/test/client.getPosition.spec.d.ts.map +1 -0
- package/dist/test/client.getPosition.spec.js +54 -0
- package/dist/test/client.getPosition.spec.js.map +1 -0
- package/dist/test/client.localReference.spec.d.ts +6 -0
- package/dist/test/client.localReference.spec.d.ts.map +1 -0
- package/dist/test/client.localReference.spec.js +439 -0
- package/dist/test/client.localReference.spec.js.map +1 -0
- package/dist/test/client.localReferenceFarm.spec.d.ts +6 -0
- package/dist/test/client.localReferenceFarm.spec.d.ts.map +1 -0
- package/dist/test/client.localReferenceFarm.spec.js +88 -0
- package/dist/test/client.localReferenceFarm.spec.js.map +1 -0
- package/dist/test/client.rebasePosition.spec.d.ts +6 -0
- package/dist/test/client.rebasePosition.spec.d.ts.map +1 -0
- package/dist/test/client.rebasePosition.spec.js +102 -0
- package/dist/test/client.rebasePosition.spec.js.map +1 -0
- package/dist/test/client.reconnectFarm.spec.d.ts +12 -0
- package/dist/test/client.reconnectFarm.spec.d.ts.map +1 -0
- package/dist/test/client.reconnectFarm.spec.js +91 -0
- package/dist/test/client.reconnectFarm.spec.js.map +1 -0
- package/dist/test/client.replay.spec.d.ts +6 -0
- package/dist/test/client.replay.spec.d.ts.map +1 -0
- package/dist/test/client.replay.spec.js +85 -0
- package/dist/test/client.replay.spec.js.map +1 -0
- package/dist/test/client.rollback.spec.d.ts +6 -0
- package/dist/test/client.rollback.spec.d.ts.map +1 -0
- package/dist/test/client.rollback.spec.js +453 -0
- package/dist/test/client.rollback.spec.js.map +1 -0
- package/dist/test/client.rollbackFarm.spec.d.ts +6 -0
- package/dist/test/client.rollbackFarm.spec.d.ts.map +1 -0
- package/dist/test/client.rollbackFarm.spec.js +48 -0
- package/dist/test/client.rollbackFarm.spec.js.map +1 -0
- package/dist/test/client.searchForMarker.spec.d.ts +6 -0
- package/dist/test/client.searchForMarker.spec.d.ts.map +1 -0
- package/dist/test/client.searchForMarker.spec.js +446 -0
- package/dist/test/client.searchForMarker.spec.js.map +1 -0
- package/dist/test/client.walkSegments.spec.d.ts +6 -0
- package/dist/test/client.walkSegments.spec.d.ts.map +1 -0
- package/dist/test/client.walkSegments.spec.js +54 -0
- package/dist/test/client.walkSegments.spec.js.map +1 -0
- package/dist/test/collections.list.spec.d.ts +6 -0
- package/dist/test/collections.list.spec.d.ts.map +1 -0
- package/dist/test/collections.list.spec.js +84 -0
- package/dist/test/collections.list.spec.js.map +1 -0
- package/dist/test/createInsertOnlyAttributionPolicy.spec.d.ts +6 -0
- package/dist/test/createInsertOnlyAttributionPolicy.spec.d.ts.map +1 -0
- package/dist/test/createInsertOnlyAttributionPolicy.spec.js +35 -0
- package/dist/test/createInsertOnlyAttributionPolicy.spec.js.map +1 -0
- package/dist/test/index.d.ts +13 -0
- package/dist/test/index.d.ts.map +1 -0
- package/dist/test/index.js +88 -0
- package/dist/test/index.js.map +1 -0
- package/dist/test/mergeTree.annotate.deltaCallback.spec.d.ts +6 -0
- package/dist/test/mergeTree.annotate.deltaCallback.spec.d.ts.map +1 -0
- package/dist/test/mergeTree.annotate.deltaCallback.spec.js +142 -0
- package/dist/test/mergeTree.annotate.deltaCallback.spec.js.map +1 -0
- package/dist/test/mergeTree.annotate.spec.d.ts +6 -0
- package/dist/test/mergeTree.annotate.spec.d.ts.map +1 -0
- package/dist/test/mergeTree.annotate.spec.js +448 -0
- package/dist/test/mergeTree.annotate.spec.js.map +1 -0
- package/dist/test/mergeTree.insert.deltaCallback.spec.d.ts +6 -0
- package/dist/test/mergeTree.insert.deltaCallback.spec.d.ts.map +1 -0
- package/dist/test/mergeTree.insert.deltaCallback.spec.js +126 -0
- package/dist/test/mergeTree.insert.deltaCallback.spec.js.map +1 -0
- package/dist/test/mergeTree.insertingWalk.spec.d.ts +6 -0
- package/dist/test/mergeTree.insertingWalk.spec.d.ts.map +1 -0
- package/dist/test/mergeTree.insertingWalk.spec.js +279 -0
- package/dist/test/mergeTree.insertingWalk.spec.js.map +1 -0
- package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.d.ts +6 -0
- package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.d.ts.map +1 -0
- package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +178 -0
- package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -0
- package/dist/test/mergeTree.markRangeRemoved.spec.d.ts +6 -0
- package/dist/test/mergeTree.markRangeRemoved.spec.d.ts.map +1 -0
- package/dist/test/mergeTree.markRangeRemoved.spec.js +130 -0
- package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -0
- package/dist/test/mergeTree.walk.spec.d.ts +6 -0
- package/dist/test/mergeTree.walk.spec.d.ts.map +1 -0
- package/dist/test/mergeTree.walk.spec.js +63 -0
- package/dist/test/mergeTree.walk.spec.js.map +1 -0
- package/dist/test/mergeTree.zamboni.spec.d.ts +6 -0
- package/dist/test/mergeTree.zamboni.spec.d.ts.map +1 -0
- package/dist/test/mergeTree.zamboni.spec.js +52 -0
- package/dist/test/mergeTree.zamboni.spec.js.map +1 -0
- package/dist/test/mergeTreeOperationRunner.d.ts +63 -0
- package/dist/test/mergeTreeOperationRunner.d.ts.map +1 -0
- package/dist/test/mergeTreeOperationRunner.js +245 -0
- package/dist/test/mergeTreeOperationRunner.js.map +1 -0
- package/dist/test/mergeTreeOperationRunner.spec.d.ts +6 -0
- package/dist/test/mergeTreeOperationRunner.spec.d.ts.map +1 -0
- package/dist/test/mergeTreeOperationRunner.spec.js +156 -0
- package/dist/test/mergeTreeOperationRunner.spec.js.map +1 -0
- package/dist/test/obliterate.concurrent.spec.d.ts +6 -0
- package/dist/test/obliterate.concurrent.spec.d.ts.map +1 -0
- package/dist/test/obliterate.concurrent.spec.js +1446 -0
- package/dist/test/obliterate.concurrent.spec.js.map +1 -0
- package/dist/test/obliterate.partialLength.spec.d.ts +6 -0
- package/dist/test/obliterate.partialLength.spec.d.ts.map +1 -0
- package/dist/test/obliterate.partialLength.spec.js +279 -0
- package/dist/test/obliterate.partialLength.spec.js.map +1 -0
- package/dist/test/obliterate.reconnect.spec.d.ts +6 -0
- package/dist/test/obliterate.reconnect.spec.d.ts.map +1 -0
- package/dist/test/obliterate.reconnect.spec.js +164 -0
- package/dist/test/obliterate.reconnect.spec.js.map +1 -0
- package/dist/test/obliterate.spec.d.ts +6 -0
- package/dist/test/obliterate.spec.d.ts.map +1 -0
- package/dist/test/obliterate.spec.js +162 -0
- package/dist/test/obliterate.spec.js.map +1 -0
- package/dist/test/ordinal.spec.d.ts +2 -0
- package/dist/test/ordinal.spec.d.ts.map +1 -0
- package/dist/test/ordinal.spec.js +43 -0
- package/dist/test/ordinal.spec.js.map +1 -0
- package/dist/test/partialLength.spec.d.ts +6 -0
- package/dist/test/partialLength.spec.d.ts.map +1 -0
- package/dist/test/partialLength.spec.js +282 -0
- package/dist/test/partialLength.spec.js.map +1 -0
- package/dist/test/properties.spec.d.ts +6 -0
- package/dist/test/properties.spec.d.ts.map +1 -0
- package/dist/test/properties.spec.js +55 -0
- package/dist/test/properties.spec.js.map +1 -0
- package/dist/test/reconnectHelper.d.ts +48 -0
- package/dist/test/reconnectHelper.d.ts.map +1 -0
- package/dist/test/reconnectHelper.js +86 -0
- package/dist/test/reconnectHelper.js.map +1 -0
- package/dist/test/resetPendingSegmentsToOp.spec.d.ts +6 -0
- package/dist/test/resetPendingSegmentsToOp.spec.d.ts.map +1 -0
- package/dist/test/resetPendingSegmentsToOp.spec.js +218 -0
- package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -0
- package/dist/test/revertibleFarm.spec.d.ts +6 -0
- package/dist/test/revertibleFarm.spec.d.ts.map +1 -0
- package/dist/test/revertibleFarm.spec.js +124 -0
- package/dist/test/revertibleFarm.spec.js.map +1 -0
- package/dist/test/revertibles.spec.d.ts +17 -0
- package/dist/test/revertibles.spec.d.ts.map +1 -0
- package/dist/test/revertibles.spec.js +385 -0
- package/dist/test/revertibles.spec.js.map +1 -0
- package/dist/test/segmentGroupCollection.spec.d.ts +6 -0
- package/dist/test/segmentGroupCollection.spec.d.ts.map +1 -0
- package/dist/test/segmentGroupCollection.spec.js +60 -0
- package/dist/test/segmentGroupCollection.spec.js.map +1 -0
- package/dist/test/snapshot.spec.d.ts +6 -0
- package/dist/test/snapshot.spec.d.ts.map +1 -0
- package/dist/test/snapshot.spec.js +178 -0
- package/dist/test/snapshot.spec.js.map +1 -0
- package/dist/test/snapshot.utils.d.ts +33 -0
- package/dist/test/snapshot.utils.d.ts.map +1 -0
- package/dist/test/snapshot.utils.js +109 -0
- package/dist/test/snapshot.utils.js.map +1 -0
- package/dist/test/snapshotlegacy.spec.d.ts +6 -0
- package/dist/test/snapshotlegacy.spec.d.ts.map +1 -0
- package/dist/test/snapshotlegacy.spec.js +139 -0
- package/dist/test/snapshotlegacy.spec.js.map +1 -0
- package/dist/test/sortedSegmentSet.spec.d.ts +6 -0
- package/dist/test/sortedSegmentSet.spec.d.ts.map +1 -0
- package/dist/test/sortedSegmentSet.spec.js +95 -0
- package/dist/test/sortedSegmentSet.spec.js.map +1 -0
- package/dist/test/testClient.d.ts +119 -0
- package/dist/test/testClient.d.ts.map +1 -0
- package/dist/test/testClient.js +439 -0
- package/dist/test/testClient.js.map +1 -0
- package/dist/test/testClientLogger.d.ts +44 -0
- package/dist/test/testClientLogger.d.ts.map +1 -0
- package/dist/test/testClientLogger.js +287 -0
- package/dist/test/testClientLogger.js.map +1 -0
- package/dist/test/testSerializer.d.ts +18 -0
- package/dist/test/testSerializer.d.ts.map +1 -0
- package/dist/test/testSerializer.js +33 -0
- package/dist/test/testSerializer.js.map +1 -0
- package/dist/test/testServer.d.ts +36 -0
- package/dist/test/testServer.d.ts.map +1 -0
- package/dist/test/testServer.js +138 -0
- package/dist/test/testServer.js.map +1 -0
- package/dist/test/testUtils.d.ts +69 -0
- package/dist/test/testUtils.d.ts.map +1 -0
- package/dist/test/testUtils.js +149 -0
- package/dist/test/testUtils.js.map +1 -0
- package/dist/test/text.d.ts +9 -0
- package/dist/test/text.d.ts.map +1 -0
- package/dist/test/text.js +76 -0
- package/dist/test/text.js.map +1 -0
- package/dist/test/tracking.spec.d.ts +6 -0
- package/dist/test/tracking.spec.d.ts.map +1 -0
- package/dist/test/tracking.spec.js +120 -0
- package/dist/test/tracking.spec.js.map +1 -0
- package/dist/test/wordUnitTests.d.ts +6 -0
- package/dist/test/wordUnitTests.d.ts.map +1 -0
- package/dist/test/wordUnitTests.js +172 -0
- package/dist/test/wordUnitTests.js.map +1 -0
- package/lib/{MergeTreeTextHelper.d.ts → MergeTreeTextHelper.d.mts} +3 -3
- package/lib/MergeTreeTextHelper.d.mts.map +1 -0
- package/lib/{MergeTreeTextHelper.js → MergeTreeTextHelper.mjs} +5 -10
- package/lib/MergeTreeTextHelper.mjs.map +1 -0
- package/lib/{attributionCollection.d.ts → attributionCollection.d.mts} +2 -2
- package/lib/attributionCollection.d.mts.map +1 -0
- package/lib/{attributionCollection.js → attributionCollection.mjs} +9 -14
- package/lib/attributionCollection.mjs.map +1 -0
- package/lib/{attributionPolicy.d.ts → attributionPolicy.d.mts} +2 -2
- package/lib/attributionPolicy.d.mts.map +1 -0
- package/lib/{attributionPolicy.js → attributionPolicy.mjs} +21 -27
- package/lib/attributionPolicy.mjs.map +1 -0
- package/lib/{client.d.ts → client.d.mts} +9 -16
- package/lib/client.d.mts.map +1 -0
- package/lib/{client.js → client.mjs} +101 -110
- package/lib/client.mjs.map +1 -0
- package/lib/collections/{index.d.ts → index.d.mts} +3 -3
- package/lib/collections/index.d.mts.map +1 -0
- package/lib/collections/index.mjs +7 -0
- package/lib/collections/index.mjs.map +1 -0
- package/lib/collections/{list.d.ts → list.d.mts} +1 -1
- package/lib/collections/list.d.mts.map +1 -0
- package/lib/collections/{list.js → list.mjs} +6 -11
- package/lib/collections/list.mjs.map +1 -0
- package/lib/collections/{rbTree.d.ts → rbTree.d.mts} +1 -1
- package/lib/collections/rbTree.d.mts.map +1 -0
- package/lib/collections/{rbTree.js → rbTree.mjs} +16 -20
- package/lib/collections/rbTree.mjs.map +1 -0
- package/lib/{constants.d.ts → constants.d.mts} +1 -1
- package/lib/constants.d.mts.map +1 -0
- package/lib/constants.mjs +32 -0
- package/lib/constants.mjs.map +1 -0
- package/lib/{endOfTreeSegment.d.ts → endOfTreeSegment.d.mts} +4 -4
- package/lib/endOfTreeSegment.d.mts.map +1 -0
- package/lib/{endOfTreeSegment.js → endOfTreeSegment.mjs} +13 -18
- package/lib/endOfTreeSegment.mjs.map +1 -0
- package/lib/{index.d.ts → index.d.mts} +21 -21
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +24 -0
- package/lib/index.mjs.map +1 -0
- package/lib/{localReference.d.ts → localReference.d.mts} +7 -7
- package/lib/localReference.d.mts.map +1 -0
- package/lib/{localReference.js → localReference.mjs} +38 -47
- package/lib/localReference.mjs.map +1 -0
- package/lib/{merge-tree-alpha.d.ts → merge-tree-alpha.d.mts} +27 -12
- package/lib/{merge-tree-beta.d.ts → merge-tree-beta.d.mts} +0 -16
- package/lib/{merge-tree-public.d.ts → merge-tree-public.d.mts} +0 -16
- package/lib/{merge-tree-untrimmed.d.ts → merge-tree-untrimmed.d.mts} +5 -29
- package/lib/{mergeTree.d.ts → mergeTree.d.mts} +12 -29
- package/lib/mergeTree.d.mts.map +1 -0
- package/lib/{mergeTree.js → mergeTree.mjs} +203 -340
- package/lib/mergeTree.mjs.map +1 -0
- package/lib/{mergeTreeDeltaCallback.d.ts → mergeTreeDeltaCallback.d.mts} +4 -8
- package/lib/mergeTreeDeltaCallback.d.mts.map +1 -0
- package/lib/{mergeTreeDeltaCallback.js → mergeTreeDeltaCallback.mjs} +2 -5
- package/lib/mergeTreeDeltaCallback.mjs.map +1 -0
- package/lib/{mergeTreeNodeWalk.d.ts → mergeTreeNodeWalk.d.mts} +2 -2
- package/lib/mergeTreeNodeWalk.d.mts.map +1 -0
- package/lib/{mergeTreeNodeWalk.js → mergeTreeNodeWalk.mjs} +14 -21
- package/lib/mergeTreeNodeWalk.mjs.map +1 -0
- package/lib/{mergeTreeNodes.d.ts → mergeTreeNodes.d.mts} +12 -12
- package/lib/mergeTreeNodes.d.mts.map +1 -0
- package/lib/{mergeTreeNodes.js → mergeTreeNodes.mjs} +60 -76
- package/lib/mergeTreeNodes.mjs.map +1 -0
- package/lib/{mergeTreeTracking.d.ts → mergeTreeTracking.d.mts} +3 -3
- package/lib/mergeTreeTracking.d.mts.map +1 -0
- package/lib/{mergeTreeTracking.js → mergeTreeTracking.mjs} +6 -13
- package/lib/mergeTreeTracking.mjs.map +1 -0
- package/lib/{opBuilder.d.ts → opBuilder.d.mts} +4 -4
- package/lib/opBuilder.d.mts.map +1 -0
- package/lib/{opBuilder.js → opBuilder.mjs} +15 -25
- package/lib/opBuilder.mjs.map +1 -0
- package/lib/{ops.d.ts → ops.d.mts} +2 -2
- package/lib/ops.d.mts.map +1 -0
- package/lib/{ops.js → ops.mjs} +5 -8
- package/lib/ops.mjs.map +1 -0
- package/lib/{ordinal.d.ts → ordinal.d.mts} +1 -1
- package/lib/ordinal.d.mts.map +1 -0
- package/lib/{ordinal.js → ordinal.mjs} +4 -9
- package/lib/ordinal.mjs.map +1 -0
- package/lib/{partialLengths.d.ts → partialLengths.d.mts} +4 -4
- package/lib/partialLengths.d.mts.map +1 -0
- package/lib/{partialLengths.js → partialLengths.mjs} +38 -46
- package/lib/partialLengths.mjs.map +1 -0
- package/lib/{properties.d.ts → properties.d.mts} +1 -1
- package/lib/properties.d.mts.map +1 -0
- package/lib/{properties.js → properties.mjs} +7 -16
- package/lib/properties.mjs.map +1 -0
- package/lib/{referencePositions.d.ts → referencePositions.d.mts} +5 -5
- package/lib/referencePositions.d.mts.map +1 -0
- package/lib/referencePositions.mjs +70 -0
- package/lib/referencePositions.mjs.map +1 -0
- package/lib/{revertibles.d.ts → revertibles.d.mts} +12 -12
- package/lib/revertibles.d.mts.map +1 -0
- package/lib/{revertibles.js → revertibles.mjs} +60 -67
- package/lib/revertibles.mjs.map +1 -0
- package/lib/{segmentGroupCollection.d.ts → segmentGroupCollection.d.mts} +2 -2
- package/lib/segmentGroupCollection.d.mts.map +1 -0
- package/lib/{segmentGroupCollection.js → segmentGroupCollection.mjs} +5 -9
- package/lib/segmentGroupCollection.mjs.map +1 -0
- package/lib/{segmentPropertiesManager.d.ts → segmentPropertiesManager.d.mts} +3 -3
- package/lib/segmentPropertiesManager.d.mts.map +1 -0
- package/lib/{segmentPropertiesManager.js → segmentPropertiesManager.mjs} +14 -20
- package/lib/{segmentPropertiesManager.js.map → segmentPropertiesManager.mjs.map} +1 -1
- package/lib/{snapshotChunks.d.ts → snapshotChunks.d.mts} +4 -4
- package/lib/snapshotChunks.d.mts.map +1 -0
- package/lib/{snapshotChunks.js → snapshotChunks.mjs} +10 -17
- package/lib/snapshotChunks.mjs.map +1 -0
- package/lib/{snapshotLoader.d.ts → snapshotLoader.d.mts} +3 -3
- package/lib/snapshotLoader.d.mts.map +1 -0
- package/lib/{snapshotLoader.js → snapshotLoader.mjs} +33 -38
- package/lib/snapshotLoader.mjs.map +1 -0
- package/lib/{snapshotV1.d.ts → snapshotV1.d.mts} +4 -4
- package/lib/snapshotV1.d.mts.map +1 -0
- package/lib/{snapshotV1.js → snapshotV1.mjs} +28 -32
- package/lib/snapshotV1.mjs.map +1 -0
- package/lib/{snapshotlegacy.d.ts → snapshotlegacy.d.mts} +3 -3
- package/lib/snapshotlegacy.d.mts.map +1 -0
- package/lib/{snapshotlegacy.js → snapshotlegacy.mjs} +21 -26
- package/lib/snapshotlegacy.mjs.map +1 -0
- package/lib/{sortedSegmentSet.d.ts → sortedSegmentSet.d.mts} +4 -4
- package/lib/sortedSegmentSet.d.mts.map +1 -0
- package/lib/{sortedSegmentSet.js → sortedSegmentSet.mjs} +3 -8
- package/lib/sortedSegmentSet.mjs.map +1 -0
- package/lib/{sortedSet.d.ts → sortedSet.d.mts} +1 -1
- package/lib/sortedSet.d.mts.map +1 -0
- package/lib/{sortedSet.js → sortedSet.mjs} +2 -6
- package/lib/sortedSet.mjs.map +1 -0
- package/lib/{textSegment.d.ts → textSegment.d.mts} +4 -4
- package/lib/textSegment.d.mts.map +1 -0
- package/lib/{textSegment.js → textSegment.mjs} +8 -12
- package/lib/textSegment.mjs.map +1 -0
- package/lib/{zamboni.d.ts → zamboni.d.mts} +3 -3
- package/lib/zamboni.d.mts.map +1 -0
- package/lib/{zamboni.js → zamboni.mjs} +22 -28
- package/lib/zamboni.mjs.map +1 -0
- package/package.json +95 -164
- package/src/client.ts +0 -8
- package/src/mergeTree.ts +0 -226
- package/src/ops.ts +1 -1
- package/src/revertibles.ts +4 -4
- package/lib/MergeTreeTextHelper.d.ts.map +0 -1
- package/lib/MergeTreeTextHelper.js.map +0 -1
- package/lib/attributionCollection.d.ts.map +0 -1
- package/lib/attributionCollection.js.map +0 -1
- package/lib/attributionPolicy.d.ts.map +0 -1
- package/lib/attributionPolicy.js.map +0 -1
- package/lib/client.d.ts.map +0 -1
- package/lib/client.js.map +0 -1
- package/lib/collections/index.d.ts.map +0 -1
- package/lib/collections/index.js +0 -14
- package/lib/collections/index.js.map +0 -1
- package/lib/collections/list.d.ts.map +0 -1
- package/lib/collections/list.js.map +0 -1
- package/lib/collections/rbTree.d.ts.map +0 -1
- package/lib/collections/rbTree.js.map +0 -1
- package/lib/constants.d.ts.map +0 -1
- package/lib/constants.js +0 -35
- package/lib/constants.js.map +0 -1
- package/lib/endOfTreeSegment.d.ts.map +0 -1
- package/lib/endOfTreeSegment.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -80
- package/lib/index.js.map +0 -1
- package/lib/localReference.d.ts.map +0 -1
- package/lib/localReference.js.map +0 -1
- package/lib/mergeTree.d.ts.map +0 -1
- package/lib/mergeTree.js.map +0 -1
- package/lib/mergeTreeDeltaCallback.d.ts.map +0 -1
- package/lib/mergeTreeDeltaCallback.js.map +0 -1
- package/lib/mergeTreeNodeWalk.d.ts.map +0 -1
- package/lib/mergeTreeNodeWalk.js.map +0 -1
- package/lib/mergeTreeNodes.d.ts.map +0 -1
- package/lib/mergeTreeNodes.js.map +0 -1
- package/lib/mergeTreeTracking.d.ts.map +0 -1
- package/lib/mergeTreeTracking.js.map +0 -1
- package/lib/opBuilder.d.ts.map +0 -1
- package/lib/opBuilder.js.map +0 -1
- package/lib/ops.d.ts.map +0 -1
- package/lib/ops.js.map +0 -1
- package/lib/ordinal.d.ts.map +0 -1
- package/lib/ordinal.js.map +0 -1
- package/lib/partialLengths.d.ts.map +0 -1
- package/lib/partialLengths.js.map +0 -1
- package/lib/properties.d.ts.map +0 -1
- package/lib/properties.js.map +0 -1
- package/lib/referencePositions.d.ts.map +0 -1
- package/lib/referencePositions.js +0 -80
- package/lib/referencePositions.js.map +0 -1
- package/lib/revertibles.d.ts.map +0 -1
- package/lib/revertibles.js.map +0 -1
- package/lib/segmentGroupCollection.d.ts.map +0 -1
- package/lib/segmentGroupCollection.js.map +0 -1
- package/lib/segmentPropertiesManager.d.ts.map +0 -1
- package/lib/snapshotChunks.d.ts.map +0 -1
- package/lib/snapshotChunks.js.map +0 -1
- package/lib/snapshotLoader.d.ts.map +0 -1
- package/lib/snapshotLoader.js.map +0 -1
- package/lib/snapshotV1.d.ts.map +0 -1
- package/lib/snapshotV1.js.map +0 -1
- package/lib/snapshotlegacy.d.ts.map +0 -1
- package/lib/snapshotlegacy.js.map +0 -1
- package/lib/sortedSegmentSet.d.ts.map +0 -1
- package/lib/sortedSegmentSet.js.map +0 -1
- package/lib/sortedSet.d.ts.map +0 -1
- package/lib/sortedSet.js.map +0 -1
- package/lib/textSegment.d.ts.map +0 -1
- package/lib/textSegment.js.map +0 -1
- package/lib/zamboni.d.ts.map +0 -1
- package/lib/zamboni.js.map +0 -1
- package/merge-tree.test-files.tar +0 -0
- package/src/mergeTreeExample1.pdf +0 -0
- package/tsconfig.esnext.json +0 -6
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const assert_1 = require("assert");
|
|
9
|
+
const stochastic_test_utils_1 = require("@fluid-private/stochastic-test-utils");
|
|
10
|
+
const ops_1 = require("../ops");
|
|
11
|
+
const localReference_1 = require("../localReference");
|
|
12
|
+
const mergeTreeOperationRunner_1 = require("./mergeTreeOperationRunner");
|
|
13
|
+
const testClient_1 = require("./testClient");
|
|
14
|
+
const testClientLogger_1 = require("./testClientLogger");
|
|
15
|
+
const testUtils_1 = require("./testUtils");
|
|
16
|
+
const defaultOptions = {
|
|
17
|
+
initLen: { min: 2, max: 256 },
|
|
18
|
+
modLen: { min: 1, max: 256 },
|
|
19
|
+
opsPerRoundRange: { min: 10, max: 10 },
|
|
20
|
+
rounds: 10,
|
|
21
|
+
operations: [mergeTreeOperationRunner_1.removeRange],
|
|
22
|
+
growthFunc: (input) => input * 2,
|
|
23
|
+
};
|
|
24
|
+
describe("MergeTree.Client", () => {
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
(0, localReference_1.setValidateRefCount)(testUtils_1.validateRefCount);
|
|
27
|
+
});
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
(0, localReference_1.setValidateRefCount)(undefined);
|
|
30
|
+
});
|
|
31
|
+
// Generate a list of single character client names, support up to 69 clients
|
|
32
|
+
const clientNames = (0, mergeTreeOperationRunner_1.generateClientNames)();
|
|
33
|
+
(0, mergeTreeOperationRunner_1.doOverRanges)(defaultOptions, ({ initLen, modLen }) => {
|
|
34
|
+
it(`LocalReferenceFarm_${initLen}_${modLen}`, async () => {
|
|
35
|
+
const random = (0, stochastic_test_utils_1.makeRandom)(0xdeadbeef, 0xfeedbed, initLen, modLen);
|
|
36
|
+
const clients = new Array(3).fill(0).map(() => new testClient_1.TestClient());
|
|
37
|
+
clients.forEach((c, i) => c.startOrUpdateCollaboration(clientNames[i]));
|
|
38
|
+
let seq = 0;
|
|
39
|
+
// init with random values
|
|
40
|
+
seq = (0, mergeTreeOperationRunner_1.runMergeTreeOperationRunner)(random, seq, clients, initLen, defaultOptions);
|
|
41
|
+
// add local references
|
|
42
|
+
const refs = [];
|
|
43
|
+
const validateRefs = (reason, workload) => {
|
|
44
|
+
const preWorkload = testClientLogger_1.TestClientLogger.toString(clients);
|
|
45
|
+
workload();
|
|
46
|
+
for (let c = 1; c < clients.length; c++) {
|
|
47
|
+
for (let r = 0; r < refs[c].length; r++) {
|
|
48
|
+
const pos0 = clients[0].localReferencePositionToPosition(refs[0][r]);
|
|
49
|
+
const posC = clients[c].localReferencePositionToPosition(refs[c][r]);
|
|
50
|
+
if (pos0 !== posC) {
|
|
51
|
+
assert_1.strict.equal(pos0, posC, `${reason}:\n${preWorkload}\n${testClientLogger_1.TestClientLogger.toString(clients)}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// console.log(`${reason}:\n${preWorkload}\n${TestClientLogger.toString(clients)}`)
|
|
56
|
+
};
|
|
57
|
+
validateRefs("Initialize", () => {
|
|
58
|
+
clients.forEach((c, i) => {
|
|
59
|
+
refs.push([]);
|
|
60
|
+
for (let t = 0; t < c.getLength(); t++) {
|
|
61
|
+
const seg = c.getContainingSegment(t);
|
|
62
|
+
const forwardLref = c.createLocalReferencePosition(seg.segment, seg.offset, ops_1.ReferenceType.SlideOnRemove, { t }, localReference_1.SlidingPreference.FORWARD);
|
|
63
|
+
const backwardLref = c.createLocalReferencePosition(seg.segment, seg.offset, ops_1.ReferenceType.SlideOnRemove, { t }, localReference_1.SlidingPreference.BACKWARD);
|
|
64
|
+
refs[i].push(forwardLref);
|
|
65
|
+
refs[i].push(backwardLref);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
validateRefs("After Init Zamboni", () => {
|
|
70
|
+
// trigger zamboni multiple times as it is incremental
|
|
71
|
+
for (let i = clients[0].getCollabWindow().minSeq; i <= seq; i++) {
|
|
72
|
+
clients.forEach((c) => c.updateMinSeq(i));
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
validateRefs("After More Ops", () => {
|
|
76
|
+
// init with random values
|
|
77
|
+
seq = (0, mergeTreeOperationRunner_1.runMergeTreeOperationRunner)(random, seq, clients, modLen, defaultOptions);
|
|
78
|
+
});
|
|
79
|
+
validateRefs("After Final Zamboni", () => {
|
|
80
|
+
// trigger zamboni multiple times as it is incremental
|
|
81
|
+
for (let i = clients[0].getCollabWindow().minSeq; i <= seq; i++) {
|
|
82
|
+
clients.forEach((c) => c.updateMinSeq(i));
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=client.localReferenceFarm.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.localReferenceFarm.spec.js","sourceRoot":"","sources":["../../src/test/client.localReferenceFarm.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/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"assert\";\nimport { makeRandom } from \"@fluid-private/stochastic-test-utils\";\nimport { ReferencePosition } from \"../referencePositions\";\nimport { ReferenceType } from \"../ops\";\nimport { setValidateRefCount, SlidingPreference } from \"../localReference\";\nimport {\n\tIMergeTreeOperationRunnerConfig,\n\tremoveRange,\n\trunMergeTreeOperationRunner,\n\tgenerateClientNames,\n\tIConfigRange,\n\tdoOverRanges,\n} from \"./mergeTreeOperationRunner\";\nimport { TestClient } from \"./testClient\";\nimport { TestClientLogger } from \"./testClientLogger\";\nimport { validateRefCount } from \"./testUtils\";\n\nconst defaultOptions: Record<\"initLen\" | \"modLen\", IConfigRange> & IMergeTreeOperationRunnerConfig =\n\t{\n\t\tinitLen: { min: 2, max: 256 },\n\t\tmodLen: { min: 1, max: 256 },\n\t\topsPerRoundRange: { min: 10, max: 10 },\n\t\trounds: 10,\n\t\toperations: [removeRange],\n\t\tgrowthFunc: (input: number) => input * 2,\n\t};\n\ndescribe(\"MergeTree.Client\", () => {\n\tbeforeEach(() => {\n\t\tsetValidateRefCount(validateRefCount);\n\t});\n\n\tafterEach(() => {\n\t\tsetValidateRefCount(undefined);\n\t});\n\n\t// Generate a list of single character client names, support up to 69 clients\n\tconst clientNames = generateClientNames();\n\n\tdoOverRanges(defaultOptions, ({ initLen, modLen }) => {\n\t\tit(`LocalReferenceFarm_${initLen}_${modLen}`, async () => {\n\t\t\tconst random = makeRandom(0xdeadbeef, 0xfeedbed, initLen, modLen);\n\n\t\t\tconst clients: TestClient[] = new Array(3).fill(0).map(() => new TestClient());\n\t\t\tclients.forEach((c, i) => c.startOrUpdateCollaboration(clientNames[i]));\n\n\t\t\tlet seq = 0;\n\t\t\t// init with random values\n\t\t\tseq = runMergeTreeOperationRunner(random, seq, clients, initLen, defaultOptions);\n\t\t\t// add local references\n\t\t\tconst refs: ReferencePosition[][] = [];\n\n\t\t\tconst validateRefs = (reason: string, workload: () => void) => {\n\t\t\t\tconst preWorkload = TestClientLogger.toString(clients);\n\t\t\t\tworkload();\n\t\t\t\tfor (let c = 1; c < clients.length; c++) {\n\t\t\t\t\tfor (let r = 0; r < refs[c].length; r++) {\n\t\t\t\t\t\tconst pos0 = clients[0].localReferencePositionToPosition(refs[0][r]);\n\t\t\t\t\t\tconst posC = clients[c].localReferencePositionToPosition(refs[c][r]);\n\t\t\t\t\t\tif (pos0 !== posC) {\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tpos0,\n\t\t\t\t\t\t\t\tposC,\n\t\t\t\t\t\t\t\t`${reason}:\\n${preWorkload}\\n${TestClientLogger.toString(clients)}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// console.log(`${reason}:\\n${preWorkload}\\n${TestClientLogger.toString(clients)}`)\n\t\t\t};\n\n\t\t\tvalidateRefs(\"Initialize\", () => {\n\t\t\t\tclients.forEach((c, i) => {\n\t\t\t\t\trefs.push([]);\n\t\t\t\t\tfor (let t = 0; t < c.getLength(); t++) {\n\t\t\t\t\t\tconst seg = c.getContainingSegment(t);\n\t\t\t\t\t\tconst forwardLref = c.createLocalReferencePosition(\n\t\t\t\t\t\t\tseg.segment!,\n\t\t\t\t\t\t\tseg.offset,\n\t\t\t\t\t\t\tReferenceType.SlideOnRemove,\n\t\t\t\t\t\t\t{ t },\n\t\t\t\t\t\t\tSlidingPreference.FORWARD,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst backwardLref = c.createLocalReferencePosition(\n\t\t\t\t\t\t\tseg.segment!,\n\t\t\t\t\t\t\tseg.offset,\n\t\t\t\t\t\t\tReferenceType.SlideOnRemove,\n\t\t\t\t\t\t\t{ t },\n\t\t\t\t\t\t\tSlidingPreference.BACKWARD,\n\t\t\t\t\t\t);\n\t\t\t\t\t\trefs[i].push(forwardLref);\n\t\t\t\t\t\trefs[i].push(backwardLref);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tvalidateRefs(\"After Init Zamboni\", () => {\n\t\t\t\t// trigger zamboni multiple times as it is incremental\n\t\t\t\tfor (let i = clients[0].getCollabWindow().minSeq; i <= seq; i++) {\n\t\t\t\t\tclients.forEach((c) => c.updateMinSeq(i));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tvalidateRefs(\"After More Ops\", () => {\n\t\t\t\t// init with random values\n\t\t\t\tseq = runMergeTreeOperationRunner(random, seq, clients, modLen, defaultOptions);\n\t\t\t});\n\n\t\t\tvalidateRefs(\"After Final Zamboni\", () => {\n\t\t\t\t// trigger zamboni multiple times as it is incremental\n\t\t\t\tfor (let i = clients[0].getCollabWindow().minSeq; i <= seq; i++) {\n\t\t\t\t\tclients.forEach((c) => c.updateMinSeq(i));\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.rebasePosition.spec.d.ts","sourceRoot":"","sources":["../../src/test/client.rebasePosition.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const assert_1 = require("assert");
|
|
8
|
+
const testClient_1 = require("./testClient");
|
|
9
|
+
describe("client.rebasePosition", () => {
|
|
10
|
+
const localUserLongId = "localUser";
|
|
11
|
+
const remoteUserLongId = "remoteUser";
|
|
12
|
+
let client;
|
|
13
|
+
let seq;
|
|
14
|
+
const getTextAt = (pos) => client.getText(pos, pos + 1);
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
client = new testClient_1.TestClient();
|
|
17
|
+
client.insertTextLocal(0, "hello world");
|
|
18
|
+
client.startOrUpdateCollaboration(localUserLongId);
|
|
19
|
+
seq = 0;
|
|
20
|
+
});
|
|
21
|
+
it("rebase past remote insert", () => {
|
|
22
|
+
client.insertTextRemote(0, "abc", undefined, ++seq, 0, remoteUserLongId);
|
|
23
|
+
const rebasedPos = client.rebasePosition(6 /* "w" */, 0, 0);
|
|
24
|
+
const text = getTextAt(rebasedPos);
|
|
25
|
+
assert_1.strict.equal(text, "w", "rebased pos should still refer to 'w'");
|
|
26
|
+
});
|
|
27
|
+
it("rebase past remote delete", () => {
|
|
28
|
+
client.removeRangeRemote(0, 3, ++seq, 0, remoteUserLongId);
|
|
29
|
+
const rebasedPos = client.rebasePosition(6 /* w */, 0, 0);
|
|
30
|
+
const text = getTextAt(rebasedPos);
|
|
31
|
+
assert_1.strict.equal(text, "w", "rebased pos should still refer to 'w'");
|
|
32
|
+
});
|
|
33
|
+
it("rebase on a variety of seqNumberFrom values", () => {
|
|
34
|
+
client.insertTextRemote(0, "abc", undefined, ++seq, 0, remoteUserLongId);
|
|
35
|
+
client.removeRangeRemote(0, 1, ++seq, seq - 1, remoteUserLongId);
|
|
36
|
+
client.insertTextRemote(1, "XYZ@", undefined, ++seq, seq - 1, remoteUserLongId);
|
|
37
|
+
const rebasedPos0 = client.rebasePosition(6 /* into "hello world" */, 0, 0);
|
|
38
|
+
const rebasedPos1 = client.rebasePosition(6 /* into "abchello world" */, 1, 0);
|
|
39
|
+
const rebasedPos2 = client.rebasePosition(6 /* into "bchello world" */, 2, 0);
|
|
40
|
+
const rebasedPos3 = client.rebasePosition(6 /* into "bXYZ@chello world" */, 3, 0);
|
|
41
|
+
assert_1.strict.equal(getTextAt(rebasedPos0), "w");
|
|
42
|
+
assert_1.strict.equal(getTextAt(rebasedPos1), "l");
|
|
43
|
+
assert_1.strict.equal(getTextAt(rebasedPos2), "o");
|
|
44
|
+
assert_1.strict.equal(getTextAt(rebasedPos3), "h");
|
|
45
|
+
});
|
|
46
|
+
describe("with subsequent local changes", () => {
|
|
47
|
+
// Rebasing is made more complicated from the client perspective when there are local changes applied
|
|
48
|
+
// meanwhile, since the local state of the string contains segments that should not be considered
|
|
49
|
+
// when computing the position to rebase to (since they wouldn't be visible remotely)
|
|
50
|
+
let op1;
|
|
51
|
+
let op2;
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
op1 = client.insertTextLocal(5, "123456");
|
|
54
|
+
op2 = client.removeRangeLocal(3, 5);
|
|
55
|
+
});
|
|
56
|
+
// For these tests, rebasedPos conceptually refers to a position that a *remote* client should use in order
|
|
57
|
+
// to get an equivalent position to the one that was applied locally with a different refSeq.
|
|
58
|
+
// Since this suite doesn't actually spin up a remote client, we verify this equivalence by asking
|
|
59
|
+
// the local client to resolve that remote position and confirm the text matches what's expected.
|
|
60
|
+
const expectTextAtRebasedPosMatches = (pos, expected, message) => {
|
|
61
|
+
const localViewOfRebasedPos = client.resolveRemoteClientPosition(pos, seq, remoteUserLongId);
|
|
62
|
+
(0, assert_1.strict)(localViewOfRebasedPos !== undefined, "pos should be defined");
|
|
63
|
+
const text = getTextAt(localViewOfRebasedPos);
|
|
64
|
+
assert_1.strict.equal(text, expected, message);
|
|
65
|
+
};
|
|
66
|
+
it("rebase past remote insert", () => {
|
|
67
|
+
client.insertTextRemote(0, "abc", undefined, ++seq, 0, remoteUserLongId);
|
|
68
|
+
const rebasedPos = client.rebasePosition(6 /* index 6 into "hello world" */, 0, 0);
|
|
69
|
+
const rebasedPos1 = client.rebasePosition(6 /* index 6 into "hello123456 world" */, 0, 1);
|
|
70
|
+
const rebasedPos2 = client.rebasePosition(6 /* index 6 into "hel123456 world" */, 0, 2);
|
|
71
|
+
expectTextAtRebasedPosMatches(rebasedPos, "w");
|
|
72
|
+
client.applyMsg(client.makeOpMessage(op1, ++seq, 0, localUserLongId), true);
|
|
73
|
+
expectTextAtRebasedPosMatches(rebasedPos1, "2");
|
|
74
|
+
client.applyMsg(client.makeOpMessage(op2, ++seq, 0, localUserLongId), true);
|
|
75
|
+
expectTextAtRebasedPosMatches(rebasedPos2, "4");
|
|
76
|
+
});
|
|
77
|
+
it("rebase past remote delete", () => {
|
|
78
|
+
client.removeRangeRemote(0, 2, ++seq, 0, remoteUserLongId);
|
|
79
|
+
const rebasedPos = client.rebasePosition(6 /* index 6 into "hello world" */, 0, 0);
|
|
80
|
+
const rebasedPos1 = client.rebasePosition(6 /* index 6 into "hello123456 world" */, 0, 1);
|
|
81
|
+
const rebasedPos2 = client.rebasePosition(6 /* index 6 into "hel123456 world" */, 0, 2);
|
|
82
|
+
expectTextAtRebasedPosMatches(rebasedPos, "w");
|
|
83
|
+
client.applyMsg(client.makeOpMessage(op1, ++seq, 0, localUserLongId), true);
|
|
84
|
+
expectTextAtRebasedPosMatches(rebasedPos1, "2");
|
|
85
|
+
client.applyMsg(client.makeOpMessage(op2, ++seq, 0, localUserLongId), true);
|
|
86
|
+
expectTextAtRebasedPosMatches(rebasedPos2, "4");
|
|
87
|
+
});
|
|
88
|
+
// Mid-remote delete with meanwhile local edits isn't particularly more interesting than the cases
|
|
89
|
+
// handled above. Instead we include some rebased positions amid the local delete (removal of "lo")
|
|
90
|
+
// as this caught a bug with the original implementation.
|
|
91
|
+
it("rebase mid local delete", () => {
|
|
92
|
+
client.removeRangeRemote(0, 2, ++seq, 0, remoteUserLongId);
|
|
93
|
+
const rebasedPos = client.rebasePosition(4 /* index 4 into "hello world" */, 0, 0);
|
|
94
|
+
const rebasedPos1 = client.rebasePosition(4 /* index 4 into "hello123456 world" */, 0, 1);
|
|
95
|
+
const rebasedPos2 = client.rebasePosition(4 /* index 4 into "hel123456 world" */, 0, 2);
|
|
96
|
+
assert_1.strict.equal(rebasedPos, 2);
|
|
97
|
+
assert_1.strict.equal(rebasedPos1, 2);
|
|
98
|
+
assert_1.strict.equal(rebasedPos2, 2);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
//# sourceMappingURL=client.rebasePosition.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.rebasePosition.spec.js","sourceRoot":"","sources":["../../src/test/client.rebasePosition.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 \"assert\";\nimport { IMergeTreeOp } from \"../ops\";\nimport { TestClient } from \"./testClient\";\n\ndescribe(\"client.rebasePosition\", () => {\n\tconst localUserLongId = \"localUser\";\n\tconst remoteUserLongId = \"remoteUser\";\n\tlet client: TestClient;\n\tlet seq: number;\n\n\tconst getTextAt = (pos: number): string => client.getText(pos, pos + 1);\n\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\n\t\tclient.insertTextLocal(0, \"hello world\");\n\t\tclient.startOrUpdateCollaboration(localUserLongId);\n\t\tseq = 0;\n\t});\n\n\tit(\"rebase past remote insert\", () => {\n\t\tclient.insertTextRemote(0, \"abc\", undefined, ++seq, 0, remoteUserLongId);\n\t\tconst rebasedPos = client.rebasePosition(6 /* \"w\" */, 0, 0);\n\t\tconst text = getTextAt(rebasedPos);\n\t\tassert.equal(text, \"w\", \"rebased pos should still refer to 'w'\");\n\t});\n\n\tit(\"rebase past remote delete\", () => {\n\t\tclient.removeRangeRemote(0, 3, ++seq, 0, remoteUserLongId);\n\t\tconst rebasedPos = client.rebasePosition(6 /* w */, 0, 0);\n\t\tconst text = getTextAt(rebasedPos);\n\t\tassert.equal(text, \"w\", \"rebased pos should still refer to 'w'\");\n\t});\n\n\tit(\"rebase on a variety of seqNumberFrom values\", () => {\n\t\tclient.insertTextRemote(0, \"abc\", undefined, ++seq, 0, remoteUserLongId);\n\t\tclient.removeRangeRemote(0, 1, ++seq, seq - 1, remoteUserLongId);\n\t\tclient.insertTextRemote(1, \"XYZ@\", undefined, ++seq, seq - 1, remoteUserLongId);\n\n\t\tconst rebasedPos0 = client.rebasePosition(6 /* into \"hello world\" */, 0, 0);\n\t\tconst rebasedPos1 = client.rebasePosition(6 /* into \"abchello world\" */, 1, 0);\n\t\tconst rebasedPos2 = client.rebasePosition(6 /* into \"bchello world\" */, 2, 0);\n\t\tconst rebasedPos3 = client.rebasePosition(6 /* into \"bXYZ@chello world\" */, 3, 0);\n\n\t\tassert.equal(getTextAt(rebasedPos0), \"w\");\n\t\tassert.equal(getTextAt(rebasedPos1), \"l\");\n\t\tassert.equal(getTextAt(rebasedPos2), \"o\");\n\t\tassert.equal(getTextAt(rebasedPos3), \"h\");\n\t});\n\n\tdescribe(\"with subsequent local changes\", () => {\n\t\t// Rebasing is made more complicated from the client perspective when there are local changes applied\n\t\t// meanwhile, since the local state of the string contains segments that should not be considered\n\t\t// when computing the position to rebase to (since they wouldn't be visible remotely)\n\n\t\tlet op1: IMergeTreeOp | undefined;\n\t\tlet op2: IMergeTreeOp | undefined;\n\t\tbeforeEach(() => {\n\t\t\top1 = client.insertTextLocal(5, \"123456\");\n\t\t\top2 = client.removeRangeLocal(3, 5);\n\t\t});\n\n\t\t// For these tests, rebasedPos conceptually refers to a position that a *remote* client should use in order\n\t\t// to get an equivalent position to the one that was applied locally with a different refSeq.\n\t\t// Since this suite doesn't actually spin up a remote client, we verify this equivalence by asking\n\t\t// the local client to resolve that remote position and confirm the text matches what's expected.\n\t\tconst expectTextAtRebasedPosMatches = (pos: number, expected: string, message?: string) => {\n\t\t\tconst localViewOfRebasedPos = client.resolveRemoteClientPosition(\n\t\t\t\tpos,\n\t\t\t\tseq,\n\t\t\t\tremoteUserLongId,\n\t\t\t);\n\t\t\tassert(localViewOfRebasedPos !== undefined, \"pos should be defined\");\n\t\t\tconst text = getTextAt(localViewOfRebasedPos);\n\t\t\tassert.equal(text, expected, message);\n\t\t};\n\n\t\tit(\"rebase past remote insert\", () => {\n\t\t\tclient.insertTextRemote(0, \"abc\", undefined, ++seq, 0, remoteUserLongId);\n\t\t\tconst rebasedPos = client.rebasePosition(6 /* index 6 into \"hello world\" */, 0, 0);\n\t\t\tconst rebasedPos1 = client.rebasePosition(\n\t\t\t\t6 /* index 6 into \"hello123456 world\" */,\n\t\t\t\t0,\n\t\t\t\t1,\n\t\t\t);\n\t\t\tconst rebasedPos2 = client.rebasePosition(6 /* index 6 into \"hel123456 world\" */, 0, 2);\n\n\t\t\texpectTextAtRebasedPosMatches(rebasedPos, \"w\");\n\n\t\t\tclient.applyMsg(client.makeOpMessage(op1, ++seq, 0, localUserLongId), true);\n\t\t\texpectTextAtRebasedPosMatches(rebasedPos1, \"2\");\n\n\t\t\tclient.applyMsg(client.makeOpMessage(op2, ++seq, 0, localUserLongId), true);\n\t\t\texpectTextAtRebasedPosMatches(rebasedPos2, \"4\");\n\t\t});\n\n\t\tit(\"rebase past remote delete\", () => {\n\t\t\tclient.removeRangeRemote(0, 2, ++seq, 0, remoteUserLongId);\n\t\t\tconst rebasedPos = client.rebasePosition(6 /* index 6 into \"hello world\" */, 0, 0);\n\t\t\tconst rebasedPos1 = client.rebasePosition(\n\t\t\t\t6 /* index 6 into \"hello123456 world\" */,\n\t\t\t\t0,\n\t\t\t\t1,\n\t\t\t);\n\t\t\tconst rebasedPos2 = client.rebasePosition(6 /* index 6 into \"hel123456 world\" */, 0, 2);\n\n\t\t\texpectTextAtRebasedPosMatches(rebasedPos, \"w\");\n\n\t\t\tclient.applyMsg(client.makeOpMessage(op1, ++seq, 0, localUserLongId), true);\n\t\t\texpectTextAtRebasedPosMatches(rebasedPos1, \"2\");\n\n\t\t\tclient.applyMsg(client.makeOpMessage(op2, ++seq, 0, localUserLongId), true);\n\t\t\texpectTextAtRebasedPosMatches(rebasedPos2, \"4\");\n\t\t});\n\n\t\t// Mid-remote delete with meanwhile local edits isn't particularly more interesting than the cases\n\t\t// handled above. Instead we include some rebased positions amid the local delete (removal of \"lo\")\n\t\t// as this caught a bug with the original implementation.\n\t\tit(\"rebase mid local delete\", () => {\n\t\t\tclient.removeRangeRemote(0, 2, ++seq, 0, remoteUserLongId);\n\t\t\tconst rebasedPos = client.rebasePosition(4 /* index 4 into \"hello world\" */, 0, 0);\n\t\t\tconst rebasedPos1 = client.rebasePosition(\n\t\t\t\t4 /* index 4 into \"hello123456 world\" */,\n\t\t\t\t0,\n\t\t\t\t1,\n\t\t\t);\n\t\t\tconst rebasedPos2 = client.rebasePosition(4 /* index 4 into \"hel123456 world\" */, 0, 2);\n\n\t\t\tassert.equal(rebasedPos, 2);\n\t\t\tassert.equal(rebasedPos1, 2);\n\t\t\tassert.equal(rebasedPos2, 2);\n\t\t});\n\t});\n});\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { IMergeTreeOperationRunnerConfig, IConfigRange } from "./mergeTreeOperationRunner";
|
|
6
|
+
interface IReconnectFarmConfig extends IMergeTreeOperationRunnerConfig {
|
|
7
|
+
minLength: number;
|
|
8
|
+
clients: IConfigRange;
|
|
9
|
+
}
|
|
10
|
+
export declare const defaultOptions: IReconnectFarmConfig;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=client.reconnectFarm.spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.reconnectFarm.spec.d.ts","sourceRoot":"","sources":["../../src/test/client.reconnectFarm.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,EAON,+BAA+B,EAC/B,YAAY,EAEZ,MAAM,4BAA4B,CAAC;AA8CpC,UAAU,oBAAqB,SAAQ,+BAA+B;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;CACtB;AAED,eAAO,MAAM,cAAc,EAAE,oBAO5B,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.defaultOptions = void 0;
|
|
9
|
+
const assert_1 = require("assert");
|
|
10
|
+
const stochastic_test_utils_1 = require("@fluid-private/stochastic-test-utils");
|
|
11
|
+
const mergeTreeOperationRunner_1 = require("./mergeTreeOperationRunner");
|
|
12
|
+
const testClient_1 = require("./testClient");
|
|
13
|
+
function applyMessagesWithReconnect(startingSeq, messageDatas, clients, logger, random) {
|
|
14
|
+
let seq = startingSeq;
|
|
15
|
+
const reconnectingClientIds = clients.length > 2 && random.bool()
|
|
16
|
+
? [clients[1].longClientId, clients[2].longClientId]
|
|
17
|
+
: [clients[1].longClientId];
|
|
18
|
+
const reconnectClientMsgs = new Map(reconnectingClientIds.map((id) => [id, []]));
|
|
19
|
+
let minSeq = 0;
|
|
20
|
+
// log and apply all the ops created in the round
|
|
21
|
+
while (messageDatas.length > 0) {
|
|
22
|
+
const [message, sg] = messageDatas.shift();
|
|
23
|
+
(0, assert_1.strict)(message.clientId, "expected clientId to be defined");
|
|
24
|
+
if (reconnectingClientIds.includes(message.clientId)) {
|
|
25
|
+
reconnectClientMsgs.get(message.clientId).push([message.contents, sg]);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
message.sequenceNumber = ++seq;
|
|
29
|
+
clients.forEach((c) => c.applyMsg(message));
|
|
30
|
+
minSeq = message.minimumSequenceNumber;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const reconnectMsgs = [];
|
|
34
|
+
reconnectClientMsgs.forEach((messageData, clientId) => {
|
|
35
|
+
const client = clients.find(({ longClientId }) => longClientId === clientId);
|
|
36
|
+
messageData.forEach(([op, segmentGroup]) => {
|
|
37
|
+
const newMsg = client.makeOpMessage(client.regeneratePendingOp(op, segmentGroup));
|
|
38
|
+
newMsg.minimumSequenceNumber = minSeq;
|
|
39
|
+
// apply message doesn't use the segment group, so just pass undefined
|
|
40
|
+
reconnectMsgs.push([newMsg, undefined]);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
return (0, mergeTreeOperationRunner_1.applyMessages)(seq, reconnectMsgs, clients, logger);
|
|
44
|
+
}
|
|
45
|
+
exports.defaultOptions = {
|
|
46
|
+
minLength: 16,
|
|
47
|
+
clients: { min: 2, max: 8 },
|
|
48
|
+
opsPerRoundRange: { min: 40, max: 320 },
|
|
49
|
+
rounds: 3,
|
|
50
|
+
operations: [mergeTreeOperationRunner_1.annotateRange, mergeTreeOperationRunner_1.removeRange, mergeTreeOperationRunner_1.insert],
|
|
51
|
+
growthFunc: (input) => input * 2,
|
|
52
|
+
};
|
|
53
|
+
// Generate a list of single character client names, support up to 69 clients
|
|
54
|
+
const clientNames = (0, mergeTreeOperationRunner_1.generateClientNames)();
|
|
55
|
+
function runReconnectFarmTests(opts, extraSeed) {
|
|
56
|
+
(0, mergeTreeOperationRunner_1.doOverRange)(opts.clients, opts.growthFunc.bind(opts), (clientCount) => {
|
|
57
|
+
it(`ReconnectFarm_${clientCount}_${extraSeed ?? 0}`, async () => {
|
|
58
|
+
const random = (0, stochastic_test_utils_1.makeRandom)(0xdeadbeef, 0xfeedbed, clientCount, extraSeed ?? 0);
|
|
59
|
+
const testOpts = { ...opts };
|
|
60
|
+
if (extraSeed) {
|
|
61
|
+
testOpts.resultsFilePostfix ?? (testOpts.resultsFilePostfix = "");
|
|
62
|
+
testOpts.resultsFilePostfix += extraSeed;
|
|
63
|
+
}
|
|
64
|
+
const clients = [new testClient_1.TestClient()];
|
|
65
|
+
clients.forEach((c, i) => c.startOrUpdateCollaboration(clientNames[i]));
|
|
66
|
+
let seq = 0;
|
|
67
|
+
clients.forEach((c) => c.updateMinSeq(seq));
|
|
68
|
+
// Add double the number of clients each iteration
|
|
69
|
+
const targetClients = Math.max(opts.clients.min, clientCount);
|
|
70
|
+
for (let cc = clients.length; cc < targetClients; cc++) {
|
|
71
|
+
const newClient = await testClient_1.TestClient.createFromClientSnapshot(clients[0], clientNames[cc]);
|
|
72
|
+
clients.push(newClient);
|
|
73
|
+
}
|
|
74
|
+
seq = (0, mergeTreeOperationRunner_1.runMergeTreeOperationRunner)(random, seq, clients, testOpts.minLength, testOpts, applyMessagesWithReconnect);
|
|
75
|
+
}).timeout(30 * 1000);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
(0, stochastic_test_utils_1.describeFuzz)("MergeTree.Client", ({ testCount }) => {
|
|
79
|
+
const opts = exports.defaultOptions;
|
|
80
|
+
if (testCount > 1) {
|
|
81
|
+
(0, mergeTreeOperationRunner_1.doOverRange)({ min: 0, max: testCount - 1 }, (x) => x + 1, (seed) => {
|
|
82
|
+
describe(`with seed ${seed}`, () => {
|
|
83
|
+
runReconnectFarmTests(opts, seed);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
runReconnectFarmTests(opts);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=client.reconnectFarm.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.reconnectFarm.spec.js","sourceRoot":"","sources":["../../src/test/client.reconnectFarm.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/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"assert\";\nimport { IRandom, makeRandom, describeFuzz } from \"@fluid-private/stochastic-test-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { IMergeTreeOp } from \"../ops\";\nimport { SegmentGroup } from \"../mergeTreeNodes\";\nimport {\n\tgenerateClientNames,\n\tdoOverRange,\n\trunMergeTreeOperationRunner,\n\tannotateRange,\n\tremoveRange,\n\tapplyMessages,\n\tIMergeTreeOperationRunnerConfig,\n\tIConfigRange,\n\tinsert,\n} from \"./mergeTreeOperationRunner\";\nimport { TestClient } from \"./testClient\";\nimport { TestClientLogger } from \"./testClientLogger\";\n\nfunction applyMessagesWithReconnect(\n\tstartingSeq: number,\n\tmessageDatas: [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][],\n\tclients: readonly TestClient[],\n\tlogger: TestClientLogger,\n\trandom: IRandom,\n) {\n\tlet seq = startingSeq;\n\tconst reconnectingClientIds =\n\t\tclients.length > 2 && random.bool()\n\t\t\t? [clients[1].longClientId!, clients[2].longClientId!]\n\t\t\t: [clients[1].longClientId!];\n\tconst reconnectClientMsgs: Map<string, [IMergeTreeOp, SegmentGroup | SegmentGroup[]][]> =\n\t\tnew Map(reconnectingClientIds.map((id) => [id, []]));\n\tlet minSeq = 0;\n\t// log and apply all the ops created in the round\n\twhile (messageDatas.length > 0) {\n\t\tconst [message, sg] = messageDatas.shift()!;\n\t\tassert(message.clientId, \"expected clientId to be defined\");\n\t\tif (reconnectingClientIds.includes(message.clientId)) {\n\t\t\treconnectClientMsgs.get(message.clientId)!.push([message.contents as IMergeTreeOp, sg]);\n\t\t} else {\n\t\t\tmessage.sequenceNumber = ++seq;\n\t\t\tclients.forEach((c) => c.applyMsg(message));\n\t\t\tminSeq = message.minimumSequenceNumber;\n\t\t}\n\t}\n\n\tconst reconnectMsgs: [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][] = [];\n\treconnectClientMsgs.forEach((messageData, clientId) => {\n\t\tconst client = clients.find(({ longClientId }) => longClientId === clientId)!;\n\t\tmessageData.forEach(([op, segmentGroup]) => {\n\t\t\tconst newMsg = client.makeOpMessage(client.regeneratePendingOp(op, segmentGroup));\n\t\t\tnewMsg.minimumSequenceNumber = minSeq;\n\t\t\t// apply message doesn't use the segment group, so just pass undefined\n\t\t\treconnectMsgs.push([newMsg, undefined as any]);\n\t\t});\n\t});\n\n\treturn applyMessages(seq, reconnectMsgs, clients, logger);\n}\n\ninterface IReconnectFarmConfig extends IMergeTreeOperationRunnerConfig {\n\tminLength: number;\n\tclients: IConfigRange;\n}\n\nexport const defaultOptions: IReconnectFarmConfig = {\n\tminLength: 16,\n\tclients: { min: 2, max: 8 },\n\topsPerRoundRange: { min: 40, max: 320 },\n\trounds: 3,\n\toperations: [annotateRange, removeRange, insert],\n\tgrowthFunc: (input: number) => input * 2,\n};\n\n// Generate a list of single character client names, support up to 69 clients\nconst clientNames = generateClientNames();\n\nfunction runReconnectFarmTests(opts: IReconnectFarmConfig, extraSeed?: number): void {\n\tdoOverRange(opts.clients, opts.growthFunc.bind(opts), (clientCount) => {\n\t\tit(`ReconnectFarm_${clientCount}_${extraSeed ?? 0}`, async () => {\n\t\t\tconst random = makeRandom(0xdeadbeef, 0xfeedbed, clientCount, extraSeed ?? 0);\n\t\t\tconst testOpts = { ...opts };\n\t\t\tif (extraSeed) {\n\t\t\t\ttestOpts.resultsFilePostfix ??= \"\";\n\t\t\t\ttestOpts.resultsFilePostfix += extraSeed;\n\t\t\t}\n\n\t\t\tconst clients: TestClient[] = [new TestClient()];\n\t\t\tclients.forEach((c, i) => c.startOrUpdateCollaboration(clientNames[i]));\n\n\t\t\tlet seq = 0;\n\t\t\tclients.forEach((c) => c.updateMinSeq(seq));\n\n\t\t\t// Add double the number of clients each iteration\n\t\t\tconst targetClients = Math.max(opts.clients.min, clientCount);\n\t\t\tfor (let cc = clients.length; cc < targetClients; cc++) {\n\t\t\t\tconst newClient = await TestClient.createFromClientSnapshot(\n\t\t\t\t\tclients[0],\n\t\t\t\t\tclientNames[cc],\n\t\t\t\t);\n\t\t\t\tclients.push(newClient);\n\t\t\t}\n\n\t\t\tseq = runMergeTreeOperationRunner(\n\t\t\t\trandom,\n\t\t\t\tseq,\n\t\t\t\tclients,\n\t\t\t\ttestOpts.minLength,\n\t\t\t\ttestOpts,\n\t\t\t\tapplyMessagesWithReconnect,\n\t\t\t);\n\t\t}).timeout(30 * 1000);\n\t});\n}\n\ndescribeFuzz(\"MergeTree.Client\", ({ testCount }) => {\n\tconst opts = defaultOptions;\n\n\tif (testCount > 1) {\n\t\tdoOverRange(\n\t\t\t{ min: 0, max: testCount - 1 },\n\t\t\t(x) => x + 1,\n\t\t\t(seed) => {\n\t\t\t\tdescribe(`with seed ${seed}`, () => {\n\t\t\t\t\trunReconnectFarmTests(opts, seed);\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t} else {\n\t\trunReconnectFarmTests(opts);\n\t}\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.replay.spec.d.ts","sourceRoot":"","sources":["../../src/test/client.replay.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
24
|
+
if (mod && mod.__esModule) return mod;
|
|
25
|
+
var result = {};
|
|
26
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
27
|
+
__setModuleDefault(result, mod);
|
|
28
|
+
return result;
|
|
29
|
+
};
|
|
30
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
|
+
};
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
const fs = __importStar(require("fs"));
|
|
35
|
+
const assert_1 = __importDefault(require("assert"));
|
|
36
|
+
const ops_1 = require("../ops");
|
|
37
|
+
const opBuilder_1 = require("../opBuilder");
|
|
38
|
+
const testClient_1 = require("./testClient");
|
|
39
|
+
const mergeTreeOperationRunner_1 = require("./mergeTreeOperationRunner");
|
|
40
|
+
const testClientLogger_1 = require("./testClientLogger");
|
|
41
|
+
describe("MergeTree.Client", () => {
|
|
42
|
+
for (const filePath of fs.readdirSync(mergeTreeOperationRunner_1.replayResultsPath)) {
|
|
43
|
+
it(`Replay ${filePath}`, async () => {
|
|
44
|
+
const file = JSON.parse(fs.readFileSync(`${mergeTreeOperationRunner_1.replayResultsPath}/${filePath}`).toString());
|
|
45
|
+
const msgClients = new Map();
|
|
46
|
+
const originalClient = new testClient_1.TestClient();
|
|
47
|
+
msgClients.set("A", { client: originalClient, msgs: [] });
|
|
48
|
+
originalClient.insertTextLocal(0, file[0].initialText);
|
|
49
|
+
originalClient.startOrUpdateCollaboration("A");
|
|
50
|
+
for (const group of file) {
|
|
51
|
+
for (const msg of group.msgs) {
|
|
52
|
+
(0, assert_1.default)(msg.clientId, "expected clientId to be defined");
|
|
53
|
+
if (!msgClients.has(msg.clientId)) {
|
|
54
|
+
const client = await testClient_1.TestClient.createFromClientSnapshot(originalClient, msg.clientId);
|
|
55
|
+
msgClients.set(msg.clientId, { client, msgs: [] });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
for (const group of file) {
|
|
60
|
+
const logger = new testClientLogger_1.TestClientLogger([...msgClients.values()].map((mc) => mc.client));
|
|
61
|
+
const initialText = logger.validate();
|
|
62
|
+
assert_1.default.strictEqual(initialText, group.initialText, "Initial text not as expected");
|
|
63
|
+
for (const msg of group.msgs) {
|
|
64
|
+
const msgClient = msgClients.get(msg.clientId);
|
|
65
|
+
while (msgClient.msgs.length > 0 &&
|
|
66
|
+
msg.referenceSequenceNumber > msgClient.client.getCurrentSeq()) {
|
|
67
|
+
msgClient.client.applyMsg(msgClient.msgs.shift());
|
|
68
|
+
}
|
|
69
|
+
const op = msg.contents;
|
|
70
|
+
msgClient.client.localTransaction(op.type === ops_1.MergeTreeDeltaType.GROUP ? op : (0, opBuilder_1.createGroupOp)(op));
|
|
71
|
+
msgClients.forEach((mc) => mc.msgs.push(msg));
|
|
72
|
+
}
|
|
73
|
+
msgClients.forEach((mc) => {
|
|
74
|
+
while (mc.msgs.length > 0) {
|
|
75
|
+
mc.client.applyMsg(mc.msgs.shift());
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
const result = logger.validate();
|
|
79
|
+
assert_1.default.strictEqual(result, group.resultText, "Result text not as expected");
|
|
80
|
+
logger.dispose();
|
|
81
|
+
}
|
|
82
|
+
}).timeout(30 * 10000);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
//# sourceMappingURL=client.replay.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.replay.spec.js","sourceRoot":"","sources":["../../src/test/client.replay.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/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport * as fs from \"fs\";\nimport assert from \"assert\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { IMergeTreeOp, MergeTreeDeltaType } from \"../ops\";\nimport { createGroupOp } from \"../opBuilder\";\nimport { TestClient } from \"./testClient\";\nimport { ReplayGroup, replayResultsPath } from \"./mergeTreeOperationRunner\";\nimport { TestClientLogger } from \"./testClientLogger\";\n\ndescribe(\"MergeTree.Client\", () => {\n\tfor (const filePath of fs.readdirSync(replayResultsPath)) {\n\t\tit(`Replay ${filePath}`, async () => {\n\t\t\tconst file: ReplayGroup[] = JSON.parse(\n\t\t\t\tfs.readFileSync(`${replayResultsPath}/${filePath}`).toString(),\n\t\t\t);\n\t\t\tconst msgClients = new Map<\n\t\t\t\tstring,\n\t\t\t\t{ client: TestClient; msgs: ISequencedDocumentMessage[] }\n\t\t\t>();\n\t\t\tconst originalClient = new TestClient();\n\t\t\tmsgClients.set(\"A\", { client: originalClient, msgs: [] });\n\t\t\toriginalClient.insertTextLocal(0, file[0].initialText);\n\t\t\toriginalClient.startOrUpdateCollaboration(\"A\");\n\t\t\tfor (const group of file) {\n\t\t\t\tfor (const msg of group.msgs) {\n\t\t\t\t\tassert(msg.clientId, \"expected clientId to be defined\");\n\t\t\t\t\tif (!msgClients.has(msg.clientId)) {\n\t\t\t\t\t\tconst client = await TestClient.createFromClientSnapshot(\n\t\t\t\t\t\t\toriginalClient,\n\t\t\t\t\t\t\tmsg.clientId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmsgClients.set(msg.clientId, { client, msgs: [] });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const group of file) {\n\t\t\t\tconst logger = new TestClientLogger(\n\t\t\t\t\t[...msgClients.values()].map((mc) => mc.client),\n\t\t\t\t);\n\t\t\t\tconst initialText = logger.validate();\n\t\t\t\tassert.strictEqual(initialText, group.initialText, \"Initial text not as expected\");\n\t\t\t\tfor (const msg of group.msgs) {\n\t\t\t\t\tconst msgClient = msgClients.get(msg.clientId!)!;\n\t\t\t\t\twhile (\n\t\t\t\t\t\tmsgClient.msgs.length > 0 &&\n\t\t\t\t\t\tmsg.referenceSequenceNumber > msgClient.client.getCurrentSeq()\n\t\t\t\t\t) {\n\t\t\t\t\t\tmsgClient.client.applyMsg(msgClient.msgs.shift()!);\n\t\t\t\t\t}\n\t\t\t\t\tconst op = msg.contents as IMergeTreeOp;\n\t\t\t\t\tmsgClient.client.localTransaction(\n\t\t\t\t\t\top.type === MergeTreeDeltaType.GROUP ? op : createGroupOp(op),\n\t\t\t\t\t);\n\t\t\t\t\tmsgClients.forEach((mc) => mc.msgs.push(msg));\n\t\t\t\t}\n\n\t\t\t\tmsgClients.forEach((mc) => {\n\t\t\t\t\twhile (mc.msgs.length > 0) {\n\t\t\t\t\t\tmc.client.applyMsg(mc.msgs.shift()!);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tconst result = logger.validate();\n\t\t\t\tassert.strictEqual(result, group.resultText, \"Result text not as expected\");\n\t\t\t\tlogger.dispose();\n\t\t\t}\n\t\t}).timeout(30 * 10000);\n\t}\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.rollback.spec.d.ts","sourceRoot":"","sources":["../../src/test/client.rollback.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|