Skip to content

Commit

Permalink
replace replicate-all
Browse files Browse the repository at this point in the history
  • Loading branch information
mixmix committed May 18, 2023
1 parent 0daab96 commit 20ccc90
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 185 deletions.
271 changes: 89 additions & 182 deletions test/add-member.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,209 +253,127 @@ test('addMembers too many members', async (t) => {
await p(alice.close)(true)
})

test('addMembers adds to all the tip epochs and gives keys to all the old epochs as well', async (t) => {
test.only('addMembers adds to all the tip epochs and gives keys to all the old epochs as well', async (t) => {
// alice adds bob and carol
// alice and bob remove carol at the same time, creating forked epochs
// everyone still replicates and sees the fork
// alice adds david to the group, and he should see both forks and the original epoch
const alice = Testbot({
keys: ssbKeys.generate(null, 'alice'),
mfSeed: Buffer.from(
'000000000000000000000000000000000000000000000000000000000000a1ce',
'hex'
),
db2: {},
})
const bob = Testbot({
keys: ssbKeys.generate(null, 'bob'),
mfSeed: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000b0b',
'hex'
),
db2: {},
})
const carol = Testbot({
keys: ssbKeys.generate(null, 'carol'),
mfSeed: Buffer.from(
'00000000000000000000000000000000000000000000000000000000000ca201',
'hex'
),
db2: {},
})
const david = Testbot({
keys: ssbKeys.generate(null, 'david'),
mfSeed: Buffer.from(
'00000000000000000000000000000000000000000000000000000000000da71d',
'hex'
),
db2: {},
})

await Promise.all([
alice.tribes2.start(),
bob.tribes2.start(),
carol.tribes2.start(),
david.tribes2.start(),
])
.then(() => t.pass('clients started'))
.catch((err) => t.error(err))
const run = Run(t)

const alice = Testbot({ name: 'alice', db2: {} })
const bob = Testbot({ name: 'bob', db2: {} })
const carol = Testbot({ name: 'carol', db2: {} })
const david = Testbot({ name: 'david', db2: {} })

await run(
'clients started',
Promise.all([
alice.tribes2.start(),
bob.tribes2.start(),
carol.tribes2.start(),
david.tribes2.start(),
])
)

const [aliceRootId, bobRootId, carolRootId, davidRootId] = (
await Promise.all(
[alice, bob, carol, david].map((peer) => p(peer.metafeeds.findOrCreate)())
await run(
'got peer roots',
Promise.all(
[alice, bob, carol, david].map((peer) =>
p(peer.metafeeds.findOrCreate)()
)
)
)
.then((res) => {
t.pass('got peer roots')
return res
})
.catch((err) => t.error(err))
).map((root) => root.id)

async function replicateAll() {
await p(setTimeout)(4000)
await p(setTimeout)(2000)

const fail = (err, a, b) => {
console.error(`Replication between ${a} and ${b} failed:`, err)
t.error(err)
}
await replicate(alice, bob, carol, david)
.then(() => t.pass('replicated all'))
.catch((err) => t.error(err, 'replicated all'))

await replicate(alice, bob)
.then(() => t.pass('replicated alice and bob'))
.catch((err) => fail(err, 'alice', 'bob'))

await replicate(alice, carol)
.then(() => t.pass('replicated alice and carol'))
.catch((err) => fail(err, 'alice', 'carol'))

await replicate(alice, david)
.then(() => t.pass('replicated alice and david'))
.catch((err) => fail(err, 'alice', 'david'))

await replicate(bob, carol)
.then(() => t.pass('replicated bob and carol'))
.catch((err) => {
p(bob.metafeeds.printTree)(bobRootId, { id: true })
p(bob.metafeeds.printTree)(aliceRootId, { id: true })
p(carol.metafeeds.printTree)(carolRootId, { id: true })
p(carol.metafeeds.printTree)(aliceRootId, { id: true })
fail(err, 'bob', 'carol')
})

await replicate(carol, david)
.then(() => t.pass('replicated carol and david'))
.catch((err) => fail(err, 'carol', 'david'))

await replicate(david, alice)
.then(() => t.pass('replicated david and alice'))
.catch((err) => fail(err, 'david', 'alice'))

await p(setTimeout)(4000)
await p(setTimeout)(2000)
}

await replicateAll()

const { id: groupId, writeKey: firstEpochKey } = await alice.tribes2
.create()
.then((res) => {
t.pass('alice created group')
return res
})
.catch((err) => t.error(err))
const { id: groupId, writeKey: firstEpochKey } = await run(
'alice created group',
alice.tribes2.create()
)
const firstEpochSecret = firstEpochKey.key.toString('base64')

const { key: firstEpochPostId } = await alice.tribes2
.publish({
const { key: firstEpochPostId } = await run(
'alice published in first epoch',
alice.tribes2.publish({
type: 'test',
text: 'first post',
recps: [groupId],
})
.then((res) => {
t.pass('alice published in first epoch')
return res
})
.catch((err) => t.error(err))
)

await alice.tribes2
.addMembers(groupId, [bobRootId, carolRootId])
.then(() => t.pass('alice added bob and carol'))
.catch((err) => t.error(err))
await run(
'alice added bob and carol',
alice.tribes2.addMembers(groupId, [bobRootId, carolRootId])
)

await replicateAll()

await bob.tribes2
.acceptInvite(groupId)
.then(() => t.pass('bob accepted invite'))
.catch((err) => t.error(err))
await run('bob accepted invite', bob.tribes2.acceptInvite(groupId))

await Promise.all([
alice.tribes2.excludeMembers(groupId, [carolRootId]),
bob.tribes2.excludeMembers(groupId, [carolRootId]),
])
.then(() => t.pass('alice and bob excluded carol'))
.catch((err) => t.error(err))
await run(
'alice and bob excluded carol',
Promise.all([
alice.tribes2.excludeMembers(groupId, [carolRootId]),
bob.tribes2.excludeMembers(groupId, [carolRootId]),
])
)

const { key: aliceForkPostId } = await alice.tribes2
.publish({
const { key: aliceForkPostId } = await run(
'alice published in her fork',
alice.tribes2.publish({
type: 'test',
text: 'alice fork post',
recps: [groupId],
})
.then((res) => {
t.pass('alice published in her fork')
return res
})
.catch((err) => t.error(err))
const { writeKey: aliceForkKey } = await alice.tribes2
.get(groupId)
.then((res) => {
t.pass('alice got info on her fork')
return res
})
.catch((err) => t.error(err))
)

const { writeKey: aliceForkKey } = await run(
'alice got info on her fork',
alice.tribes2.get(groupId)
)
const aliceForkSecret = aliceForkKey.key.toString('base64')

const { key: bobForkPostId } = await bob.tribes2
.publish({
const { key: bobForkPostId } = await run(
'bob posted in his fork',
bob.tribes2.publish({
type: 'test',
text: 'bob fork post',
recps: [groupId],
})
.then((res) => {
t.pass('bob posted in his fork')
return res
})
.catch((err) => t.error(err))
const { writeKey: bobForkKey } = await bob.tribes2
.get(groupId)
.then((res) => {
t.pass('bob got info on his fork')
return res
})
.catch((err) => t.error(err))
)

const { writeKey: bobForkKey } = await run(
'bob got info on his fork',
bob.tribes2.get(groupId)
)
const bobForkSecret = bobForkKey.key.toString('base64')

await replicateAll()

const addDavid = await alice.tribes2
.addMembers(groupId, [davidRootId])
.then((res) => {
t.pass('david got added to the group by alice')
return res
})
.catch((err) => t.error(err))

const addDavid = await run(
'david got added to the group by alice',
alice.tribes2.addMembers(groupId, [davidRootId])
)
t.equal(addDavid.length, 2, 'David got added to both forks')

const adds = await Promise.all(
addDavid.map((add) => p(alice.db.get)(add.key))
const adds = await run(
'alice got her additions of david',
Promise.all(addDavid.map((add) => p(alice.db.get)(add.key)))
)
.then((res) => {
t.pass('alice got her additions of david')
return res
})
.catch((err) => t.error(err))
const addContents = adds.map((add) => add.content)

const addAliceFork = addContents.find(
(content) => content.secret === aliceForkSecret
)
Expand Down Expand Up @@ -484,45 +402,34 @@ test('addMembers adds to all the tip epochs and gives keys to all the old epochs
"gave david the secret to the initial epoch, in the addition to bob's fork"
)

await replicate(alice, david)
.then(() => t.pass('replicated'))
.catch((err) => t.error(err))
await run('replicated', replicate(alice, david))

await david.tribes2
.acceptInvite(groupId)
.then(() => t.pass('david accepted invite'))
.catch((err) => t.error(err))
await run('david accepted invite', david.tribes2.acceptInvite(groupId))

const bobForkMsg = await p(david.db.get)(bobForkPostId)
.then((res) => {
t.pass("david got bob's post in his fork")
return res
})
.catch((err) => t.error(err))
const bobForkMsg = await run(
"david got bob's post in his fork",
p(david.db.get)(bobForkPostId)
)
t.notEquals(
typeof bobForkMsg.content,
'string',
"david decrypted the msg in bob's fork"
)

const aliceForkMsg = await p(david.db.get)(aliceForkPostId)
.then((res) => {
t.pass("david got alice's post in her fork")
return res
})
.catch((err) => t.error(err))
const aliceForkMsg = await run(
"david got alice's post in her fork",
p(david.db.get)(aliceForkPostId)
)
t.notEquals(
typeof aliceForkMsg.content,
'string',
"david decrypted the msg in alice's fork"
)

const firstEpochMsg = await p(david.db.get)(firstEpochPostId)
.then((res) => {
t.pass("david got alice's post in the initial epoch")
return res
})
.catch((err) => t.error(err))
const firstEpochMsg = await run(
"david got alice's post in the initial epoch",
p(david.db.get)(firstEpochPostId)
)
t.notEquals(
typeof firstEpochMsg.content,
'string',
Expand All @@ -535,6 +442,6 @@ test('addMembers adds to all the tip epochs and gives keys to all the old epochs
p(carol.close)(true),
p(david.close)(true),
])
.then(() => t.pass('clients got closed'))
.then(() => t.pass('clients close'))
.catch((err) => t.error(err))
})
Loading

0 comments on commit 20ccc90

Please sign in to comment.