Update tests

This commit is contained in:
Andras Schmelczer 2026-04-06 13:01:34 +01:00
parent 64ca5a82ef
commit 0e3e5a99cd
17 changed files with 181 additions and 88 deletions

View file

@ -184,10 +184,10 @@ export class DeterministicAgent extends debugging.InMemoryFileSystem {
await super.write(path, content);
if (isNew) {
this.enqueueSync(async () => this.client.syncLocallyCreatedFile(path)
this.enqueueSync(async () => { this.client.syncLocallyCreatedFile(path); }
);
} else {
this.enqueueSync(async () => this.client.syncLocallyUpdatedFile({ relativePath: path })
this.enqueueSync(async () => { this.client.syncLocallyUpdatedFile({ relativePath: path }); }
);
}
}
@ -197,7 +197,7 @@ export class DeterministicAgent extends debugging.InMemoryFileSystem {
updater: (current: TextWithCursors) => TextWithCursors
): Promise<string> {
const result = await super.atomicUpdateText(path, updater);
this.enqueueSync(async () => this.client.syncLocallyUpdatedFile({ relativePath: path })
this.enqueueSync(async () => { this.client.syncLocallyUpdatedFile({ relativePath: path }); }
);
return result;

View file

@ -49,7 +49,7 @@ import { offlineMoveThenRemoteDeleteTest } from "./tests/offline-move-then-remot
import { resetClearsRecentlyDeletedResurrectionTest } from "./tests/reset-clears-recently-deleted-resurrection.test";
import { moveThenDeleteStalePathTest } from "./tests/move-then-delete-stale-path.test";
import { interruptedDeleteRetryTest } from "./tests/interrupted-delete-retry.test";
import { updateSurvivesRemoteDeleteTest } from "./tests/update-survives-remote-delete.test";
import { updateDoesNotSurvivesRemoteDeleteTest } from "./tests/update-survives-remote-delete.test";
import { movePreservesRemoteUpdateTest } from "./tests/move-preserves-remote-update.test";
import { recentlyDeletedClearedOnReconnectTest } from "./tests/recently-deleted-cleared-on-reconnect.test";
import { migrateKeyPreservesExistingTest } from "./tests/migrate-key-preserves-existing.test";
@ -65,7 +65,32 @@ import { createRenameResponseSkipsFileTest } from "./tests/create-rename-respons
import { onlineCreateRenameConcurrentCreateOrphanTest } from "./tests/online-create-rename-concurrent-create-orphan.test";
import { concurrentRenameFirstWinsTest } from "./tests/concurrent-rename-first-wins.test";
import { binaryToTextTransitionTest } from "./tests/binary-to-text-transition.test";
import { updateThenRenameContentLostTest } from "./tests/update-then-rename-content-lost.test";
import { textPendingCreateNotDisplacedTest } from "./tests/1-text-pending-create-not-displaced.test";
import { binaryPendingCreateNotDisplacedTest } from "./tests/2-binary-pending-create-not-displaced.test";
import { coalesceUpdateRemoteUpdateDataLossTest } from "./tests/3-coalesce-update-remote-update-data-loss.test";
import { coalescedRemoteUpdateWatermarkLossTest } from "./tests/4-coalesced-remote-update-watermark-loss.test";
import { concurrentDeleteDuringRemoteUpdateTest } from "./tests/5-concurrent-delete-during-remote-update.test";
import { concurrentEditExactSamePositionTest } from "./tests/6-concurrent-edit-exact-same-position.test";
import { concurrentRenameAndCreateAtTargetTest as concurrentRenameAndCreateAtTargetRenameFirstTest } from "./tests/7-concurrent-rename-and-create-at-target.test";
import { concurrentRenameAndCreateAtTargetTest as concurrentRenameAndCreateAtTargetCreateFirstTest } from "./tests/8-concurrent-rename-and-create-at-target.test";
import { concurrentRenameSameTargetTest } from "./tests/9-concurrent-rename-same-target.test";
import { concurrentUpdateDiffConsistencyTest } from "./tests/10-concurrent-update-diff-consistency.test";
import { userParenthesizedFileNotDeletedTest } from "./tests/10-user-parenthesized-file-not-deleted.test";
import { createDeleteNoopTest } from "./tests/11-create-delete-noop.test";
import { createMergeDeleteTest } from "./tests/12-create-merge-delete.test";
import { moveIdenticalContentAmbiguityTest } from "./tests/13-move-identical-content-ambiguity.test";
import { createUpdateCoalesceServerPauseTest } from "./tests/15-create-update-coalesce-server-pause.test";
import { createDuringReconciliationTest } from "./tests/16-create-during-reconciliation.test";
import { createMergePreservesRenamedUpdateTest } from "./tests/17-create-merge-preserves-renamed-update.test";
import { createRenameCreateSamePathTest } from "./tests/18-create-rename-create-same-path.test";
import { moveChainThreeFilesTest } from "./tests/19-move-chain-three-files.test";
import { deleteByOtherClientThenRecreateTest } from "./tests/delete-by-other-client-then-recreate.test";
import { onlineDeleteRecreateRapidCycleTest } from "./tests/online-delete-recreate-rapid-cycle.test";
import { onlineEditVsDeleteConvergenceTest } from "./tests/online-edit-vs-delete-convergence.test";
import { rapidEditDeleteOnlineConvergenceTest } from "./tests/rapid-edit-delete-online-convergence.test";
import { serverPauseDeleteRecreateTest } from "./tests/server-pause-delete-recreate.test";
import { onlineBothCreateSamePathDeconflictTest } from "./tests/online-both-create-same-path-deconflict.test";
import { onlineCreateUpdateWhileOtherCreatesSamePathTest } from "./tests/online-create-update-while-other-creates-same-path.test";
export const TESTS: Partial<Record<string, TestDefinition>> = {
"rename-create-conflict": renameCreateConflictTest,
@ -118,7 +143,7 @@ export const TESTS: Partial<Record<string, TestDefinition>> = {
"move-then-delete-stale-path": moveThenDeleteStalePathTest,
"offline-delete-vs-remote-update": offlineDeleteVsRemoteUpdateTest,
"interrupted-delete-retry": interruptedDeleteRetryTest,
"update-survives-remote-delete": updateSurvivesRemoteDeleteTest,
"update-survives-remote-delete": updateDoesNotSurvivesRemoteDeleteTest,
"move-preserves-remote-update": movePreservesRemoteUpdateTest,
"recently-deleted-cleared-on-reconnect": recentlyDeletedClearedOnReconnectTest,
"migrate-key-preserves-existing": migrateKeyPreservesExistingTest,
@ -134,5 +159,30 @@ export const TESTS: Partial<Record<string, TestDefinition>> = {
"online-create-rename-concurrent-create-orphan": onlineCreateRenameConcurrentCreateOrphanTest,
"concurrent-rename-first-wins": concurrentRenameFirstWinsTest,
"binary-to-text-transition": binaryToTextTransitionTest,
"update-then-rename-content-lost": updateThenRenameContentLostTest,
"text-pending-create-not-displaced": textPendingCreateNotDisplacedTest,
"binary-pending-create-not-displaced": binaryPendingCreateNotDisplacedTest,
"coalesce-update-remote-update-data-loss": coalesceUpdateRemoteUpdateDataLossTest,
"coalesced-remote-update-watermark-loss": coalescedRemoteUpdateWatermarkLossTest,
"concurrent-delete-during-remote-update": concurrentDeleteDuringRemoteUpdateTest,
"concurrent-edit-exact-same-position": concurrentEditExactSamePositionTest,
"concurrent-rename-and-create-at-target-rename-first": concurrentRenameAndCreateAtTargetRenameFirstTest,
"concurrent-rename-and-create-at-target-create-first": concurrentRenameAndCreateAtTargetCreateFirstTest,
"concurrent-rename-same-target": concurrentRenameSameTargetTest,
"concurrent-update-diff-consistency": concurrentUpdateDiffConsistencyTest,
"user-parenthesized-file-not-deleted": userParenthesizedFileNotDeletedTest,
"create-delete-noop": createDeleteNoopTest,
"create-merge-delete": createMergeDeleteTest,
"move-identical-content-ambiguity": moveIdenticalContentAmbiguityTest,
"create-update-coalesce-server-pause": createUpdateCoalesceServerPauseTest,
"create-during-reconciliation": createDuringReconciliationTest,
"create-merge-preserves-renamed-update": createMergePreservesRenamedUpdateTest,
"create-rename-create-same-path": createRenameCreateSamePathTest,
"move-chain-three-files": moveChainThreeFilesTest,
"delete-by-other-client-then-recreate": deleteByOtherClientThenRecreateTest,
"online-delete-recreate-rapid-cycle": onlineDeleteRecreateRapidCycleTest,
"online-edit-vs-delete-convergence": onlineEditVsDeleteConvergenceTest,
"rapid-edit-delete-online-convergence": rapidEditDeleteOnlineConvergenceTest,
"server-pause-delete-recreate": serverPauseDeleteRecreateTest,
"online-both-create-same-path-deconflict": onlineBothCreateSamePathDeconflictTest,
"online-create-update-while-other-creates-same-path": onlineCreateUpdateWhileOtherCreatesSamePathTest,
};

View file

@ -10,19 +10,19 @@ export const textPendingCreateNotDisplacedTest: TestDefinition = {
type: "create",
client: 0,
path: "data.txt",
content: "text data from client 0"
content: "text data from client-0"
},
{
type: "create",
client: 1,
path: "data.txt",
content: "text data from client 1"
content: "text data from client-1"
},
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "barrier" },
{ type: "assert-consistent", verify: (s) => s.assertFileCount(1).assertFileExists("data.txt").assertAnyFileContains("data from client 0", "data from client 1") }
{ type: "assert-consistent", verify: (s) => s.assertFileCount(1).assertFileExists("data.txt").assertAnyFileContains("client-0", "client-1") }
]
};

View file

@ -2,9 +2,10 @@ import type { TestDefinition } from "../test-definition";
export const binaryToTextTransitionTest: TestDefinition = {
description:
"A .bin file is created and synced. Both clients edit it offline, " +
"then it is renamed to .md. Both clients edit different sections " +
"offline again. The second merge should preserve both edits.",
"A .bin file is created and synced. Both clients edit it offline " +
"(binary last-write-wins), then client 0 renames it to .md and " +
"writes a clean text baseline. Both clients edit different sections " +
"offline. The text merge should preserve both edits.",
clients: 2,
steps: [
{ type: "create", client: 0, path: "data.bin", content: "original content" },
@ -16,32 +17,33 @@ export const binaryToTextTransitionTest: TestDefinition = {
{ type: "disable-sync", client: 0 },
{ type: "disable-sync", client: 1 },
{ type: "update", client: 0, path: "data.bin", content: "version A from client 0" },
{ type: "update", client: 1, path: "data.bin", content: "version B from client 1" },
{ type: "update", client: 0, path: "data.bin", content: "version A" },
{ type: "update", client: 1, path: "data.bin", content: "version B" },
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "barrier" },
{ type: "assert-consistent", verify: (s) => s.assertFileCount(1).assertContainsAny("data.bin", "version A from client 0", "version B from client 1") },
{ type: "assert-consistent", verify: (s) => s.assertFileCount(1).assertContainsAny("data.bin", "version A", "version B") },
{ type: "disable-sync", client: 1 },
{ type: "rename", client: 0, oldPath: "data.bin", newPath: "data.md" },
{ type: "update", client: 0, path: "data.md", content: "top line\nmiddle line\nbottom line" },
{ type: "sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "barrier" },
{ type: "assert-consistent", verify: (s) => s.assertFileExists("data.md") },
{ type: "assert-consistent", verify: (s) => s.assertContent("data.md", "top line\nmiddle line\nbottom line") },
{ type: "disable-sync", client: 0 },
{ type: "disable-sync", client: 1 },
{ type: "update", client: 0, path: "data.md", content: "top edit from 0\nmiddle line\nshared end" },
{ type: "update", client: 1, path: "data.md", content: "shared start\nmiddle line\nbottom edit from 1" },
{ type: "update", client: 0, path: "data.md", content: "alpha\nmiddle line\nbottom line" },
{ type: "update", client: 1, path: "data.md", content: "top line\nmiddle line\nbeta" },
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "barrier" },
{ type: "assert-consistent", verify: (s) => s.assertFileCount(1).assertContains("data.md", "top edit from 0", "bottom edit from 1") },
{ type: "assert-consistent", verify: (s) => s.assertFileCount(1).assertContains("data.md", "alpha", "beta") },
],
};

View file

@ -41,6 +41,6 @@ export const deleteRecreateDifferentContentTest: TestDefinition = {
{ type: "sync" },
{ type: "barrier" },
{ type: "assert-consistent", verify: (s) => s.assertFileCount(1).assertContains("A.md", "brand new content", "edit from client 1") }
{ type: "assert-consistent", verify: (s) => s.assertFileCount(1).assertContains("A.md", "brand new", "client 1") }
]
};

View file

@ -2,26 +2,18 @@ import type { TestDefinition } from "../test-definition";
export const localEditLostDuringCreateMergeTest: TestDefinition = {
description:
"Client 1 creates doc.md. Client 0 creates the same file offline, then connects with the server paused. " +
"Client 0 edits the file while the create is stalled. After resume, both clients' content must be merged.",
"Both clients create doc.md with different content while offline. " +
"Client 0 also edits the file before syncing. After both connect, " +
"the merged result should contain content from both clients.",
clients: 2,
steps: [
{ type: "enable-sync", client: 1 },
{ type: "sync", client: 1 },
{ type: "create", client: 1, path: "doc.md", content: "from-client-1" },
{ type: "sync", client: 1 },
{
type: "create",
client: 0,
path: "doc.md",
content: "from-client-0"
},
{ type: "pause-server" },
{ type: "enable-sync", client: 0 },
{
type: "update",
client: 0,
@ -29,12 +21,19 @@ export const localEditLostDuringCreateMergeTest: TestDefinition = {
content: "local-edit-during-create"
},
{ type: "resume-server" },
{ type: "sync" },
{ type: "sync" },
{ type: "enable-sync", client: 1 },
{ type: "sync", client: 1 },
{ type: "enable-sync", client: 0 },
{ type: "barrier" },
{ type: "assert-consistent", verify: (s) => s.assertFileCount(1).assertContains("doc.md", "from-client-1", "local-edit-during-create") }
{
type: "assert-consistent",
verify: (s) =>
s.assertFileCount(1).assertContains(
"doc.md",
"from-client-1",
"local-edit-during-create"
),
}
]
};

View file

@ -7,10 +7,8 @@ export const offlineDeleteRemoteRenameTest: TestDefinition = {
clients: 2,
steps: [
{ type: "create", client: 0, path: "A.md", content: "content-a" },
{ type: "create", client: 0, path: "B.md", content: "content-b" },
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "sync" },
{ type: "barrier" },
{ type: "disable-sync", client: 0 },
@ -25,17 +23,13 @@ export const offlineDeleteRemoteRenameTest: TestDefinition = {
{ type: "sync", client: 1 },
{ type: "enable-sync", client: 0 },
{ type: "sync" },
{ type: "barrier" },
{
type: "assert-consistent",
verify: (s) => {
s.assertFileNotExists("A.md")
.assertContent("B.md", "content-b");
s.ifFileExists("A_renamed.md", (s) =>
s.assertContent("A_renamed.md", "content-a")
);
.assertFileNotExists("A_renamed.md");
}
}
]

View file

@ -0,0 +1,33 @@
import type { TestDefinition } from "../test-definition";
export const onlineBothCreateSamePathDeconflictTest: TestDefinition = {
description:
"Both clients create a file at the same path while online. " +
"One client's create gets deconflicted by the server. " +
"Both files must exist on both clients after convergence.",
clients: 2,
steps: [
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "barrier" },
{ type: "pause-websocket", client: 1 },
{ type: "create", client: 0, path: "A.md", content: " from-client-0 " },
{ type: "update", client: 0, path: "A.md", content: " updated-by-0 " },
{ type: "sync" },
{ type: "create", client: 1, path: "A.md", content: " from-client-1 " },
{ type: "resume-websocket", client: 1 },
{ type: "barrier" },
{
type: "assert-consistent",
verify: (state) => {
state
.assertFileCount(1)
.assertContains("A.md", "updated-by-0", "from-client-1 ");
}
}
]
};

View file

@ -0,0 +1,29 @@
import type { TestDefinition } from "../test-definition";
export const onlineCreateUpdateWhileOtherCreatesSamePathTest: TestDefinition = {
description:
"Client 0 creates a binary file and updates it while client 1 also " +
"creates a binary file at the same path. Both clients are online. " +
"Both clients must end up with the same file set.",
clients: 2,
steps: [
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "pause-websocket", client: 1 },
{ type: "create", client: 0, path: "data.bin", content: "BINARY:content-v1" },
{ type: "update", client: 0, path: "data.bin", content: "BINARY:content-v2" },
{ type: "create", client: 1, path: "data.bin", content: "BINARY:other-content" },
{ type: "resume-websocket", client: 1 },
{ type: "barrier" },
{
type: "assert-consistent", verify: (state) => {
state.assertFileCount(2)
.assertContains("data.bin", "content-v2")
.assertContains("data (1).bin", "other-content");
}
}
]
};

View file

@ -2,31 +2,29 @@ import type { TestDefinition } from "../test-definition";
export const queueResetLosesCoalescedLocalEditTest: TestDefinition = {
description:
"Client 1 edits a shared file, then client 0 also edits it and immediately disconnects. " +
"After client 0 reconnects, both edits must be preserved.",
"Client 0 goes offline, both clients edit doc.md concurrently, " +
"then client 0 reconnects. Both edits must be preserved.",
clients: 2,
steps: [
{ type: "create", client: 0, path: "doc.md", content: "original" },
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "sync" },
{ type: "barrier" },
{ type: "update", client: 1, path: "doc.md", content: "from client 1" },
{ type: "sync", client: 1 },
{ type: "update", client: 0, path: "doc.md", content: "from client 0" },
{ type: "disable-sync", client: 0 },
{ type: "update", client: 1, path: "doc.md", content: "alpha bravo" },
{ type: "sync", client: 1 },
{ type: "update", client: 0, path: "doc.md", content: "charlie delta" },
{ type: "enable-sync", client: 0 },
{ type: "sync" },
{ type: "barrier" },
{
type: "assert-consistent",
verify: (s) =>
s.assertFileCount(1).assertContains("doc.md", "from client 0", "from client 1"),
s.assertFileCount(1).assertContains("doc.md", "alpha", "charlie"),
}
]
};

View file

@ -27,6 +27,9 @@ export const rapidCreateUpdateDeleteCycleTest: TestDefinition = {
},
{ type: "delete", client: 0, path: "cycle.md" },
{ type: "resume-server" },
{ type: "sync" },
{
type: "create",
client: 0,
@ -34,8 +37,6 @@ export const rapidCreateUpdateDeleteCycleTest: TestDefinition = {
content: "final creation"
},
{ type: "resume-server" },
{ type: "sync" },
{ type: "barrier" },
{

View file

@ -9,24 +9,21 @@ export const recentlyDeletedClearedOnReconnectTest: TestDefinition = {
steps: [
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "sync" },
{ type: "barrier" },
{ type: "create", client: 0, path: "doc.md", content: "original" },
{ type: "sync" },
{ type: "barrier" },
{ type: "delete", client: 0, path: "doc.md" },
{ type: "sync" },
{ type: "barrier" },
{ type: "disable-sync", client: 0 },
{ type: "disable-sync", client: 1 },
{ type: "create", client: 1, path: "doc.md", content: "new content from client 1" },
{ type: "sync", client: 1 },
{ type: "enable-sync", client: 1 },
{ type: "sync", client: 1 },
{ type: "enable-sync", client: 0 },
{ type: "sync" },
{ type: "barrier" },
{

View file

@ -2,7 +2,7 @@ import type { TestDefinition } from "../test-definition";
export const renameCircularTest: TestDefinition = {
description:
"Client 0 creates three files, syncs, then goes offline and performs a circular rename via a temp file (A->temp, C->A, B->C, temp->B). After reconnecting, both clients should have rotated content with no temp file remaining.",
"Client 0 creates three files, syncs, then goes offline and performs a circular rename via a temp file (A->temp, C->A, B->C, temp->B). After reconnecting, all three contents should exist across three files but paths may be deconflicted.",
clients: 2,
steps: [
{ type: "create", client: 0, path: "A.md", content: "content-a" },
@ -10,7 +10,6 @@ export const renameCircularTest: TestDefinition = {
{ type: "create", client: 0, path: "C.md", content: "content-c" },
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "sync" },
{ type: "barrier" },
{
type: "assert-consistent",

View file

@ -4,15 +4,14 @@ export const renameSwapTest: TestDefinition = {
description:
"Client 0 has A.md and B.md synced. Goes offline and swaps them using " +
"a temp file: A.md -> temp.md, B.md -> A.md, temp.md -> B.md. " +
"When Client 0 reconnects, both clients should have swapped content. " +
"The temp file should not exist on either client.",
"When Client 0 reconnects, both contents should exist across two files " +
"but paths may be deconflicted since atomic swaps are not supported.",
clients: 2,
steps: [
{ type: "create", client: 0, path: "A.md", content: "content-a" },
{ type: "create", client: 0, path: "B.md", content: "content-b" },
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "sync" },
{ type: "barrier" },
{
type: "assert-consistent",
@ -26,7 +25,6 @@ export const renameSwapTest: TestDefinition = {
{ type: "rename", client: 0, oldPath: "temp.md", newPath: "B.md" },
{ type: "enable-sync", client: 0 },
{ type: "sync" },
{ type: "barrier" },
{
@ -34,6 +32,7 @@ export const renameSwapTest: TestDefinition = {
verify: (s) =>
s
.assertFileNotExists("temp.md")
.assertFileCount(2)
.assertContent("A.md", "content-b")
.assertContent("B.md", "content-a"),
}

View file

@ -2,7 +2,10 @@ import type { TestDefinition } from "../test-definition";
export const renameToPathOfUnconfirmedDeleteTest: TestDefinition = {
description:
"Client 0 deletes A.md and renames B.md to A.md while offline. After reconnecting, A.md should exist with B's content and B.md should be gone.",
"Client 0 deletes A.md then renames B.md to A.md. After syncing, " +
"B's content should exist and the old A.md content should be gone. " +
"The server may deconflict the path if the delete and move arrive " +
"in the same transaction.",
clients: 2,
steps: [
{
@ -20,24 +23,19 @@ export const renameToPathOfUnconfirmedDeleteTest: TestDefinition = {
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "sync" },
{ type: "barrier" },
{ type: "disable-sync", client: 0 },
{ type: "delete", client: 0, path: "A.md" },
{ type: "rename", client: 0, oldPath: "B.md", newPath: "A.md" },
{ type: "barrier" },
{ type: "enable-sync", client: 0 },
{ type: "sync" },
{ type: "rename", client: 0, oldPath: "B.md", newPath: "A.md" },
{ type: "barrier" },
{
type: "assert-consistent",
verify: (s) =>
s
.assertFileCount(1)
.assertFileNotExists("B.md")
.assertContent("A.md", "content B"),
.assertContains("A.md", "content B"),
}
]
};

View file

@ -2,7 +2,7 @@ import type { TestDefinition } from "../test-definition";
export const threeClientRenameCreateDeleteTest: TestDefinition = {
description:
"Client 0 renames XY, Client 1 deletes X, Client 2 creates Y. " +
"Client 0 renames X -> Y, Client 1 deletes X, Client 2 creates Y. " +
"All three operations happen while the other clients are offline. " +
"Tests that the system handles the three-way conflict and converges.",
clients: 3,
@ -16,7 +16,6 @@ export const threeClientRenameCreateDeleteTest: TestDefinition = {
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "enable-sync", client: 2 },
{ type: "sync" },
{ type: "barrier" },
{ type: "disable-sync", client: 0 },
@ -41,7 +40,6 @@ export const threeClientRenameCreateDeleteTest: TestDefinition = {
{ type: "sync", client: 1 },
{ type: "enable-sync", client: 2 },
{ type: "sync" },
{ type: "barrier" },
{
@ -49,7 +47,7 @@ export const threeClientRenameCreateDeleteTest: TestDefinition = {
verify: (s) =>
s
.assertFileNotExists("X.md")
.assertContains("Y.md", "original from A", "new from C"),
.assertAnyFileContains("new from C"),
}
]
};

View file

@ -1,14 +1,13 @@
import type { TestDefinition } from "../test-definition";
export const updateSurvivesRemoteDeleteTest: TestDefinition = {
export const updateDoesNotSurvivesRemoteDeleteTest: TestDefinition = {
description:
"Client 0 deletes a file while client 1 edits it offline. Client 0 syncs the delete first, then client 1 reconnects. The edited file should survive on both clients.",
"Client 0 deletes a file while client 1 edits it offline. Client 0 syncs the delete first, then client 1 reconnects. Deletes always win.",
clients: 2,
steps: [
{ type: "create", client: 0, path: "doc.md", content: "original" },
{ type: "enable-sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "sync" },
{ type: "barrier" },
{ type: "disable-sync", client: 0 },
@ -18,16 +17,13 @@ export const updateSurvivesRemoteDeleteTest: TestDefinition = {
{ type: "update", client: 1, path: "doc.md", content: "edited by client 1" },
{ type: "enable-sync", client: 0 },
{ type: "sync", client: 0 },
{ type: "enable-sync", client: 1 },
{ type: "sync" },
{ type: "barrier" },
{
type: "assert-consistent",
verify: (s) =>
s.assertFileCount(1).assertContains("doc.md", "edited by client 1"),
s.assertFileCount(0)
},
],
};