Skip to content

Commit 949b000

Browse files
authored
fix: start daemons in series (#95)
We store references to the daemon client in the return value of `Promise.all` and use them to stop the daemons after a test run - if one or more daemons fail to start, we lose all references to daemons that started successfully so cannot stop them and the test run hangs. Instead start them individually so we can tear down any that started successfully.
1 parent 544b97a commit 949b000

11 files changed

+134
-136
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@
128128
"clean": "aegir clean",
129129
"lint": "aegir lint",
130130
"dep-check": "aegir dep-check -i protons",
131-
"build": "aegir build",
131+
"build": "aegir build --bundle false",
132132
"postbuild": "cp src/resources/keys/*.key dist/src/resources/keys",
133133
"release": "aegir release"
134134
},

src/connect.ts

+17-18
Original file line numberDiff line numberDiff line change
@@ -22,52 +22,51 @@ export function connectTests (factory: DaemonFactory): void {
2222

2323
function runConnectTests (name: string, factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
2424
describe(`connect using ${name}`, () => {
25-
let daemons: Daemon[]
25+
let daemonA: Daemon
26+
let daemonB: Daemon
2627

2728
// Start Daemons
2829
before(async function () {
2930
this.timeout(20 * 1000)
3031

31-
daemons = await Promise.all([
32-
factory.spawn(optionsA),
33-
factory.spawn(optionsB)
34-
])
32+
daemonA = await factory.spawn(optionsA)
33+
daemonB = await factory.spawn(optionsB)
3534
})
3635

3736
// Stop daemons
3837
after(async function () {
39-
if (daemons != null) {
40-
await Promise.all(
41-
daemons.map(async (daemon) => { await daemon.stop() })
42-
)
43-
}
38+
await Promise.all(
39+
[daemonA, daemonB]
40+
.filter(Boolean)
41+
.map(async d => { await d.stop() })
42+
)
4443
})
4544

4645
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
4746
this.timeout(10 * 1000)
4847

49-
const identify1 = await daemons[0].client.identify()
50-
const identify2 = await daemons[1].client.identify()
48+
const identify1 = await daemonA.client.identify()
49+
const identify2 = await daemonB.client.identify()
5150

5251
// verify connected peers
53-
const knownPeersBeforeConnect1 = await daemons[0].client.listPeers()
52+
const knownPeersBeforeConnect1 = await daemonA.client.listPeers()
5453
expect(knownPeersBeforeConnect1).to.have.lengthOf(0)
5554

56-
const knownPeersBeforeConnect2 = await daemons[1].client.listPeers()
55+
const knownPeersBeforeConnect2 = await daemonB.client.listPeers()
5756
expect(knownPeersBeforeConnect2).to.have.lengthOf(0)
5857

5958
// connect peers
60-
await daemons[0].client.connect(identify2.peerId, identify2.addrs)
59+
await daemonA.client.connect(identify2.peerId, identify2.addrs)
6160

62-
// daemons[0] will take some time to get the peers
61+
// daemonA will take some time to get the peers
6362
await new Promise(resolve => setTimeout(resolve, 1000))
6463

6564
// verify connected peers
66-
const knownPeersAfterConnect1 = await daemons[0].client.listPeers()
65+
const knownPeersAfterConnect1 = await daemonA.client.listPeers()
6766
expect(knownPeersAfterConnect1).to.have.length.greaterThanOrEqual(1)
6867
expect(knownPeersAfterConnect1[0].toString()).to.equal(identify2.peerId.toString())
6968

70-
const knownPeersAfterConnect2 = await daemons[1].client.listPeers()
69+
const knownPeersAfterConnect2 = await daemonB.client.listPeers()
7170
expect(knownPeersAfterConnect2).to.have.length.greaterThanOrEqual(1)
7271
expect(knownPeersAfterConnect2[0].toString()).to.equal(identify1.peerId.toString())
7372
})

src/dht/content-fetching.ts

+13-14
Original file line numberDiff line numberDiff line change
@@ -29,41 +29,40 @@ export function contentFetchingTests (factory: DaemonFactory): void {
2929

3030
function runContentFetchingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
3131
describe('dht.contentFetching', () => {
32-
let daemons: Daemon[]
32+
let daemonA: Daemon
33+
let daemonB: Daemon
3334

3435
// Start Daemons
3536
before(async function () {
3637
this.timeout(20 * 1000)
3738

38-
daemons = await Promise.all([
39-
factory.spawn(optionsA),
40-
factory.spawn(optionsB)
41-
])
39+
daemonA = await factory.spawn(optionsA)
40+
daemonB = await factory.spawn(optionsB)
4241

4342
// connect them
44-
const identify0 = await daemons[0].client.identify()
43+
const identify0 = await daemonA.client.identify()
4544

46-
await daemons[1].client.connect(identify0.peerId, identify0.addrs)
45+
await daemonB.client.connect(identify0.peerId, identify0.addrs)
4746

4847
// jsDaemon1 will take some time to get the peers
4948
await new Promise(resolve => setTimeout(resolve, 1000))
5049
})
5150

5251
// Stop daemons
5352
after(async function () {
54-
if (daemons != null) {
55-
await Promise.all(
56-
daemons.map(async (daemon) => { await daemon.stop() })
57-
)
58-
}
53+
await Promise.all(
54+
[daemonA, daemonB]
55+
.filter(Boolean)
56+
.map(async d => { await d.stop() })
57+
)
5958
})
6059

6160
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
6261
this.timeout(10 * 1000)
6362

64-
await daemons[0].client.dht.put(record.key, record.value)
63+
await daemonA.client.dht.put(record.key, record.value)
6564

66-
const data = await daemons[1].client.dht.get(record.key)
65+
const data = await daemonB.client.dht.get(record.key)
6766
expect(data).to.equalBytes(record.value)
6867
})
6968
})

src/dht/content-routing.ts

+20-18
Original file line numberDiff line numberDiff line change
@@ -27,45 +27,47 @@ export function contentRoutingTests (factory: DaemonFactory): void {
2727

2828
function runContentRoutingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
2929
describe('dht.contentRouting', () => {
30-
let daemons: Daemon[]
30+
let daemonA: Daemon
31+
let daemonB: Daemon
32+
let daemonC: Daemon
3133
let identify: IdentifyResult[]
3234

3335
// Start Daemons
3436
before(async function () {
3537
this.timeout(20 * 1000)
3638

37-
daemons = await Promise.all([
38-
factory.spawn(optionsA),
39-
factory.spawn(optionsB),
40-
factory.spawn(optionsB)
41-
])
39+
daemonA = await factory.spawn(optionsA)
40+
daemonB = await factory.spawn(optionsB)
41+
daemonC = await factory.spawn(optionsB)
4242

43-
identify = await Promise.all(
44-
daemons.map(async d => await d.client.identify())
45-
)
43+
identify = await Promise.all([
44+
daemonA.client.identify(),
45+
daemonB.client.identify(),
46+
daemonC.client.identify()
47+
])
4648

47-
await daemons[0].client.connect(identify[1].peerId, identify[1].addrs)
48-
await daemons[0].client.connect(identify[2].peerId, identify[2].addrs)
49+
await daemonA.client.connect(identify[1].peerId, identify[1].addrs)
50+
await daemonA.client.connect(identify[2].peerId, identify[2].addrs)
4951

5052
// get the peers in the table
5153
await new Promise(resolve => setTimeout(resolve, 1000))
5254
})
5355

5456
// Stop daemons
5557
after(async function () {
56-
if (daemons != null) {
57-
await Promise.all(
58-
daemons.map(async (daemon) => { await daemon.stop() })
59-
)
60-
}
58+
await Promise.all(
59+
[daemonA, daemonB]
60+
.filter(Boolean)
61+
.map(async d => { await d.stop() })
62+
)
6163
})
6264

6365
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
6466
const cid = CID.parse('QmVzw6MPsF96TyXBSRs1ptLoVMWRv5FCYJZZGJSVB2Hp39')
6567

66-
await daemons[0].client.dht.provide(cid)
68+
await daemonA.client.dht.provide(cid)
6769

68-
const providers = await all(daemons[1].client.dht.findProviders(cid, 1))
70+
const providers = await all(daemonB.client.dht.findProviders(cid, 1))
6971

7072
expect(providers).to.exist()
7173
expect(providers.length).to.be.greaterThan(0)

src/dht/peer-routing.ts

+16-16
Original file line numberDiff line numberDiff line change
@@ -21,41 +21,41 @@ export function peerRoutingTests (factory: DaemonFactory): void {
2121

2222
function runPeerRoutingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
2323
describe('dht.peerRouting', () => {
24-
let daemons: Daemon[]
24+
let daemonA: Daemon
25+
let daemonB: Daemon
26+
let daemonC: Daemon
2527

2628
// Start Daemons
2729
before(async function () {
2830
this.timeout(20 * 1000)
2931

30-
daemons = await Promise.all([
31-
factory.spawn(optionsA),
32-
factory.spawn(optionsB),
33-
factory.spawn(optionsB)
34-
])
32+
daemonA = await factory.spawn(optionsA)
33+
daemonB = await factory.spawn(optionsB)
34+
daemonC = await factory.spawn(optionsB)
3535
})
3636

3737
// Stop daemons
3838
after(async function () {
39-
if (daemons != null) {
40-
await Promise.all(
41-
daemons.map(async (daemon) => { await daemon.stop() })
42-
)
43-
}
39+
await Promise.all(
40+
[daemonA, daemonB, daemonC]
41+
.filter(Boolean)
42+
.map(async d => { await d.stop() })
43+
)
4444
})
4545

4646
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
47-
const identify1 = await daemons[1].client.identify()
48-
const identify2 = await daemons[2].client.identify()
47+
const identify1 = await daemonB.client.identify()
48+
const identify2 = await daemonC.client.identify()
4949

5050
// peers need at least one peer in their routing table or they fail with:
5151
// connect 0 => 1
52-
await daemons[0].client.connect(identify1.peerId, identify1.addrs)
52+
await daemonA.client.connect(identify1.peerId, identify1.addrs)
5353

5454
// connect 0 => 2
55-
await daemons[0].client.connect(identify2.peerId, identify2.addrs)
55+
await daemonA.client.connect(identify2.peerId, identify2.addrs)
5656

5757
// peer 1 find peer 2, retry up to 10 times to allow the routing table to refresh
58-
const peerData: PeerInfo = await pRetry(async () => await daemons[1].client.dht.findPeer(identify2.peerId), { retries: 10 })
58+
const peerData: PeerInfo = await pRetry(async () => await daemonB.client.dht.findPeer(identify2.peerId), { retries: 10 })
5959

6060
expect(identify2.addrs.map(ma => ma.toString())).to.include.deep.members(peerData.multiaddrs.map(ma => ma.toString()))
6161
})

src/pubsub/floodsub.ts

+14-17
Original file line numberDiff line numberDiff line change
@@ -22,37 +22,34 @@ export function floodsubTests (factory: DaemonFactory): void {
2222

2323
function runFloodsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
2424
describe('pubsub.floodSub', () => {
25-
let daemons: Daemon[]
25+
let daemonA: Daemon
26+
let daemonB: Daemon
2627

2728
// Start Daemons
2829
before(async function () {
2930
this.timeout(20 * 1000)
3031

31-
daemons = await Promise.all([
32-
factory.spawn(optionsA),
33-
factory.spawn(optionsB)
34-
])
32+
daemonA = await factory.spawn(optionsA)
33+
daemonB = await factory.spawn(optionsB)
3534

36-
const [peerA, peerB] = daemons
37-
const identifyB = await peerB.client.identify()
38-
await peerA.client.connect(identifyB.peerId, identifyB.addrs)
35+
const identifyB = await daemonB.client.identify()
36+
await daemonA.client.connect(identifyB.peerId, identifyB.addrs)
3937
})
4038

4139
// Stop daemons
4240
after(async function () {
43-
if (daemons != null) {
44-
await Promise.all(
45-
daemons.map(async (daemon) => { await daemon.stop() })
46-
)
47-
}
41+
await Promise.all(
42+
[daemonA, daemonB]
43+
.filter(Boolean)
44+
.map(async d => { await d.stop() })
45+
)
4846
})
4947

5048
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
5149
const topic = 'test-topic'
5250
const data = uint8ArrayFromString('test-data')
53-
const [peerA, peerB] = daemons
5451

55-
const subscription = await peerB.client.pubsub.subscribe(topic)
52+
const subscription = await daemonB.client.pubsub.subscribe(topic)
5653
const subscriber = async (): Promise<void> => {
5754
const message = await first(subscription.messages())
5855

@@ -61,8 +58,8 @@ function runFloodsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optio
6158
}
6259

6360
const publisher = async (): Promise<void> => {
64-
await waitForSubscribed(topic, peerA, peerB)
65-
await peerA.client.pubsub.publish(topic, data)
61+
await waitForSubscribed(topic, daemonA, daemonB)
62+
await daemonA.client.pubsub.publish(topic, data)
6663
}
6764

6865
return await Promise.all([

src/pubsub/gossipsub.ts

+14-17
Original file line numberDiff line numberDiff line change
@@ -22,37 +22,34 @@ export function gossipsubTests (factory: DaemonFactory): void {
2222

2323
function runGossipsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
2424
describe('pubsub.gossipsub', () => {
25-
let daemons: Daemon[]
25+
let daemonA: Daemon
26+
let daemonB: Daemon
2627

2728
// Start Daemons
2829
before(async function () {
2930
this.timeout(20 * 1000)
3031

31-
daemons = await Promise.all([
32-
factory.spawn(optionsA),
33-
factory.spawn(optionsB)
34-
])
32+
daemonA = await factory.spawn(optionsA)
33+
daemonB = await factory.spawn(optionsB)
3534

36-
const [peerA, peerB] = daemons
37-
const identifyB = await peerB.client.identify()
38-
await peerA.client.connect(identifyB.peerId, identifyB.addrs)
35+
const identifyB = await daemonB.client.identify()
36+
await daemonA.client.connect(identifyB.peerId, identifyB.addrs)
3937
})
4038

4139
// Stop daemons
4240
after(async function () {
43-
if (daemons != null) {
44-
await Promise.all(
45-
daemons.map(async daemon => { await daemon.stop() })
46-
)
47-
}
41+
await Promise.all(
42+
[daemonA, daemonB]
43+
.filter(Boolean)
44+
.map(async d => { await d.stop() })
45+
)
4846
})
4947

5048
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
5149
const topic = 'test-topic'
5250
const data = uint8ArrayFromString('test-data')
53-
const [peerA, peerB] = daemons
5451

55-
const subscription = await peerB.client.pubsub.subscribe(topic)
52+
const subscription = await daemonB.client.pubsub.subscribe(topic)
5653
const subscriber = async (): Promise<void> => {
5754
const message = await first(subscription.messages())
5855

@@ -61,8 +58,8 @@ function runGossipsubTests (factory: DaemonFactory, optionsA: SpawnOptions, opti
6158
}
6259

6360
const publisher = async (): Promise<void> => {
64-
await waitForSubscribed(topic, peerA, peerB)
65-
await peerA.client.pubsub.publish(topic, data)
61+
await waitForSubscribed(topic, daemonA, daemonB)
62+
await daemonA.client.pubsub.publish(topic, data)
6663
}
6764

6865
return await Promise.all([

0 commit comments

Comments
 (0)