Skip to content

Commit

Permalink
test: Add n-peers chain test (#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
mykola-vrmchk authored Feb 7, 2024
1 parent 7e06810 commit 6cd453c
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 21 deletions.
107 changes: 90 additions & 17 deletions packages/automerge-repo/test/Repo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,80 @@ describe("Repo", () => {
})

describe("with peers (linear network)", async () => {
it("n-peers connected in a line", async () => {
const createNConnectedRepos = async (
numberOfPeers: number,
latency?: number
) => {
const networkAdapters: DummyNetworkAdapter[][] = []
const repos: Repo[] = []
const networkReady: Promise<void>[] = []

// Create n repos and connect them in a line.
for (let idx = 0; idx < numberOfPeers; idx++) {
const network = []

const pair = DummyNetworkAdapter.createConnectedPair({ latency })
networkAdapters.push(pair)

if (idx > 0) {
network.push(networkAdapters[idx - 1][1])
networkReady.push(
eventPromise(networkAdapters[idx - 1][1], "ready")
)
}

if (idx < numberOfPeers - 1) {
network.push(pair[0])
networkReady.push(eventPromise(pair[0], "ready"))
}

const repo = new Repo({
network,
storage: new DummyStorageAdapter(),
peerId: `peer-${idx}` as PeerId,
sharePolicy: async () => true,
})
repos.push(repo)
}

await Promise.all(networkReady)

const connectedPromise = Promise.all(
repos.map(repo => eventPromise(repo.networkSubsystem, "peer"))
)

// Initialize the network.
for (let idx = 0; idx < numberOfPeers; idx++) {
if (idx > 0) {
networkAdapters[idx - 1][1].peerCandidate(
`peer-${idx - 1}` as PeerId
)
}
if (idx < numberOfPeers - 1) {
networkAdapters[idx][0].peerCandidate(`peer-${idx + 1}` as PeerId)
}
}

await connectedPromise

return { repos }
}

const numberOfPeers = 10
const { repos } = await createNConnectedRepos(numberOfPeers, 10)

const handle0 = repos[0].create()
handle0.change((d: any) => {
d.foo = "bar"
})

const handleN = repos[numberOfPeers - 1].find<TestDoc>(handle0.url)

await handleN.whenReady()
assert.deepStrictEqual(handleN.docSync(), { foo: "bar" })
})

const setup = async ({
connectAlice = true,
isCharlieEphemeral = false,
Expand Down Expand Up @@ -1023,36 +1097,35 @@ describe("Repo", () => {
})
})


it('peer receives a document when connection is recovered', async () => {
const alice = "alice" as PeerId;
const bob = "bob" as PeerId;
const [aliceAdapter, bobAdapter] = DummyNetworkAdapter.createConnectedPair();
it("peer receives a document when connection is recovered", async () => {
const alice = "alice" as PeerId
const bob = "bob" as PeerId
const [aliceAdapter, bobAdapter] = DummyNetworkAdapter.createConnectedPair()
const aliceRepo = new Repo({
network: [aliceAdapter],
peerId: alice
peerId: alice,
})
const bobRepo = new Repo({
network: [bobAdapter],
peerId: bob
peerId: bob,
})

const aliceDoc = aliceRepo.create();
aliceDoc.change((doc: any) => doc.text = 'Hello world');
const aliceDoc = aliceRepo.create()
aliceDoc.change((doc: any) => (doc.text = "Hello world"))

const bobDoc = bobRepo.find(aliceDoc.url);
const bobDoc = bobRepo.find(aliceDoc.url)
bobDoc.unavailable()
await bobDoc.whenReady([HandleState.UNAVAILABLE]);
await bobDoc.whenReady([HandleState.UNAVAILABLE])

aliceAdapter.peerCandidate(bob);
aliceAdapter.peerCandidate(bob)
// Bob isn't yet connected to Alice and can't respond to her sync message
await pause(100);
bobAdapter.peerCandidate(alice);
await pause(100)
bobAdapter.peerCandidate(alice)

await bobDoc.whenReady([HandleState.READY]);
await bobDoc.whenReady([HandleState.READY])

assert.equal(bobDoc.isReady(), true);
});
assert.equal(bobDoc.isReady(), true)
})

describe("with peers (mesh network)", () => {
const setup = async () => {
Expand Down
9 changes: 5 additions & 4 deletions packages/automerge-repo/test/helpers/DummyNetworkAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export class DummyNetworkAdapter extends NetworkAdapter {
this.#sendMessage = opts.sendMessage;
}

connect(_: string) {
connect(peerId: PeerId) {
this.peerId = peerId;
if (this.#startReady) {
this.emit("ready", { network: this })
}
Expand All @@ -31,14 +32,14 @@ export class DummyNetworkAdapter extends NetworkAdapter {
this.emit('message', message);
}

static createConnectedPair() {
static createConnectedPair({ latency = 10 }: { latency?: number} = {}) {
const adapter1: DummyNetworkAdapter = new DummyNetworkAdapter({
startReady: true,
sendMessage: (message: Message) => pause(10).then(() => adapter2.receive(message)),
sendMessage: (message: Message) => pause(latency).then(() => adapter2.receive(message)),
});
const adapter2: DummyNetworkAdapter = new DummyNetworkAdapter({
startReady: true,
sendMessage: (message: Message) => pause(10).then(() => adapter1.receive(message)),
sendMessage: (message: Message) => pause(latency).then(() => adapter1.receive(message)),
});

return [adapter1, adapter2];
Expand Down

0 comments on commit 6cd453c

Please sign in to comment.