@libp2p/interface-compliance-tests 0.0.0 → 0.2.0
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/LICENSE +4 -0
- package/README.md +25 -0
- package/dist/src/connection/connection.d.ts +5 -0
- package/dist/src/connection/connection.d.ts.map +1 -0
- package/dist/src/connection/connection.js +148 -0
- package/dist/src/connection/connection.js.map +1 -0
- package/dist/src/connection/index.d.ts +5 -0
- package/dist/src/connection/index.d.ts.map +1 -0
- package/dist/src/connection/index.js +5 -0
- package/dist/src/connection/index.js.map +1 -0
- package/dist/src/crypto/index.d.ts +5 -0
- package/dist/src/crypto/index.d.ts.map +1 -0
- package/dist/src/crypto/index.js +78 -0
- package/dist/src/crypto/index.js.map +1 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/peer-discovery/index.d.ts +6 -0
- package/dist/src/peer-discovery/index.d.ts.map +1 -0
- package/dist/src/peer-discovery/index.js +63 -0
- package/dist/src/peer-discovery/index.js.map +1 -0
- package/dist/src/pubsub/api.d.ts +6 -0
- package/dist/src/pubsub/api.d.ts.map +1 -0
- package/dist/src/pubsub/api.js +65 -0
- package/dist/src/pubsub/api.js.map +1 -0
- package/dist/src/pubsub/connection-handlers.d.ts +6 -0
- package/dist/src/pubsub/connection-handlers.d.ts.map +1 -0
- package/dist/src/pubsub/connection-handlers.js +279 -0
- package/dist/src/pubsub/connection-handlers.js.map +1 -0
- package/dist/src/pubsub/emit-self.d.ts +6 -0
- package/dist/src/pubsub/emit-self.d.ts.map +1 -0
- package/dist/src/pubsub/emit-self.js +51 -0
- package/dist/src/pubsub/emit-self.js.map +1 -0
- package/dist/src/pubsub/index.d.ts +6 -0
- package/dist/src/pubsub/index.d.ts.map +1 -0
- package/dist/src/pubsub/index.js +17 -0
- package/dist/src/pubsub/index.js.map +1 -0
- package/dist/src/pubsub/messages.d.ts +6 -0
- package/dist/src/pubsub/messages.d.ts.map +1 -0
- package/dist/src/pubsub/messages.js +93 -0
- package/dist/src/pubsub/messages.js.map +1 -0
- package/dist/src/pubsub/multiple-nodes.d.ts +6 -0
- package/dist/src/pubsub/multiple-nodes.d.ts.map +1 -0
- package/dist/src/pubsub/multiple-nodes.js +283 -0
- package/dist/src/pubsub/multiple-nodes.js.map +1 -0
- package/dist/src/pubsub/two-nodes.d.ts +6 -0
- package/dist/src/pubsub/two-nodes.d.ts.map +1 -0
- package/dist/src/pubsub/two-nodes.js +127 -0
- package/dist/src/pubsub/two-nodes.js.map +1 -0
- package/dist/src/pubsub/utils.d.ts +3 -0
- package/dist/src/pubsub/utils.d.ts.map +1 -0
- package/dist/src/pubsub/utils.js +11 -0
- package/dist/src/pubsub/utils.js.map +1 -0
- package/dist/src/record/index.d.ts +5 -0
- package/dist/src/record/index.d.ts.map +1 -0
- package/dist/src/record/index.js +25 -0
- package/dist/src/record/index.js.map +1 -0
- package/dist/src/stream-muxer/base-test.d.ts +5 -0
- package/dist/src/stream-muxer/base-test.d.ts.map +1 -0
- package/dist/src/stream-muxer/base-test.js +123 -0
- package/dist/src/stream-muxer/base-test.js.map +1 -0
- package/dist/src/stream-muxer/close-test.d.ts +5 -0
- package/dist/src/stream-muxer/close-test.d.ts.map +1 -0
- package/dist/src/stream-muxer/close-test.js +103 -0
- package/dist/src/stream-muxer/close-test.js.map +1 -0
- package/dist/src/stream-muxer/index.d.ts +5 -0
- package/dist/src/stream-muxer/index.d.ts.map +1 -0
- package/dist/src/stream-muxer/index.js +13 -0
- package/dist/src/stream-muxer/index.js.map +1 -0
- package/dist/src/stream-muxer/mega-stress-test.d.ts +5 -0
- package/dist/src/stream-muxer/mega-stress-test.d.ts.map +1 -0
- package/dist/src/stream-muxer/mega-stress-test.js +8 -0
- package/dist/src/stream-muxer/mega-stress-test.js.map +1 -0
- package/dist/src/stream-muxer/spawner.d.ts +4 -0
- package/dist/src/stream-muxer/spawner.d.ts.map +1 -0
- package/dist/src/stream-muxer/spawner.js +32 -0
- package/dist/src/stream-muxer/spawner.js.map +1 -0
- package/dist/src/stream-muxer/stress-test.d.ts +5 -0
- package/dist/src/stream-muxer/stress-test.d.ts.map +1 -0
- package/dist/src/stream-muxer/stress-test.js +21 -0
- package/dist/src/stream-muxer/stress-test.js.map +1 -0
- package/dist/src/topology/multicodec-topology.d.ts +5 -0
- package/dist/src/topology/multicodec-topology.d.ts.map +1 -0
- package/dist/src/topology/multicodec-topology.js +109 -0
- package/dist/src/topology/multicodec-topology.js.map +1 -0
- package/dist/src/topology/topology.d.ts +5 -0
- package/dist/src/topology/topology.d.ts.map +1 -0
- package/dist/src/topology/topology.js +29 -0
- package/dist/src/topology/topology.js.map +1 -0
- package/dist/src/transport/dial-test.d.ts +5 -0
- package/dist/src/transport/dial-test.d.ts.map +1 -0
- package/dist/src/transport/dial-test.js +78 -0
- package/dist/src/transport/dial-test.js.map +1 -0
- package/dist/src/transport/filter-test.d.ts +5 -0
- package/dist/src/transport/filter-test.d.ts.map +1 -0
- package/dist/src/transport/filter-test.js +19 -0
- package/dist/src/transport/filter-test.js.map +1 -0
- package/dist/src/transport/index.d.ts +18 -0
- package/dist/src/transport/index.d.ts.map +1 -0
- package/dist/src/transport/index.js +11 -0
- package/dist/src/transport/index.js.map +1 -0
- package/dist/src/transport/listen-test.d.ts +5 -0
- package/dist/src/transport/listen-test.d.ts.map +1 -0
- package/dist/src/transport/listen-test.js +116 -0
- package/dist/src/transport/listen-test.js.map +1 -0
- package/dist/src/transport/utils/index.d.ts +8 -0
- package/dist/src/transport/utils/index.d.ts.map +1 -0
- package/dist/src/transport/utils/index.js +104 -0
- package/dist/src/transport/utils/index.js.map +1 -0
- package/dist/src/utils/peers.d.ts +7 -0
- package/dist/src/utils/peers.d.ts.map +1 -0
- package/dist/src/utils/peers.js +26 -0
- package/dist/src/utils/peers.js.map +1 -0
- package/dist/test/connection/index.spec.d.ts +2 -0
- package/dist/test/connection/index.spec.d.ts.map +1 -0
- package/dist/test/connection/index.spec.js +71 -0
- package/dist/test/connection/index.spec.js.map +1 -0
- package/dist/test/crypto/index.spec.d.ts +2 -0
- package/dist/test/crypto/index.spec.d.ts.map +1 -0
- package/dist/test/crypto/index.spec.js +11 -0
- package/dist/test/crypto/index.spec.js.map +1 -0
- package/dist/test/crypto/mock-crypto.d.ts +4 -0
- package/dist/test/crypto/mock-crypto.d.ts.map +1 -0
- package/dist/test/crypto/mock-crypto.js +93 -0
- package/dist/test/crypto/mock-crypto.js.map +1 -0
- package/dist/test/peer-discovery/index.spec.d.ts +2 -0
- package/dist/test/peer-discovery/index.spec.d.ts.map +1 -0
- package/dist/test/peer-discovery/index.spec.js +18 -0
- package/dist/test/peer-discovery/index.spec.js.map +1 -0
- package/dist/test/peer-discovery/mock-discovery.d.ts +20 -0
- package/dist/test/peer-discovery/mock-discovery.d.ts.map +1 -0
- package/dist/test/peer-discovery/mock-discovery.js +39 -0
- package/dist/test/peer-discovery/mock-discovery.js.map +1 -0
- package/dist/test/topology/mock-peer-store.d.ts +12 -0
- package/dist/test/topology/mock-peer-store.d.ts.map +1 -0
- package/dist/test/topology/mock-peer-store.js +18 -0
- package/dist/test/topology/mock-peer-store.js.map +1 -0
- package/dist/test/topology/multicodec-topology.spec.d.ts +2 -0
- package/dist/test/topology/multicodec-topology.spec.d.ts.map +1 -0
- package/dist/test/topology/multicodec-topology.spec.js +45 -0
- package/dist/test/topology/multicodec-topology.spec.js.map +1 -0
- package/dist/test/topology/topology.spec.d.ts +2 -0
- package/dist/test/topology/topology.spec.d.ts.map +1 -0
- package/dist/test/topology/topology.spec.js +21 -0
- package/dist/test/topology/topology.spec.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +120 -4
- package/src/connection/README.md +256 -0
- package/src/connection/connection.ts +178 -0
- package/src/connection/index.ts +7 -0
- package/src/crypto/index.ts +104 -0
- package/src/index.ts +5 -0
- package/src/peer-discovery/index.ts +87 -0
- package/src/pubsub/api.ts +89 -0
- package/src/pubsub/connection-handlers.ts +356 -0
- package/src/pubsub/emit-self.ts +67 -0
- package/src/pubsub/index.ts +20 -0
- package/src/pubsub/messages.ts +111 -0
- package/src/pubsub/multiple-nodes.ts +353 -0
- package/src/pubsub/two-nodes.ts +175 -0
- package/src/pubsub/utils.ts +13 -0
- package/src/record/index.ts +32 -0
- package/src/stream-muxer/base-test.ts +154 -0
- package/src/stream-muxer/close-test.ts +124 -0
- package/src/stream-muxer/index.ts +15 -0
- package/src/stream-muxer/mega-stress-test.ts +11 -0
- package/src/stream-muxer/spawner.ts +52 -0
- package/src/stream-muxer/stress-test.ts +24 -0
- package/src/topology/multicodec-topology.ts +136 -0
- package/src/topology/topology.ts +38 -0
- package/src/transport/dial-test.ts +98 -0
- package/src/transport/filter-test.ts +26 -0
- package/src/transport/index.ts +29 -0
- package/src/transport/listen-test.ts +152 -0
- package/src/transport/utils/index.ts +123 -0
- package/src/utils/peers.ts +25 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { expect } from 'aegir/utils/chai.js'
|
|
2
|
+
import sinon from 'sinon'
|
|
3
|
+
import pDefer from 'p-defer'
|
|
4
|
+
import pWaitFor from 'p-wait-for'
|
|
5
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
6
|
+
import type { TestSetup } from '../index.js'
|
|
7
|
+
import type { PubSub, Message } from '@libp2p/interfaces/pubsub'
|
|
8
|
+
import type { Startable } from '@libp2p/interfaces'
|
|
9
|
+
|
|
10
|
+
const topic = 'foo'
|
|
11
|
+
const data = uint8ArrayFromString('bar')
|
|
12
|
+
|
|
13
|
+
export default (common: TestSetup<PubSub & Startable>) => {
|
|
14
|
+
describe('pubsub api', () => {
|
|
15
|
+
let pubsub: PubSub & Startable
|
|
16
|
+
|
|
17
|
+
// Create pubsub router
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
pubsub = await common.setup()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
afterEach(async () => {
|
|
23
|
+
sinon.restore()
|
|
24
|
+
await pubsub.stop()
|
|
25
|
+
await common.teardown()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('can start correctly', async () => {
|
|
29
|
+
sinon.spy(pubsub.registrar, 'register')
|
|
30
|
+
|
|
31
|
+
await pubsub.start()
|
|
32
|
+
|
|
33
|
+
expect(pubsub.started).to.eql(true)
|
|
34
|
+
expect(pubsub.registrar.register).to.have.property('callCount', 1)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('can stop correctly', async () => {
|
|
38
|
+
sinon.spy(pubsub.registrar, 'unregister')
|
|
39
|
+
|
|
40
|
+
await pubsub.start()
|
|
41
|
+
await pubsub.stop()
|
|
42
|
+
|
|
43
|
+
expect(pubsub.started).to.eql(false)
|
|
44
|
+
expect(pubsub.registrar.unregister).to.have.property('callCount', 1)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('can subscribe and unsubscribe correctly', async () => {
|
|
48
|
+
const handler = () => {
|
|
49
|
+
throw new Error('a message should not be received')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
await pubsub.start()
|
|
53
|
+
pubsub.subscribe(topic)
|
|
54
|
+
pubsub.on('topic', handler)
|
|
55
|
+
|
|
56
|
+
await pWaitFor(() => {
|
|
57
|
+
const topics = pubsub.getTopics()
|
|
58
|
+
return topics.length === 1 && topics[0] === topic
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
pubsub.unsubscribe(topic)
|
|
62
|
+
|
|
63
|
+
await pWaitFor(() => pubsub.getTopics().length === 0)
|
|
64
|
+
|
|
65
|
+
// Publish to guarantee the handler is not called
|
|
66
|
+
await pubsub.publish(topic, data)
|
|
67
|
+
|
|
68
|
+
await pubsub.stop()
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('can subscribe and publish correctly', async () => {
|
|
72
|
+
const defer = pDefer()
|
|
73
|
+
|
|
74
|
+
const handler = (msg: Message) => {
|
|
75
|
+
expect(msg).to.not.eql(undefined)
|
|
76
|
+
defer.resolve()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await pubsub.start()
|
|
80
|
+
|
|
81
|
+
pubsub.subscribe(topic)
|
|
82
|
+
pubsub.on(topic, handler)
|
|
83
|
+
await pubsub.publish(topic, data)
|
|
84
|
+
await defer.promise
|
|
85
|
+
|
|
86
|
+
await pubsub.stop()
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
}
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import { expect } from 'aegir/utils/chai.js'
|
|
2
|
+
import sinon from 'sinon'
|
|
3
|
+
import pDefer from 'p-defer'
|
|
4
|
+
import pWaitFor from 'p-wait-for'
|
|
5
|
+
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
6
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
7
|
+
import { expectSet } from './utils.js'
|
|
8
|
+
import type { TestSetup } from '../index.js'
|
|
9
|
+
import type { PubSub, Message } from '@libp2p/interfaces/pubsub'
|
|
10
|
+
import type { Startable } from '@libp2p/interfaces'
|
|
11
|
+
|
|
12
|
+
export default (common: TestSetup<PubSub & Startable>) => {
|
|
13
|
+
describe('pubsub connection handlers', () => {
|
|
14
|
+
let psA: PubSub & Startable
|
|
15
|
+
let psB: PubSub & Startable
|
|
16
|
+
|
|
17
|
+
describe('nodes send state on connection', () => {
|
|
18
|
+
// Create pubsub nodes and connect them
|
|
19
|
+
before(async () => {
|
|
20
|
+
psA = await common.setup()
|
|
21
|
+
psB = await common.setup()
|
|
22
|
+
|
|
23
|
+
expect(psA.peers.size).to.be.eql(0)
|
|
24
|
+
expect(psB.peers.size).to.be.eql(0)
|
|
25
|
+
|
|
26
|
+
// Start pubsub
|
|
27
|
+
await psA.start()
|
|
28
|
+
await psB.start()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Make subscriptions prior to nodes connected
|
|
32
|
+
before(() => {
|
|
33
|
+
psA.subscribe('Za')
|
|
34
|
+
psB.subscribe('Zb')
|
|
35
|
+
|
|
36
|
+
expect(psA.peers.size).to.equal(0)
|
|
37
|
+
expectSet(psA.subscriptions, ['Za'])
|
|
38
|
+
expect(psB.peers.size).to.equal(0)
|
|
39
|
+
expectSet(psB.subscriptions, ['Zb'])
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
after(async () => {
|
|
43
|
+
sinon.restore()
|
|
44
|
+
await common.teardown()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('existing subscriptions are sent upon peer connection', async function () {
|
|
48
|
+
await Promise.all([
|
|
49
|
+
// @ts-expect-error protected fields
|
|
50
|
+
psA._libp2p.dial(psB.peerId),
|
|
51
|
+
new Promise((resolve) => psA.once('pubsub:subscription-change', resolve)),
|
|
52
|
+
new Promise((resolve) => psB.once('pubsub:subscription-change', resolve))
|
|
53
|
+
])
|
|
54
|
+
|
|
55
|
+
expect(psA.peers.size).to.equal(1)
|
|
56
|
+
expect(psB.peers.size).to.equal(1)
|
|
57
|
+
|
|
58
|
+
expectSet(psA.subscriptions, ['Za'])
|
|
59
|
+
|
|
60
|
+
expectSet(psB.topics.get('Za'), [psA.peerId.toString()])
|
|
61
|
+
|
|
62
|
+
expectSet(psB.subscriptions, ['Zb'])
|
|
63
|
+
|
|
64
|
+
expectSet(psA.topics.get('Zb'), [psB.peerId.toString()])
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
describe('pubsub started before connect', () => {
|
|
69
|
+
// Create pubsub nodes and start them
|
|
70
|
+
beforeEach(async () => {
|
|
71
|
+
psA = await common.setup()
|
|
72
|
+
psB = await common.setup()
|
|
73
|
+
|
|
74
|
+
await psA.start()
|
|
75
|
+
await psB.start()
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
afterEach(async () => {
|
|
79
|
+
sinon.restore()
|
|
80
|
+
|
|
81
|
+
await common.teardown()
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('should get notified of connected peers on dial', async () => {
|
|
85
|
+
// @ts-expect-error protected fields
|
|
86
|
+
const connection = await psA._libp2p.dial(psB.peerId)
|
|
87
|
+
expect(connection).to.exist()
|
|
88
|
+
|
|
89
|
+
return await Promise.all([
|
|
90
|
+
pWaitFor(() => psA.peers.size === 1),
|
|
91
|
+
pWaitFor(() => psB.peers.size === 1)
|
|
92
|
+
])
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('should receive pubsub messages', async () => {
|
|
96
|
+
const defer = pDefer()
|
|
97
|
+
const topic = 'test-topic'
|
|
98
|
+
const data = uint8ArrayFromString('hey!')
|
|
99
|
+
|
|
100
|
+
// @ts-expect-error protected fields
|
|
101
|
+
await psA._libp2p.dial(psB.peerId)
|
|
102
|
+
|
|
103
|
+
let subscribedTopics = psA.getTopics()
|
|
104
|
+
expect(subscribedTopics).to.not.include(topic)
|
|
105
|
+
|
|
106
|
+
psA.on(topic, (msg) => {
|
|
107
|
+
expect(msg.data).to.equalBytes(data)
|
|
108
|
+
defer.resolve()
|
|
109
|
+
})
|
|
110
|
+
psA.subscribe(topic)
|
|
111
|
+
|
|
112
|
+
subscribedTopics = psA.getTopics()
|
|
113
|
+
expect(subscribedTopics).to.include(topic)
|
|
114
|
+
|
|
115
|
+
// wait for psB to know about psA subscription
|
|
116
|
+
await pWaitFor(() => {
|
|
117
|
+
const subscribedPeers = psB.getSubscribers(topic)
|
|
118
|
+
return subscribedPeers.includes(psA.peerId.toString())
|
|
119
|
+
})
|
|
120
|
+
void psB.publish(topic, data)
|
|
121
|
+
|
|
122
|
+
await defer.promise
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
describe('pubsub started after connect', () => {
|
|
127
|
+
// Create pubsub nodes
|
|
128
|
+
beforeEach(async () => {
|
|
129
|
+
psA = await common.setup()
|
|
130
|
+
psB = await common.setup()
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
afterEach(async () => {
|
|
134
|
+
sinon.restore()
|
|
135
|
+
|
|
136
|
+
await psA.stop()
|
|
137
|
+
await psB.stop()
|
|
138
|
+
|
|
139
|
+
await common.teardown()
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('should get notified of connected peers after starting', async () => {
|
|
143
|
+
// @ts-expect-error protected fields
|
|
144
|
+
const connection = await psA._libp2p.dial(psB.peerId)
|
|
145
|
+
expect(connection).to.exist()
|
|
146
|
+
expect(psA.peers.size).to.be.eql(0)
|
|
147
|
+
expect(psB.peers.size).to.be.eql(0)
|
|
148
|
+
|
|
149
|
+
await psA.start()
|
|
150
|
+
await psB.start()
|
|
151
|
+
|
|
152
|
+
return await Promise.all([
|
|
153
|
+
pWaitFor(() => psA.peers.size === 1),
|
|
154
|
+
pWaitFor(() => psB.peers.size === 1)
|
|
155
|
+
])
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
it('should receive pubsub messages', async () => {
|
|
159
|
+
const defer = pDefer()
|
|
160
|
+
const topic = 'test-topic'
|
|
161
|
+
const data = uint8ArrayFromString('hey!')
|
|
162
|
+
|
|
163
|
+
// @ts-expect-error protected fields
|
|
164
|
+
await psA._libp2p.dial(psB.peerId)
|
|
165
|
+
|
|
166
|
+
await psA.start()
|
|
167
|
+
await psB.start()
|
|
168
|
+
|
|
169
|
+
await Promise.all([
|
|
170
|
+
pWaitFor(() => psA.peers.size === 1),
|
|
171
|
+
pWaitFor(() => psB.peers.size === 1)
|
|
172
|
+
])
|
|
173
|
+
|
|
174
|
+
let subscribedTopics = psA.getTopics()
|
|
175
|
+
expect(subscribedTopics).to.not.include(topic)
|
|
176
|
+
|
|
177
|
+
psA.on(topic, (msg) => {
|
|
178
|
+
expect(msg.data).to.equalBytes(data)
|
|
179
|
+
defer.resolve()
|
|
180
|
+
})
|
|
181
|
+
psA.subscribe(topic)
|
|
182
|
+
|
|
183
|
+
subscribedTopics = psA.getTopics()
|
|
184
|
+
expect(subscribedTopics).to.include(topic)
|
|
185
|
+
|
|
186
|
+
// wait for psB to know about psA subscription
|
|
187
|
+
await pWaitFor(() => {
|
|
188
|
+
const subscribedPeers = psB.getSubscribers(topic)
|
|
189
|
+
return subscribedPeers.includes(psA.peerId.toString())
|
|
190
|
+
})
|
|
191
|
+
void psB.publish(topic, data)
|
|
192
|
+
|
|
193
|
+
await defer.promise
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
describe('pubsub with intermittent connections', () => {
|
|
198
|
+
// Create pubsub nodes and start them
|
|
199
|
+
beforeEach(async () => {
|
|
200
|
+
psA = await common.setup()
|
|
201
|
+
psB = await common.setup()
|
|
202
|
+
|
|
203
|
+
await psA.start()
|
|
204
|
+
await psB.start()
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
afterEach(async () => {
|
|
208
|
+
sinon.restore()
|
|
209
|
+
|
|
210
|
+
await psA.stop()
|
|
211
|
+
await psB.stop()
|
|
212
|
+
|
|
213
|
+
await common.teardown()
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
it('should receive pubsub messages after a node restart', async function () {
|
|
217
|
+
const topic = 'test-topic'
|
|
218
|
+
const data = uint8ArrayFromString('hey!')
|
|
219
|
+
const psAid = psA.peerId.toString()
|
|
220
|
+
|
|
221
|
+
let counter = 0
|
|
222
|
+
const defer1 = pDefer()
|
|
223
|
+
const defer2 = pDefer()
|
|
224
|
+
|
|
225
|
+
// @ts-expect-error protected fields
|
|
226
|
+
await psA._libp2p.dial(psB.peerId)
|
|
227
|
+
|
|
228
|
+
let subscribedTopics = psA.getTopics()
|
|
229
|
+
expect(subscribedTopics).to.not.include(topic)
|
|
230
|
+
|
|
231
|
+
psA.on(topic, (msg) => {
|
|
232
|
+
expect(msg.data).to.equalBytes(data)
|
|
233
|
+
counter++
|
|
234
|
+
counter === 1 ? defer1.resolve() : defer2.resolve()
|
|
235
|
+
})
|
|
236
|
+
psA.subscribe(topic)
|
|
237
|
+
|
|
238
|
+
subscribedTopics = psA.getTopics()
|
|
239
|
+
expect(subscribedTopics).to.include(topic)
|
|
240
|
+
|
|
241
|
+
// wait for psB to know about psA subscription
|
|
242
|
+
await pWaitFor(() => {
|
|
243
|
+
const subscribedPeers = psB.getSubscribers(topic)
|
|
244
|
+
return subscribedPeers.includes(psAid)
|
|
245
|
+
})
|
|
246
|
+
void psB.publish(topic, data)
|
|
247
|
+
|
|
248
|
+
await defer1.promise
|
|
249
|
+
|
|
250
|
+
await psB.stop()
|
|
251
|
+
// @ts-expect-error protected fields
|
|
252
|
+
await psB._libp2p.stop()
|
|
253
|
+
await pWaitFor(() => {
|
|
254
|
+
// @ts-expect-error protected fields
|
|
255
|
+
const aHasConnectionToB = psA._libp2p.connectionManager.get(psB.peerId)
|
|
256
|
+
// @ts-expect-error protected fields
|
|
257
|
+
const bHasConnectionToA = psB._libp2p.connectionManager.get(psA.peerId)
|
|
258
|
+
|
|
259
|
+
return aHasConnectionToB != null && bHasConnectionToA != null
|
|
260
|
+
})
|
|
261
|
+
// @ts-expect-error protected fields
|
|
262
|
+
await psB._libp2p.start()
|
|
263
|
+
await psB.start()
|
|
264
|
+
|
|
265
|
+
// @ts-expect-error protected fields
|
|
266
|
+
psA._libp2p.peerStore.addressBook.set(psB.peerId, psB._libp2p.multiaddrs)
|
|
267
|
+
// @ts-expect-error protected fields
|
|
268
|
+
await psA._libp2p.dial(psB.peerId)
|
|
269
|
+
|
|
270
|
+
// wait for remoteLibp2p to know about libp2p subscription
|
|
271
|
+
await pWaitFor(() => {
|
|
272
|
+
const subscribedPeers = psB.getSubscribers(topic)
|
|
273
|
+
return subscribedPeers.includes(psAid)
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
void psB.publish(topic, data)
|
|
277
|
+
|
|
278
|
+
await defer2.promise
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
it('should handle quick reconnects with a delayed disconnect', async () => {
|
|
282
|
+
// Subscribe on both
|
|
283
|
+
let aReceivedFirstMessageFromB = false
|
|
284
|
+
let aReceivedSecondMessageFromB = false
|
|
285
|
+
let bReceivedFirstMessageFromA = false
|
|
286
|
+
let bReceivedSecondMessageFromA = false
|
|
287
|
+
|
|
288
|
+
const handlerSpyA = (message: Message) => {
|
|
289
|
+
const data = uint8ArrayToString(message.data)
|
|
290
|
+
|
|
291
|
+
if (data === 'message-from-b-1') {
|
|
292
|
+
aReceivedFirstMessageFromB = true
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (data === 'message-from-b-2') {
|
|
296
|
+
aReceivedSecondMessageFromB = true
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const handlerSpyB = (message: Message) => {
|
|
300
|
+
const data = uint8ArrayToString(message.data)
|
|
301
|
+
|
|
302
|
+
if (data === 'message-from-a-1') {
|
|
303
|
+
bReceivedFirstMessageFromA = true
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (data === 'message-from-a-2') {
|
|
307
|
+
bReceivedSecondMessageFromA = true
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const topic = 'reconnect-channel'
|
|
312
|
+
|
|
313
|
+
psA.on(topic, handlerSpyA)
|
|
314
|
+
psB.on(topic, handlerSpyB)
|
|
315
|
+
psA.subscribe(topic)
|
|
316
|
+
psB.subscribe(topic)
|
|
317
|
+
|
|
318
|
+
// Create two connections to the remote peer
|
|
319
|
+
// @ts-expect-error protected fields
|
|
320
|
+
const originalConnection = await psA._libp2p.dialer.connectToPeer(psB.peerId)
|
|
321
|
+
// second connection
|
|
322
|
+
// @ts-expect-error protected fields
|
|
323
|
+
await psA._libp2p.dialer.connectToPeer(psB.peerId)
|
|
324
|
+
// @ts-expect-error protected fields
|
|
325
|
+
expect(psA._libp2p.connections.get(psB.peerId.toString())).to.have.length(2)
|
|
326
|
+
|
|
327
|
+
// Wait for subscriptions to occur
|
|
328
|
+
await pWaitFor(() => {
|
|
329
|
+
return psA.getSubscribers(topic).includes(psB.peerId.toString()) &&
|
|
330
|
+
psB.getSubscribers(topic).includes(psA.peerId.toString())
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
// Verify messages go both ways
|
|
334
|
+
void psA.publish(topic, uint8ArrayFromString('message-from-a-1'))
|
|
335
|
+
void psB.publish(topic, uint8ArrayFromString('message-from-b-1'))
|
|
336
|
+
await pWaitFor(() => {
|
|
337
|
+
return aReceivedFirstMessageFromB && bReceivedFirstMessageFromA
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
// Disconnect the first connection (this acts as a delayed reconnect)
|
|
341
|
+
// @ts-expect-error protected fields
|
|
342
|
+
const psAConnUpdateSpy = sinon.spy(psA._libp2p.connectionManager.connections, 'set')
|
|
343
|
+
|
|
344
|
+
await originalConnection.close()
|
|
345
|
+
await pWaitFor(() => psAConnUpdateSpy.callCount === 1)
|
|
346
|
+
|
|
347
|
+
// Verify messages go both ways after the disconnect
|
|
348
|
+
void psA.publish(topic, uint8ArrayFromString('message-from-a-2'))
|
|
349
|
+
void psB.publish(topic, uint8ArrayFromString('message-from-b-2'))
|
|
350
|
+
await pWaitFor(() => {
|
|
351
|
+
return aReceivedSecondMessageFromB && bReceivedSecondMessageFromA
|
|
352
|
+
})
|
|
353
|
+
})
|
|
354
|
+
})
|
|
355
|
+
})
|
|
356
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { expect } from 'aegir/utils/chai.js'
|
|
2
|
+
import sinon from 'sinon'
|
|
3
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
4
|
+
import type { TestSetup } from '../index.js'
|
|
5
|
+
import type { PubSub, PubsubOptions } from '@libp2p/interfaces/pubsub'
|
|
6
|
+
import type { Startable } from '@libp2p/interfaces'
|
|
7
|
+
|
|
8
|
+
const topic = 'foo'
|
|
9
|
+
const data = uint8ArrayFromString('bar')
|
|
10
|
+
const shouldNotHappen = () => expect.fail()
|
|
11
|
+
|
|
12
|
+
export default (common: TestSetup<PubSub & Startable, Partial<PubsubOptions>>) => {
|
|
13
|
+
describe('emit self', () => {
|
|
14
|
+
let pubsub: PubSub & Startable
|
|
15
|
+
|
|
16
|
+
describe('enabled', () => {
|
|
17
|
+
before(async () => {
|
|
18
|
+
pubsub = await common.setup({ emitSelf: true })
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
before(async () => {
|
|
22
|
+
await pubsub.start()
|
|
23
|
+
pubsub.subscribe(topic)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
after(async () => {
|
|
27
|
+
sinon.restore()
|
|
28
|
+
await pubsub.stop()
|
|
29
|
+
await common.teardown()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should emit to self on publish', async () => {
|
|
33
|
+
const promise = new Promise((resolve) => pubsub.once(topic, resolve))
|
|
34
|
+
|
|
35
|
+
void pubsub.publish(topic, data)
|
|
36
|
+
|
|
37
|
+
return await promise
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('disabled', () => {
|
|
42
|
+
before(async () => {
|
|
43
|
+
pubsub = await common.setup({ emitSelf: false })
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
before(async () => {
|
|
47
|
+
await pubsub.start()
|
|
48
|
+
pubsub.subscribe(topic)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
after(async () => {
|
|
52
|
+
sinon.restore()
|
|
53
|
+
await pubsub.stop()
|
|
54
|
+
await common.teardown()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('should not emit to self on publish', async () => {
|
|
58
|
+
pubsub.once(topic, () => shouldNotHappen)
|
|
59
|
+
|
|
60
|
+
void pubsub.publish(topic, data)
|
|
61
|
+
|
|
62
|
+
// Wait 1 second to guarantee that self is not noticed
|
|
63
|
+
return await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import apiTest from './api.js'
|
|
2
|
+
import emitSelfTest from './emit-self.js'
|
|
3
|
+
import messagesTest from './messages.js'
|
|
4
|
+
import connectionHandlersTest from './connection-handlers.js'
|
|
5
|
+
import twoNodesTest from './two-nodes.js'
|
|
6
|
+
import multipleNodesTest from './multiple-nodes.js'
|
|
7
|
+
import type { TestSetup } from '../index.js'
|
|
8
|
+
import type { PubSub } from '@libp2p/interfaces/pubsub'
|
|
9
|
+
import type { Startable } from '@libp2p/interfaces'
|
|
10
|
+
|
|
11
|
+
export default (common: TestSetup<PubSub & Startable>) => {
|
|
12
|
+
describe('interface-pubsub compliance tests', () => {
|
|
13
|
+
apiTest(common)
|
|
14
|
+
emitSelfTest(common)
|
|
15
|
+
messagesTest(common)
|
|
16
|
+
connectionHandlersTest(common)
|
|
17
|
+
twoNodesTest(common)
|
|
18
|
+
multipleNodesTest(common)
|
|
19
|
+
})
|
|
20
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { expect } from 'aegir/utils/chai.js'
|
|
2
|
+
import sinon from 'sinon'
|
|
3
|
+
import * as PeerIdFactory from '@libp2p/peer-id-factory'
|
|
4
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
5
|
+
import * as utils from '@libp2p/pubsub/utils'
|
|
6
|
+
import { PeerStreams } from '@libp2p/pubsub/peer-streams'
|
|
7
|
+
import type { TestSetup } from '../index.js'
|
|
8
|
+
import type { PubSub } from '@libp2p/interfaces/pubsub'
|
|
9
|
+
import type { Startable } from '@libp2p/interfaces'
|
|
10
|
+
|
|
11
|
+
const topic = 'foo'
|
|
12
|
+
const data = uint8ArrayFromString('bar')
|
|
13
|
+
|
|
14
|
+
export default (common: TestSetup<PubSub & Startable>) => {
|
|
15
|
+
describe('messages', () => {
|
|
16
|
+
let pubsub: PubSub & Startable
|
|
17
|
+
|
|
18
|
+
// Create pubsub router
|
|
19
|
+
beforeEach(async () => {
|
|
20
|
+
pubsub = await common.setup()
|
|
21
|
+
await pubsub.start()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
afterEach(async () => {
|
|
25
|
+
sinon.restore()
|
|
26
|
+
await pubsub.stop()
|
|
27
|
+
await common.teardown()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('should emit normalized signed messages on publish', async () => {
|
|
31
|
+
pubsub.globalSignaturePolicy = 'StrictSign'
|
|
32
|
+
// @ts-expect-error protected field
|
|
33
|
+
sinon.spy(pubsub, '_emitMessage')
|
|
34
|
+
|
|
35
|
+
await pubsub.publish(topic, data)
|
|
36
|
+
// @ts-expect-error protected field
|
|
37
|
+
expect(pubsub._emitMessage.callCount).to.eql(1)
|
|
38
|
+
// @ts-expect-error protected field
|
|
39
|
+
const [messageToEmit] = pubsub._emitMessage.getCall(0).args
|
|
40
|
+
|
|
41
|
+
expect(messageToEmit.seqno).to.not.eql(undefined)
|
|
42
|
+
expect(messageToEmit.key).to.not.eql(undefined)
|
|
43
|
+
expect(messageToEmit.signature).to.not.eql(undefined)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('should drop unsigned messages', async () => {
|
|
47
|
+
// @ts-expect-error protected field
|
|
48
|
+
sinon.spy(pubsub, '_emitMessage')
|
|
49
|
+
// @ts-expect-error protected field
|
|
50
|
+
sinon.spy(pubsub, '_publish')
|
|
51
|
+
sinon.spy(pubsub, 'validate')
|
|
52
|
+
|
|
53
|
+
const peerStream = new PeerStreams({
|
|
54
|
+
id: await PeerIdFactory.createEd25519PeerId(),
|
|
55
|
+
protocol: 'test'
|
|
56
|
+
})
|
|
57
|
+
const rpc = {
|
|
58
|
+
subscriptions: [],
|
|
59
|
+
msgs: [{
|
|
60
|
+
receivedFrom: peerStream.id.toString(),
|
|
61
|
+
from: peerStream.id.toBytes(),
|
|
62
|
+
data,
|
|
63
|
+
seqno: utils.randomSeqno(),
|
|
64
|
+
topicIDs: [topic]
|
|
65
|
+
}]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
pubsub.subscribe(topic)
|
|
69
|
+
// @ts-expect-error protected field
|
|
70
|
+
await pubsub._processRpc(peerStream.id.toString(), peerStream, rpc)
|
|
71
|
+
|
|
72
|
+
expect(pubsub.validate).to.have.property('callCount', 1)
|
|
73
|
+
// @ts-expect-error protected field
|
|
74
|
+
expect(pubsub._emitMessage).to.have.property('called', false)
|
|
75
|
+
// @ts-expect-error protected field
|
|
76
|
+
expect(pubsub._publish).to.have.property('called', false)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('should not drop unsigned messages if strict signing is disabled', async () => {
|
|
80
|
+
pubsub.globalSignaturePolicy = 'StrictNoSign'
|
|
81
|
+
// @ts-expect-error protected field
|
|
82
|
+
sinon.spy(pubsub, '_emitMessage')
|
|
83
|
+
// @ts-expect-error protected field
|
|
84
|
+
sinon.spy(pubsub, '_publish')
|
|
85
|
+
sinon.spy(pubsub, 'validate')
|
|
86
|
+
|
|
87
|
+
const peerStream = new PeerStreams({
|
|
88
|
+
id: await PeerIdFactory.createEd25519PeerId(),
|
|
89
|
+
protocol: 'test'
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
const rpc = {
|
|
93
|
+
subscriptions: [],
|
|
94
|
+
msgs: [{
|
|
95
|
+
data,
|
|
96
|
+
topicIDs: [topic]
|
|
97
|
+
}]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
pubsub.subscribe(topic)
|
|
101
|
+
// @ts-expect-error protected field
|
|
102
|
+
await pubsub._processRpc(peerStream.id.toString(), peerStream, rpc)
|
|
103
|
+
|
|
104
|
+
expect(pubsub.validate).to.have.property('callCount', 1)
|
|
105
|
+
// @ts-expect-error protected field
|
|
106
|
+
expect(pubsub._emitMessage).to.have.property('called', 1)
|
|
107
|
+
// @ts-expect-error protected field
|
|
108
|
+
expect(pubsub._publish).to.have.property('called', 1)
|
|
109
|
+
})
|
|
110
|
+
})
|
|
111
|
+
}
|