@fluidframework/merge-tree 2.22.0 → 2.22.1
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/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +38 -9
- package/dist/mergeTree.js.map +1 -1
- package/dist/test/obliterate.concurrent.spec.js +52 -0
- package/dist/test/obliterate.concurrent.spec.js.map +1 -1
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +38 -9
- package/lib/mergeTree.js.map +1 -1
- package/lib/test/obliterate.concurrent.spec.js +52 -0
- package/lib/test/obliterate.concurrent.spec.js.map +1 -1
- package/package.json +16 -16
- package/src/mergeTree.ts +46 -9
|
@@ -1497,6 +1497,58 @@ for (const incremental of [true, false]) {
|
|
|
1497
1497
|
helper.processAllOps();
|
|
1498
1498
|
helper.logger.validate({ baseText: "8m" });
|
|
1499
1499
|
});
|
|
1500
|
+
// See 'Local obliterate wins post-insertion of segment previously thought to have won' (below) for a simpler
|
|
1501
|
+
// to understand version of this test. This test is the original partial synchronization fuzz variant which
|
|
1502
|
+
// demonstrated that issue, and has been preserved for now in case it catches additional related problems.
|
|
1503
|
+
// Once fuzz testing more meaninfully leverages ops being sent to different clients at different types (partial
|
|
1504
|
+
// synchronization), it's probably fine to remove this.
|
|
1505
|
+
it("fuzz regression: Local obliterate wins post-insertion of segment previously thought to have won", () => {
|
|
1506
|
+
const helper = new PartialSyncTestHelper();
|
|
1507
|
+
helper.insertText("A", 0, "Hx15J");
|
|
1508
|
+
helper.processAllOps();
|
|
1509
|
+
helper.insertText("A", 0, "9T");
|
|
1510
|
+
helper.insertText("B", 0, "c8v");
|
|
1511
|
+
helper.advanceClients("A", "C");
|
|
1512
|
+
helper.removeRange("A", 2, 5);
|
|
1513
|
+
helper.removeRange("A", 0, 1);
|
|
1514
|
+
helper.obliterateRange("A", 0, 3);
|
|
1515
|
+
helper.obliterateRange("C", { pos: 1, side: Side.After }, { pos: 4, side: Side.Before });
|
|
1516
|
+
helper.insertText("B", 0, "4qpo");
|
|
1517
|
+
helper.insertText("C", 2, "fP");
|
|
1518
|
+
helper.insertText("A", 0, "hn");
|
|
1519
|
+
helper.advanceClients("A", "C");
|
|
1520
|
+
helper.obliterateRange("A", { pos: 5, side: Side.After }, { pos: 9, side: Side.After });
|
|
1521
|
+
helper.obliterateRange("B", { pos: 3, side: Side.Before }, { pos: 9, side: Side.After });
|
|
1522
|
+
// At the time of the original bug, this would hit 0xa3f.
|
|
1523
|
+
helper.processAllOps();
|
|
1524
|
+
helper.logger.validate({ baseText: "hn4qpJ" });
|
|
1525
|
+
});
|
|
1526
|
+
// Simpler version of the above test which has the same root cause but reproduces a slightly different failure mode.
|
|
1527
|
+
it("Local obliterate wins post-insertion of segment previously thought to have won", () => {
|
|
1528
|
+
const helper = new PartialSyncTestHelper();
|
|
1529
|
+
helper.insertText("A", 0, "1xx2");
|
|
1530
|
+
helper.processAllOps();
|
|
1531
|
+
// A and B both obliterate the 'xx' segment with an expanding obliterate, then try to insert
|
|
1532
|
+
// into the gap that it leaves.
|
|
1533
|
+
helper.obliterateRange("A", { pos: 0, side: Side.After }, { pos: 3, side: Side.Before });
|
|
1534
|
+
helper.insertText("A", 1, "aaaa");
|
|
1535
|
+
helper.obliterateRange("B", { pos: 0, side: Side.After }, { pos: 3, side: Side.Before });
|
|
1536
|
+
helper.insertText("B", 1, "bbb");
|
|
1537
|
+
helper.advanceClients("A", "B");
|
|
1538
|
+
// Meanwhile, C attempts the same thing without seeing A or B's obliterate & insertions
|
|
1539
|
+
helper.obliterateRange("C", { pos: 0, side: Side.After }, { pos: 3, side: Side.Before });
|
|
1540
|
+
helper.insertText("C", 1, "ccc");
|
|
1541
|
+
// Before seeing C's ops, B attempts to insert more content. Since B hasn't yet seen C's obliterate,
|
|
1542
|
+
// A and B are under the impression that B's obliterate has won and the string contents are '1bbb2'.
|
|
1543
|
+
helper.insertText("B", 5, "B");
|
|
1544
|
+
helper.insertText("A", 5, "A");
|
|
1545
|
+
helper.processAllOps();
|
|
1546
|
+
// By now, all clients realize C actually won the obliterate and should have additionally applied B's
|
|
1547
|
+
// op correctly as it was outside of the obliterated range.
|
|
1548
|
+
// At the time this test was written, client C had trouble recognizing that A and B think that B has won
|
|
1549
|
+
// and merged incorrectly, hitting 'MergeTree insert failed'.
|
|
1550
|
+
helper.logger.validate({ baseText: "1ccc2AB" });
|
|
1551
|
+
});
|
|
1500
1552
|
});
|
|
1501
1553
|
});
|
|
1502
1554
|
}
|