@libp2p/interface-compliance-tests 3.0.7-ea8a0637 → 3.0.7-eabf6f36
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/README.md +9 -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 +150 -0
- package/dist/src/connection/index.js.map +1 -0
- package/dist/src/connection-encryption/index.d.ts +5 -0
- package/dist/src/connection-encryption/index.d.ts.map +1 -0
- package/dist/src/connection-encryption/index.js +71 -0
- package/dist/src/connection-encryption/index.js.map +1 -0
- package/dist/src/connection-encryption/utils/index.d.ts +3 -0
- package/dist/src/connection-encryption/utils/index.d.ts.map +1 -0
- package/dist/src/connection-encryption/utils/index.js +19 -0
- package/dist/src/connection-encryption/utils/index.js.map +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/is-valid-tick.d.ts.map +1 -1
- package/dist/src/is-valid-tick.js.map +1 -1
- package/dist/src/mocks/connection-encrypter.d.ts +3 -0
- package/dist/src/mocks/connection-encrypter.d.ts.map +1 -0
- package/dist/src/mocks/connection-encrypter.js +98 -0
- package/dist/src/mocks/connection-encrypter.js.map +1 -0
- package/dist/src/mocks/connection-gater.d.ts +3 -0
- package/dist/src/mocks/connection-gater.d.ts.map +1 -0
- package/dist/src/mocks/connection-gater.js +17 -0
- package/dist/src/mocks/connection-gater.js.map +1 -0
- package/dist/src/mocks/connection-manager.d.ts +29 -0
- package/dist/src/mocks/connection-manager.d.ts.map +1 -0
- package/dist/src/mocks/connection-manager.js +145 -0
- package/dist/src/mocks/connection-manager.js.map +1 -0
- package/dist/src/mocks/connection.d.ts +32 -0
- package/dist/src/mocks/connection.d.ts.map +1 -0
- package/dist/src/mocks/connection.js +167 -0
- package/dist/src/mocks/connection.js.map +1 -0
- package/dist/src/mocks/duplex.d.ts +3 -0
- package/dist/src/mocks/duplex.d.ts.map +1 -0
- package/dist/src/mocks/duplex.js +9 -0
- package/dist/src/mocks/duplex.js.map +1 -0
- package/dist/src/mocks/index.d.ts +13 -0
- package/dist/src/mocks/index.d.ts.map +1 -0
- package/dist/src/mocks/index.js +11 -0
- package/dist/src/mocks/index.js.map +1 -0
- package/dist/src/mocks/metrics.d.ts +3 -0
- package/dist/src/mocks/metrics.d.ts.map +1 -0
- package/dist/src/mocks/metrics.js +115 -0
- package/dist/src/mocks/metrics.js.map +1 -0
- package/dist/src/mocks/multiaddr-connection.d.ts +17 -0
- package/dist/src/mocks/multiaddr-connection.d.ts.map +1 -0
- package/dist/src/mocks/multiaddr-connection.js +60 -0
- package/dist/src/mocks/multiaddr-connection.js.map +1 -0
- package/dist/src/mocks/muxer.d.ts +36 -0
- package/dist/src/mocks/muxer.d.ts.map +1 -0
- package/dist/src/mocks/muxer.js +213 -0
- package/dist/src/mocks/muxer.js.map +1 -0
- package/dist/src/mocks/peer-discovery.d.ts +22 -0
- package/dist/src/mocks/peer-discovery.d.ts.map +1 -0
- package/dist/src/mocks/peer-discovery.js +47 -0
- package/dist/src/mocks/peer-discovery.js.map +1 -0
- package/dist/src/mocks/registrar.d.ts +18 -0
- package/dist/src/mocks/registrar.d.ts.map +1 -0
- package/dist/src/mocks/registrar.js +66 -0
- package/dist/src/mocks/registrar.js.map +1 -0
- package/dist/src/mocks/upgrader.d.ts +10 -0
- package/dist/src/mocks/upgrader.d.ts.map +1 -0
- package/dist/src/mocks/upgrader.js +31 -0
- package/dist/src/mocks/upgrader.js.map +1 -0
- package/dist/src/peer-discovery/index.d.ts +5 -0
- package/dist/src/peer-discovery/index.d.ts.map +1 -0
- package/dist/src/peer-discovery/index.js +66 -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 +87 -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 +329 -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 +80 -0
- package/dist/src/pubsub/emit-self.js.map +1 -0
- package/dist/src/pubsub/index.d.ts +18 -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 +48 -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 +350 -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 +217 -0
- package/dist/src/pubsub/two-nodes.js.map +1 -0
- package/dist/src/pubsub/utils.d.ts +6 -0
- package/dist/src/pubsub/utils.d.ts.map +1 -0
- package/dist/src/pubsub/utils.js +22 -0
- package/dist/src/pubsub/utils.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 +153 -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 +357 -0
- package/dist/src/stream-muxer/close-test.js.map +1 -0
- package/dist/src/stream-muxer/fixtures/pb/message.d.ts +13 -0
- package/dist/src/stream-muxer/fixtures/pb/message.d.ts.map +1 -0
- package/dist/src/stream-muxer/fixtures/pb/message.js +67 -0
- package/dist/src/stream-muxer/fixtures/pb/message.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 +11 -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 +37 -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 +23 -0
- package/dist/src/stream-muxer/stress-test.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 +98 -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 +18 -0
- package/dist/src/transport/filter-test.js.map +1 -0
- package/dist/src/transport/index.d.ts +15 -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 +152 -0
- package/dist/src/transport/listen-test.js.map +1 -0
- package/package.json +72 -5
- package/src/connection/index.ts +182 -0
- package/src/connection-encryption/index.ts +97 -0
- package/src/connection-encryption/utils/index.ts +24 -0
- package/src/index.ts +0 -1
- package/src/is-valid-tick.ts +0 -1
- package/src/mocks/connection-encrypter.ts +113 -0
- package/src/mocks/connection-gater.ts +18 -0
- package/src/mocks/connection-manager.ts +211 -0
- package/src/mocks/connection.ts +226 -0
- package/src/mocks/duplex.ts +10 -0
- package/src/mocks/index.ts +12 -0
- package/src/mocks/metrics.ts +162 -0
- package/src/mocks/multiaddr-connection.ts +76 -0
- package/src/mocks/muxer.ts +303 -0
- package/src/mocks/peer-discovery.ts +60 -0
- package/src/mocks/registrar.ts +88 -0
- package/src/mocks/upgrader.ts +49 -0
- package/src/peer-discovery/index.ts +90 -0
- package/src/pubsub/api.ts +114 -0
- package/src/pubsub/connection-handlers.ts +413 -0
- package/src/pubsub/emit-self.ts +99 -0
- package/src/pubsub/index.ts +34 -0
- package/src/pubsub/messages.ts +59 -0
- package/src/pubsub/multiple-nodes.ts +440 -0
- package/src/pubsub/two-nodes.ts +273 -0
- package/src/pubsub/utils.ts +29 -0
- package/src/stream-muxer/base-test.ts +196 -0
- package/src/stream-muxer/close-test.ts +442 -0
- package/src/stream-muxer/fixtures/pb/message.proto +7 -0
- package/src/stream-muxer/fixtures/pb/message.ts +87 -0
- package/src/stream-muxer/index.ts +15 -0
- package/src/stream-muxer/mega-stress-test.ts +14 -0
- package/src/stream-muxer/spawner.ts +55 -0
- package/src/stream-muxer/stress-test.ts +27 -0
- package/src/transport/dial-test.ts +124 -0
- package/src/transport/filter-test.ts +25 -0
- package/src/transport/index.ts +25 -0
- package/src/transport/listen-test.ts +191 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/* eslint max-nested-callbacks: ["error", 6] */
|
|
2
|
+
import { TopicValidatorResult } from '@libp2p/interface/pubsub'
|
|
3
|
+
import { start, stop } from '@libp2p/interface/startable'
|
|
4
|
+
import { expect } from 'aegir/chai'
|
|
5
|
+
import pDefer from 'p-defer'
|
|
6
|
+
import pWaitFor from 'p-wait-for'
|
|
7
|
+
import sinon from 'sinon'
|
|
8
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
9
|
+
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
10
|
+
import { mockNetwork } from '../mocks/index.js'
|
|
11
|
+
import { createComponents, waitForSubscriptionUpdate } from './utils.js'
|
|
12
|
+
import type { PubSubArgs, PubSubComponents } from './index.js'
|
|
13
|
+
import type { TestSetup } from '../index.js'
|
|
14
|
+
import type { Message, PubSub } from '@libp2p/interface/pubsub'
|
|
15
|
+
|
|
16
|
+
const topic = 'foo'
|
|
17
|
+
|
|
18
|
+
function shouldNotHappen (): void {
|
|
19
|
+
expect.fail()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default (common: TestSetup<PubSub, PubSubArgs>): void => {
|
|
23
|
+
describe('pubsub with two nodes', () => {
|
|
24
|
+
let psA: PubSub
|
|
25
|
+
let psB: PubSub
|
|
26
|
+
let componentsA: PubSubComponents
|
|
27
|
+
let componentsB: PubSubComponents
|
|
28
|
+
|
|
29
|
+
// Create pubsub nodes and connect them
|
|
30
|
+
beforeEach(async () => {
|
|
31
|
+
mockNetwork.reset()
|
|
32
|
+
|
|
33
|
+
componentsA = await createComponents()
|
|
34
|
+
componentsB = await createComponents()
|
|
35
|
+
|
|
36
|
+
psA = componentsA.pubsub = await common.setup({
|
|
37
|
+
components: componentsA,
|
|
38
|
+
init: {
|
|
39
|
+
emitSelf: true
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
psB = componentsB.pubsub = await common.setup({
|
|
43
|
+
components: componentsB,
|
|
44
|
+
init: {
|
|
45
|
+
emitSelf: false
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// Start pubsub and connect nodes
|
|
50
|
+
await start(...Object.values(componentsA), ...Object.values(componentsB))
|
|
51
|
+
|
|
52
|
+
expect(psA.getPeers()).to.be.empty()
|
|
53
|
+
expect(psB.getPeers()).to.be.empty()
|
|
54
|
+
|
|
55
|
+
await componentsA.connectionManager.openConnection(componentsB.peerId)
|
|
56
|
+
|
|
57
|
+
// Wait for peers to be ready in pubsub
|
|
58
|
+
await pWaitFor(() => psA.getPeers().length === 1 && psB.getPeers().length === 1)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
afterEach(async () => {
|
|
62
|
+
sinon.restore()
|
|
63
|
+
await stop(...Object.values(componentsA), ...Object.values(componentsB))
|
|
64
|
+
await common.teardown()
|
|
65
|
+
mockNetwork.reset()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('Subscribe to a topic in nodeA', async () => {
|
|
69
|
+
const defer = pDefer()
|
|
70
|
+
|
|
71
|
+
psB.addEventListener('subscription-change', (evt) => {
|
|
72
|
+
const { peerId: changedPeerId, subscriptions: changedSubs } = evt.detail
|
|
73
|
+
expect(psA.getTopics()).to.deep.equal([topic])
|
|
74
|
+
expect(psB.getPeers()).to.have.lengthOf(1)
|
|
75
|
+
expect(psB.getSubscribers(topic).map(p => p.toString())).to.deep.equal([componentsA.peerId.toString()])
|
|
76
|
+
expect(changedPeerId).to.deep.equal(psB.getPeers()[0])
|
|
77
|
+
expect(changedSubs).to.have.lengthOf(1)
|
|
78
|
+
expect(changedSubs[0].topic).to.equal(topic)
|
|
79
|
+
expect(changedSubs[0].subscribe).to.equal(true)
|
|
80
|
+
defer.resolve()
|
|
81
|
+
}, {
|
|
82
|
+
once: true
|
|
83
|
+
})
|
|
84
|
+
psA.subscribe(topic)
|
|
85
|
+
|
|
86
|
+
return defer.promise
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('Publish to a topic in nodeA', async () => {
|
|
90
|
+
const defer = pDefer()
|
|
91
|
+
|
|
92
|
+
psA.addEventListener('message', (evt) => {
|
|
93
|
+
if (evt.detail.topic === topic) {
|
|
94
|
+
const msg = evt.detail
|
|
95
|
+
expect(uint8ArrayToString(msg.data)).to.equal('hey')
|
|
96
|
+
psB.removeEventListener('message', shouldNotHappen)
|
|
97
|
+
defer.resolve()
|
|
98
|
+
}
|
|
99
|
+
}, {
|
|
100
|
+
once: true
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
psA.subscribe(topic)
|
|
104
|
+
psB.subscribe(topic)
|
|
105
|
+
|
|
106
|
+
await Promise.all([
|
|
107
|
+
waitForSubscriptionUpdate(psA, componentsB.peerId),
|
|
108
|
+
waitForSubscriptionUpdate(psB, componentsA.peerId)
|
|
109
|
+
])
|
|
110
|
+
|
|
111
|
+
await psA.publish(topic, uint8ArrayFromString('hey'))
|
|
112
|
+
|
|
113
|
+
return defer.promise
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('Publish to a topic in nodeB', async () => {
|
|
117
|
+
const defer = pDefer()
|
|
118
|
+
|
|
119
|
+
psA.addEventListener('message', (evt) => {
|
|
120
|
+
if (evt.detail.topic !== topic) {
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const msg = evt.detail
|
|
125
|
+
psA.addEventListener('message', (evt) => {
|
|
126
|
+
if (evt.detail.topic === topic) {
|
|
127
|
+
shouldNotHappen()
|
|
128
|
+
}
|
|
129
|
+
}, {
|
|
130
|
+
once: true
|
|
131
|
+
})
|
|
132
|
+
expect(uint8ArrayToString(msg.data)).to.equal('banana')
|
|
133
|
+
|
|
134
|
+
setTimeout(() => {
|
|
135
|
+
psA.removeEventListener('message')
|
|
136
|
+
psB.removeEventListener('message')
|
|
137
|
+
|
|
138
|
+
defer.resolve()
|
|
139
|
+
}, 100)
|
|
140
|
+
}, {
|
|
141
|
+
once: true
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
psB.addEventListener('message', shouldNotHappen)
|
|
145
|
+
|
|
146
|
+
psA.subscribe(topic)
|
|
147
|
+
psB.subscribe(topic)
|
|
148
|
+
|
|
149
|
+
await Promise.all([
|
|
150
|
+
waitForSubscriptionUpdate(psA, componentsB.peerId),
|
|
151
|
+
waitForSubscriptionUpdate(psB, componentsA.peerId)
|
|
152
|
+
])
|
|
153
|
+
|
|
154
|
+
await psB.publish(topic, uint8ArrayFromString('banana'))
|
|
155
|
+
|
|
156
|
+
return defer.promise
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('validate topic message', async () => {
|
|
160
|
+
const defer = pDefer()
|
|
161
|
+
|
|
162
|
+
psA.subscribe(topic)
|
|
163
|
+
|
|
164
|
+
psB.topicValidators.set(topic, (peer, message) => {
|
|
165
|
+
if (!peer.equals(componentsA.peerId)) {
|
|
166
|
+
defer.reject(new Error('Invalid peer id in topic validator fn'))
|
|
167
|
+
return TopicValidatorResult.Reject
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (uint8ArrayToString(message.data) !== 'hey') {
|
|
171
|
+
defer.reject(new Error('Invalid message in topic validator fn'))
|
|
172
|
+
return TopicValidatorResult.Reject
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
defer.resolve()
|
|
176
|
+
return TopicValidatorResult.Accept
|
|
177
|
+
})
|
|
178
|
+
psB.subscribe(topic)
|
|
179
|
+
|
|
180
|
+
await Promise.all([
|
|
181
|
+
waitForSubscriptionUpdate(psA, componentsB.peerId),
|
|
182
|
+
waitForSubscriptionUpdate(psB, componentsA.peerId)
|
|
183
|
+
])
|
|
184
|
+
|
|
185
|
+
await psA.publish(topic, uint8ArrayFromString('hey'))
|
|
186
|
+
|
|
187
|
+
return defer.promise
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
it('Publish 10 msg to a topic in nodeB', async () => {
|
|
191
|
+
const defer = pDefer()
|
|
192
|
+
let counter = 0
|
|
193
|
+
|
|
194
|
+
psB.addEventListener('message', shouldNotHappen)
|
|
195
|
+
psA.addEventListener('message', receivedMsg)
|
|
196
|
+
|
|
197
|
+
function receivedMsg (evt: CustomEvent<Message>): void {
|
|
198
|
+
const msg = evt.detail
|
|
199
|
+
if (msg.type === 'unsigned') {
|
|
200
|
+
expect(uint8ArrayToString(msg.data)).to.equal('banana')
|
|
201
|
+
expect(msg.topic).to.be.equal(topic)
|
|
202
|
+
} else {
|
|
203
|
+
expect(uint8ArrayToString(msg.data)).to.equal('banana')
|
|
204
|
+
expect(msg.from.toString()).to.equal(componentsB.peerId.toString())
|
|
205
|
+
expect(msg.sequenceNumber).to.be.a('BigInt')
|
|
206
|
+
expect(msg.topic).to.be.equal(topic)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (++counter === 10) {
|
|
210
|
+
psA.removeEventListener('message', receivedMsg)
|
|
211
|
+
psB.removeEventListener('message', shouldNotHappen)
|
|
212
|
+
|
|
213
|
+
defer.resolve()
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
psA.subscribe(topic)
|
|
218
|
+
psB.subscribe(topic)
|
|
219
|
+
|
|
220
|
+
await Promise.all([
|
|
221
|
+
waitForSubscriptionUpdate(psA, componentsB.peerId),
|
|
222
|
+
waitForSubscriptionUpdate(psB, componentsA.peerId)
|
|
223
|
+
])
|
|
224
|
+
|
|
225
|
+
await Promise.all(
|
|
226
|
+
Array.from({ length: 10 }, async (_, i) => {
|
|
227
|
+
await psB.publish(topic, uint8ArrayFromString('banana'))
|
|
228
|
+
})
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
return defer.promise
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
it('Unsubscribe from topic in nodeA', async () => {
|
|
235
|
+
const defer = pDefer()
|
|
236
|
+
let callCount = 0
|
|
237
|
+
|
|
238
|
+
psB.addEventListener('subscription-change', (evt) => {
|
|
239
|
+
callCount++
|
|
240
|
+
|
|
241
|
+
if (callCount === 1) {
|
|
242
|
+
// notice subscribe
|
|
243
|
+
const { peerId: changedPeerId, subscriptions: changedSubs } = evt.detail
|
|
244
|
+
expect(psB.getPeers()).to.have.lengthOf(1)
|
|
245
|
+
expect(psB.getTopics()).to.be.empty()
|
|
246
|
+
expect(changedPeerId).to.deep.equal(psB.getPeers()[0])
|
|
247
|
+
expect(changedSubs).to.have.lengthOf(1)
|
|
248
|
+
expect(changedSubs[0].topic).to.equal(topic)
|
|
249
|
+
expect(changedSubs[0].subscribe).to.equal(true)
|
|
250
|
+
} else {
|
|
251
|
+
// notice unsubscribe
|
|
252
|
+
const { peerId: changedPeerId, subscriptions: changedSubs } = evt.detail
|
|
253
|
+
expect(psB.getPeers()).to.have.lengthOf(1)
|
|
254
|
+
expect(psB.getTopics()).to.be.empty()
|
|
255
|
+
expect(changedPeerId).to.deep.equal(psB.getPeers()[0])
|
|
256
|
+
expect(changedSubs).to.have.lengthOf(1)
|
|
257
|
+
expect(changedSubs[0].topic).to.equal(topic)
|
|
258
|
+
expect(changedSubs[0].subscribe).to.equal(false)
|
|
259
|
+
|
|
260
|
+
defer.resolve()
|
|
261
|
+
}
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
psA.subscribe(topic)
|
|
265
|
+
expect(psA.getTopics()).to.not.be.empty()
|
|
266
|
+
|
|
267
|
+
psA.unsubscribe(topic)
|
|
268
|
+
expect(psA.getTopics()).to.be.empty()
|
|
269
|
+
|
|
270
|
+
return defer.promise
|
|
271
|
+
})
|
|
272
|
+
})
|
|
273
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { EventEmitter } from '@libp2p/interface/events'
|
|
2
|
+
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
|
|
3
|
+
import { pEvent } from 'p-event'
|
|
4
|
+
import pWaitFor from 'p-wait-for'
|
|
5
|
+
import { mockConnectionManager, mockRegistrar, mockNetwork } from '../mocks/index.js'
|
|
6
|
+
import type { MockNetworkComponents } from '../mocks/index.js'
|
|
7
|
+
import type { PeerId } from '@libp2p/interface/peer-id'
|
|
8
|
+
import type { PubSub, SubscriptionChangeData } from '@libp2p/interface/pubsub'
|
|
9
|
+
|
|
10
|
+
export async function waitForSubscriptionUpdate (a: PubSub, b: PeerId): Promise<void> {
|
|
11
|
+
await pWaitFor(async () => {
|
|
12
|
+
const event = await pEvent<'subscription-change', CustomEvent<SubscriptionChangeData>>(a, 'subscription-change')
|
|
13
|
+
|
|
14
|
+
return event.detail.peerId.equals(b)
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function createComponents (): Promise<MockNetworkComponents> {
|
|
19
|
+
const components: any = {
|
|
20
|
+
peerId: await createEd25519PeerId(),
|
|
21
|
+
registrar: mockRegistrar(),
|
|
22
|
+
events: new EventEmitter()
|
|
23
|
+
}
|
|
24
|
+
components.connectionManager = mockConnectionManager(components)
|
|
25
|
+
|
|
26
|
+
mockNetwork.addNode(components)
|
|
27
|
+
|
|
28
|
+
return components
|
|
29
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { expect } from 'aegir/chai'
|
|
2
|
+
import all from 'it-all'
|
|
3
|
+
import drain from 'it-drain'
|
|
4
|
+
import map from 'it-map'
|
|
5
|
+
import { duplexPair } from 'it-pair/duplex'
|
|
6
|
+
import { pipe } from 'it-pipe'
|
|
7
|
+
import defer from 'p-defer'
|
|
8
|
+
import { Uint8ArrayList } from 'uint8arraylist'
|
|
9
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
10
|
+
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
11
|
+
import { isValidTick } from '../is-valid-tick.js'
|
|
12
|
+
import type { TestSetup } from '../index.js'
|
|
13
|
+
import type { Stream } from '@libp2p/interface/connection'
|
|
14
|
+
import type { StreamMuxerFactory } from '@libp2p/interface/stream-muxer'
|
|
15
|
+
import type { Source, Duplex } from 'it-stream-types'
|
|
16
|
+
import type { DeferredPromise } from 'p-defer'
|
|
17
|
+
|
|
18
|
+
async function drainAndClose (stream: Duplex<any>): Promise<void> {
|
|
19
|
+
await pipe([], stream, drain)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
23
|
+
describe('base', () => {
|
|
24
|
+
it('Open a stream from the dialer', async () => {
|
|
25
|
+
const p = duplexPair<Uint8Array>()
|
|
26
|
+
const dialerFactory = await common.setup()
|
|
27
|
+
const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' })
|
|
28
|
+
const onStreamPromise: DeferredPromise<Stream> = defer()
|
|
29
|
+
const onStreamEndPromise: DeferredPromise<Stream> = defer()
|
|
30
|
+
|
|
31
|
+
const listenerFactory = await common.setup()
|
|
32
|
+
const listener = listenerFactory.createStreamMuxer({
|
|
33
|
+
direction: 'inbound',
|
|
34
|
+
onIncomingStream: (stream) => {
|
|
35
|
+
onStreamPromise.resolve(stream)
|
|
36
|
+
},
|
|
37
|
+
onStreamEnd: (stream) => {
|
|
38
|
+
onStreamEndPromise.resolve(stream)
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
void pipe(p[0], dialer, p[0])
|
|
43
|
+
void pipe(p[1], listener, p[1])
|
|
44
|
+
|
|
45
|
+
const conn = await dialer.newStream()
|
|
46
|
+
expect(dialer.streams).to.include(conn)
|
|
47
|
+
expect(isValidTick(conn.timeline.open)).to.equal(true)
|
|
48
|
+
|
|
49
|
+
void drainAndClose(conn)
|
|
50
|
+
|
|
51
|
+
const stream = await onStreamPromise.promise
|
|
52
|
+
expect(isValidTick(stream.timeline.open)).to.equal(true)
|
|
53
|
+
// Make sure the stream is being tracked
|
|
54
|
+
expect(listener.streams).to.include(stream)
|
|
55
|
+
|
|
56
|
+
void drainAndClose(stream)
|
|
57
|
+
|
|
58
|
+
// Make sure stream is closed properly
|
|
59
|
+
const endedStream = await onStreamEndPromise.promise
|
|
60
|
+
expect(listener.streams).to.not.include(endedStream)
|
|
61
|
+
|
|
62
|
+
if (endedStream.timeline.close == null) {
|
|
63
|
+
throw new Error('timeline had no close time')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Make sure the stream is removed from tracking
|
|
67
|
+
expect(isValidTick(endedStream.timeline.close)).to.equal(true)
|
|
68
|
+
|
|
69
|
+
await drainAndClose(dialer)
|
|
70
|
+
await drainAndClose(listener)
|
|
71
|
+
|
|
72
|
+
// ensure we have no streams left
|
|
73
|
+
expect(dialer.streams).to.have.length(0)
|
|
74
|
+
expect(listener.streams).to.have.length(0)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('Open a stream from the listener', async () => {
|
|
78
|
+
const p = duplexPair<Uint8Array>()
|
|
79
|
+
const onStreamPromise: DeferredPromise<Stream> = defer()
|
|
80
|
+
const dialerFactory = await common.setup()
|
|
81
|
+
const dialer = dialerFactory.createStreamMuxer({
|
|
82
|
+
direction: 'outbound',
|
|
83
|
+
onIncomingStream: (stream: Stream) => {
|
|
84
|
+
onStreamPromise.resolve(stream)
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
const listenerFactory = await common.setup()
|
|
89
|
+
const listener = listenerFactory.createStreamMuxer({ direction: 'inbound' })
|
|
90
|
+
|
|
91
|
+
void pipe(p[0], dialer, p[0])
|
|
92
|
+
void pipe(p[1], listener, p[1])
|
|
93
|
+
|
|
94
|
+
const conn = await listener.newStream()
|
|
95
|
+
|
|
96
|
+
void drainAndClose(conn)
|
|
97
|
+
|
|
98
|
+
const stream = await onStreamPromise.promise
|
|
99
|
+
expect(isValidTick(stream.timeline.open)).to.equal(true)
|
|
100
|
+
expect(listener.streams).to.include(conn)
|
|
101
|
+
expect(isValidTick(conn.timeline.open)).to.equal(true)
|
|
102
|
+
void drainAndClose(stream)
|
|
103
|
+
|
|
104
|
+
await drainAndClose(dialer)
|
|
105
|
+
await drainAndClose(listener)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('Open a stream on both sides', async () => {
|
|
109
|
+
const p = duplexPair<Uint8Array>()
|
|
110
|
+
const onDialerStreamPromise: DeferredPromise<Stream> = defer()
|
|
111
|
+
const onListenerStreamPromise: DeferredPromise<Stream> = defer()
|
|
112
|
+
const dialerFactory = await common.setup()
|
|
113
|
+
const dialer = dialerFactory.createStreamMuxer({
|
|
114
|
+
direction: 'outbound',
|
|
115
|
+
onIncomingStream: (stream) => {
|
|
116
|
+
onDialerStreamPromise.resolve(stream)
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
const listenerFactory = await common.setup()
|
|
121
|
+
const listener = listenerFactory.createStreamMuxer({
|
|
122
|
+
direction: 'inbound',
|
|
123
|
+
onIncomingStream: (stream) => {
|
|
124
|
+
onListenerStreamPromise.resolve(stream)
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
void pipe(p[0], dialer, p[0])
|
|
129
|
+
void pipe(p[1], listener, p[1])
|
|
130
|
+
|
|
131
|
+
const dialerInitiatorStream = await dialer.newStream()
|
|
132
|
+
const listenerInitiatorStream = await listener.newStream()
|
|
133
|
+
|
|
134
|
+
await Promise.all([
|
|
135
|
+
drainAndClose(dialerInitiatorStream),
|
|
136
|
+
drainAndClose(listenerInitiatorStream),
|
|
137
|
+
onDialerStreamPromise.promise.then(async stream => { await drainAndClose(stream) }),
|
|
138
|
+
onListenerStreamPromise.promise.then(async stream => { await drainAndClose(stream) })
|
|
139
|
+
])
|
|
140
|
+
|
|
141
|
+
await Promise.all([
|
|
142
|
+
drainAndClose(dialer),
|
|
143
|
+
drainAndClose(listener)
|
|
144
|
+
])
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it('Open a stream on one side, write, open a stream on the other side', async () => {
|
|
148
|
+
const toString = (source: Source<Uint8ArrayList>): AsyncGenerator<string> => map(source, (u) => uint8ArrayToString(u.subarray()))
|
|
149
|
+
const p = duplexPair<Uint8Array>()
|
|
150
|
+
const onDialerStreamPromise: DeferredPromise<Stream> = defer()
|
|
151
|
+
const onListenerStreamPromise: DeferredPromise<Stream> = defer()
|
|
152
|
+
const dialerFactory = await common.setup()
|
|
153
|
+
const dialer = dialerFactory.createStreamMuxer({
|
|
154
|
+
direction: 'outbound',
|
|
155
|
+
onIncomingStream: (stream) => {
|
|
156
|
+
onDialerStreamPromise.resolve(stream)
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
const listenerFactory = await common.setup()
|
|
160
|
+
const listener = listenerFactory.createStreamMuxer({
|
|
161
|
+
direction: 'inbound',
|
|
162
|
+
onIncomingStream: (stream) => {
|
|
163
|
+
onListenerStreamPromise.resolve(stream)
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
void pipe(p[0], dialer, p[0])
|
|
168
|
+
void pipe(p[1], listener, p[1])
|
|
169
|
+
|
|
170
|
+
const dialerConn = await dialer.newStream()
|
|
171
|
+
const listenerConn = await listener.newStream()
|
|
172
|
+
|
|
173
|
+
void pipe([new Uint8ArrayList(uint8ArrayFromString('hey'))], dialerConn)
|
|
174
|
+
void pipe([new Uint8ArrayList(uint8ArrayFromString('hello'))], listenerConn)
|
|
175
|
+
|
|
176
|
+
const [
|
|
177
|
+
dialerStream,
|
|
178
|
+
listenerStream
|
|
179
|
+
] = await Promise.all([
|
|
180
|
+
onDialerStreamPromise.promise,
|
|
181
|
+
onListenerStreamPromise.promise
|
|
182
|
+
])
|
|
183
|
+
|
|
184
|
+
const [
|
|
185
|
+
listenerChunks,
|
|
186
|
+
dialerChunks
|
|
187
|
+
] = await Promise.all([
|
|
188
|
+
pipe(listenerStream, toString, async (source) => all(source)),
|
|
189
|
+
pipe(dialerStream, toString, async (source) => all(source))
|
|
190
|
+
])
|
|
191
|
+
|
|
192
|
+
expect(listenerChunks).to.be.eql(['hey'])
|
|
193
|
+
expect(dialerChunks).to.be.eql(['hello'])
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
}
|