@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.
Files changed (177) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +25 -0
  3. package/dist/src/connection/connection.d.ts +5 -0
  4. package/dist/src/connection/connection.d.ts.map +1 -0
  5. package/dist/src/connection/connection.js +148 -0
  6. package/dist/src/connection/connection.js.map +1 -0
  7. package/dist/src/connection/index.d.ts +5 -0
  8. package/dist/src/connection/index.d.ts.map +1 -0
  9. package/dist/src/connection/index.js +5 -0
  10. package/dist/src/connection/index.js.map +1 -0
  11. package/dist/src/crypto/index.d.ts +5 -0
  12. package/dist/src/crypto/index.d.ts.map +1 -0
  13. package/dist/src/crypto/index.js +78 -0
  14. package/dist/src/crypto/index.js.map +1 -0
  15. package/dist/src/index.d.ts +5 -0
  16. package/dist/src/index.d.ts.map +1 -0
  17. package/dist/src/index.js +2 -0
  18. package/dist/src/index.js.map +1 -0
  19. package/dist/src/peer-discovery/index.d.ts +6 -0
  20. package/dist/src/peer-discovery/index.d.ts.map +1 -0
  21. package/dist/src/peer-discovery/index.js +63 -0
  22. package/dist/src/peer-discovery/index.js.map +1 -0
  23. package/dist/src/pubsub/api.d.ts +6 -0
  24. package/dist/src/pubsub/api.d.ts.map +1 -0
  25. package/dist/src/pubsub/api.js +65 -0
  26. package/dist/src/pubsub/api.js.map +1 -0
  27. package/dist/src/pubsub/connection-handlers.d.ts +6 -0
  28. package/dist/src/pubsub/connection-handlers.d.ts.map +1 -0
  29. package/dist/src/pubsub/connection-handlers.js +279 -0
  30. package/dist/src/pubsub/connection-handlers.js.map +1 -0
  31. package/dist/src/pubsub/emit-self.d.ts +6 -0
  32. package/dist/src/pubsub/emit-self.d.ts.map +1 -0
  33. package/dist/src/pubsub/emit-self.js +51 -0
  34. package/dist/src/pubsub/emit-self.js.map +1 -0
  35. package/dist/src/pubsub/index.d.ts +6 -0
  36. package/dist/src/pubsub/index.d.ts.map +1 -0
  37. package/dist/src/pubsub/index.js +17 -0
  38. package/dist/src/pubsub/index.js.map +1 -0
  39. package/dist/src/pubsub/messages.d.ts +6 -0
  40. package/dist/src/pubsub/messages.d.ts.map +1 -0
  41. package/dist/src/pubsub/messages.js +93 -0
  42. package/dist/src/pubsub/messages.js.map +1 -0
  43. package/dist/src/pubsub/multiple-nodes.d.ts +6 -0
  44. package/dist/src/pubsub/multiple-nodes.d.ts.map +1 -0
  45. package/dist/src/pubsub/multiple-nodes.js +283 -0
  46. package/dist/src/pubsub/multiple-nodes.js.map +1 -0
  47. package/dist/src/pubsub/two-nodes.d.ts +6 -0
  48. package/dist/src/pubsub/two-nodes.d.ts.map +1 -0
  49. package/dist/src/pubsub/two-nodes.js +127 -0
  50. package/dist/src/pubsub/two-nodes.js.map +1 -0
  51. package/dist/src/pubsub/utils.d.ts +3 -0
  52. package/dist/src/pubsub/utils.d.ts.map +1 -0
  53. package/dist/src/pubsub/utils.js +11 -0
  54. package/dist/src/pubsub/utils.js.map +1 -0
  55. package/dist/src/record/index.d.ts +5 -0
  56. package/dist/src/record/index.d.ts.map +1 -0
  57. package/dist/src/record/index.js +25 -0
  58. package/dist/src/record/index.js.map +1 -0
  59. package/dist/src/stream-muxer/base-test.d.ts +5 -0
  60. package/dist/src/stream-muxer/base-test.d.ts.map +1 -0
  61. package/dist/src/stream-muxer/base-test.js +123 -0
  62. package/dist/src/stream-muxer/base-test.js.map +1 -0
  63. package/dist/src/stream-muxer/close-test.d.ts +5 -0
  64. package/dist/src/stream-muxer/close-test.d.ts.map +1 -0
  65. package/dist/src/stream-muxer/close-test.js +103 -0
  66. package/dist/src/stream-muxer/close-test.js.map +1 -0
  67. package/dist/src/stream-muxer/index.d.ts +5 -0
  68. package/dist/src/stream-muxer/index.d.ts.map +1 -0
  69. package/dist/src/stream-muxer/index.js +13 -0
  70. package/dist/src/stream-muxer/index.js.map +1 -0
  71. package/dist/src/stream-muxer/mega-stress-test.d.ts +5 -0
  72. package/dist/src/stream-muxer/mega-stress-test.d.ts.map +1 -0
  73. package/dist/src/stream-muxer/mega-stress-test.js +8 -0
  74. package/dist/src/stream-muxer/mega-stress-test.js.map +1 -0
  75. package/dist/src/stream-muxer/spawner.d.ts +4 -0
  76. package/dist/src/stream-muxer/spawner.d.ts.map +1 -0
  77. package/dist/src/stream-muxer/spawner.js +32 -0
  78. package/dist/src/stream-muxer/spawner.js.map +1 -0
  79. package/dist/src/stream-muxer/stress-test.d.ts +5 -0
  80. package/dist/src/stream-muxer/stress-test.d.ts.map +1 -0
  81. package/dist/src/stream-muxer/stress-test.js +21 -0
  82. package/dist/src/stream-muxer/stress-test.js.map +1 -0
  83. package/dist/src/topology/multicodec-topology.d.ts +5 -0
  84. package/dist/src/topology/multicodec-topology.d.ts.map +1 -0
  85. package/dist/src/topology/multicodec-topology.js +109 -0
  86. package/dist/src/topology/multicodec-topology.js.map +1 -0
  87. package/dist/src/topology/topology.d.ts +5 -0
  88. package/dist/src/topology/topology.d.ts.map +1 -0
  89. package/dist/src/topology/topology.js +29 -0
  90. package/dist/src/topology/topology.js.map +1 -0
  91. package/dist/src/transport/dial-test.d.ts +5 -0
  92. package/dist/src/transport/dial-test.d.ts.map +1 -0
  93. package/dist/src/transport/dial-test.js +78 -0
  94. package/dist/src/transport/dial-test.js.map +1 -0
  95. package/dist/src/transport/filter-test.d.ts +5 -0
  96. package/dist/src/transport/filter-test.d.ts.map +1 -0
  97. package/dist/src/transport/filter-test.js +19 -0
  98. package/dist/src/transport/filter-test.js.map +1 -0
  99. package/dist/src/transport/index.d.ts +18 -0
  100. package/dist/src/transport/index.d.ts.map +1 -0
  101. package/dist/src/transport/index.js +11 -0
  102. package/dist/src/transport/index.js.map +1 -0
  103. package/dist/src/transport/listen-test.d.ts +5 -0
  104. package/dist/src/transport/listen-test.d.ts.map +1 -0
  105. package/dist/src/transport/listen-test.js +116 -0
  106. package/dist/src/transport/listen-test.js.map +1 -0
  107. package/dist/src/transport/utils/index.d.ts +8 -0
  108. package/dist/src/transport/utils/index.d.ts.map +1 -0
  109. package/dist/src/transport/utils/index.js +104 -0
  110. package/dist/src/transport/utils/index.js.map +1 -0
  111. package/dist/src/utils/peers.d.ts +7 -0
  112. package/dist/src/utils/peers.d.ts.map +1 -0
  113. package/dist/src/utils/peers.js +26 -0
  114. package/dist/src/utils/peers.js.map +1 -0
  115. package/dist/test/connection/index.spec.d.ts +2 -0
  116. package/dist/test/connection/index.spec.d.ts.map +1 -0
  117. package/dist/test/connection/index.spec.js +71 -0
  118. package/dist/test/connection/index.spec.js.map +1 -0
  119. package/dist/test/crypto/index.spec.d.ts +2 -0
  120. package/dist/test/crypto/index.spec.d.ts.map +1 -0
  121. package/dist/test/crypto/index.spec.js +11 -0
  122. package/dist/test/crypto/index.spec.js.map +1 -0
  123. package/dist/test/crypto/mock-crypto.d.ts +4 -0
  124. package/dist/test/crypto/mock-crypto.d.ts.map +1 -0
  125. package/dist/test/crypto/mock-crypto.js +93 -0
  126. package/dist/test/crypto/mock-crypto.js.map +1 -0
  127. package/dist/test/peer-discovery/index.spec.d.ts +2 -0
  128. package/dist/test/peer-discovery/index.spec.d.ts.map +1 -0
  129. package/dist/test/peer-discovery/index.spec.js +18 -0
  130. package/dist/test/peer-discovery/index.spec.js.map +1 -0
  131. package/dist/test/peer-discovery/mock-discovery.d.ts +20 -0
  132. package/dist/test/peer-discovery/mock-discovery.d.ts.map +1 -0
  133. package/dist/test/peer-discovery/mock-discovery.js +39 -0
  134. package/dist/test/peer-discovery/mock-discovery.js.map +1 -0
  135. package/dist/test/topology/mock-peer-store.d.ts +12 -0
  136. package/dist/test/topology/mock-peer-store.d.ts.map +1 -0
  137. package/dist/test/topology/mock-peer-store.js +18 -0
  138. package/dist/test/topology/mock-peer-store.js.map +1 -0
  139. package/dist/test/topology/multicodec-topology.spec.d.ts +2 -0
  140. package/dist/test/topology/multicodec-topology.spec.d.ts.map +1 -0
  141. package/dist/test/topology/multicodec-topology.spec.js +45 -0
  142. package/dist/test/topology/multicodec-topology.spec.js.map +1 -0
  143. package/dist/test/topology/topology.spec.d.ts +2 -0
  144. package/dist/test/topology/topology.spec.d.ts.map +1 -0
  145. package/dist/test/topology/topology.spec.js +21 -0
  146. package/dist/test/topology/topology.spec.js.map +1 -0
  147. package/dist/tsconfig.tsbuildinfo +1 -0
  148. package/package.json +120 -4
  149. package/src/connection/README.md +256 -0
  150. package/src/connection/connection.ts +178 -0
  151. package/src/connection/index.ts +7 -0
  152. package/src/crypto/index.ts +104 -0
  153. package/src/index.ts +5 -0
  154. package/src/peer-discovery/index.ts +87 -0
  155. package/src/pubsub/api.ts +89 -0
  156. package/src/pubsub/connection-handlers.ts +356 -0
  157. package/src/pubsub/emit-self.ts +67 -0
  158. package/src/pubsub/index.ts +20 -0
  159. package/src/pubsub/messages.ts +111 -0
  160. package/src/pubsub/multiple-nodes.ts +353 -0
  161. package/src/pubsub/two-nodes.ts +175 -0
  162. package/src/pubsub/utils.ts +13 -0
  163. package/src/record/index.ts +32 -0
  164. package/src/stream-muxer/base-test.ts +154 -0
  165. package/src/stream-muxer/close-test.ts +124 -0
  166. package/src/stream-muxer/index.ts +15 -0
  167. package/src/stream-muxer/mega-stress-test.ts +11 -0
  168. package/src/stream-muxer/spawner.ts +52 -0
  169. package/src/stream-muxer/stress-test.ts +24 -0
  170. package/src/topology/multicodec-topology.ts +136 -0
  171. package/src/topology/topology.ts +38 -0
  172. package/src/transport/dial-test.ts +98 -0
  173. package/src/transport/filter-test.ts +26 -0
  174. package/src/transport/index.ts +29 -0
  175. package/src/transport/listen-test.ts +152 -0
  176. package/src/transport/utils/index.ts +123 -0
  177. package/src/utils/peers.ts +25 -0
@@ -0,0 +1,353 @@
1
+ /* eslint max-nested-callbacks: ["error", 6] */
2
+ import { expect } from 'aegir/utils/chai.js'
3
+ import sinon from 'sinon'
4
+ import delay from 'delay'
5
+ import pDefer from 'p-defer'
6
+ import pWaitFor from 'p-wait-for'
7
+ import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
8
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
9
+ import { expectSet } from './utils.js'
10
+ import type { TestSetup } from '../index.js'
11
+ import type { PubSub, Message } from '@libp2p/interfaces/pubsub'
12
+ import type { Startable } from '@libp2p/interfaces'
13
+
14
+ export default (common: TestSetup<PubSub & Startable>) => {
15
+ describe('pubsub with multiple nodes', function () {
16
+ describe('every peer subscribes to the topic', () => {
17
+ describe('line', () => {
18
+ // line
19
+ // ◉────◉────◉
20
+ // a b c
21
+ let psA: PubSub & Startable
22
+ let psB: PubSub & Startable
23
+ let psC: PubSub & Startable
24
+
25
+ // Create and start pubsub nodes
26
+ beforeEach(async () => {
27
+ psA = await common.setup()
28
+ psB = await common.setup()
29
+ psC = await common.setup()
30
+
31
+ // Start pubsub modes
32
+ ;[psA, psB, psC].map((p) => p.start())
33
+ })
34
+
35
+ // Connect nodes
36
+ beforeEach(async () => {
37
+ // @ts-expect-error protected field
38
+ await psA._libp2p.dial(psB.peerId)
39
+ // @ts-expect-error protected field
40
+ await psB._libp2p.dial(psC.peerId)
41
+
42
+ // Wait for peers to be ready in pubsub
43
+ await pWaitFor(() =>
44
+ psA.peers.size === 1 &&
45
+ psC.peers.size === 1 &&
46
+ psA.peers.size === 1
47
+ )
48
+ })
49
+
50
+ afterEach(async () => {
51
+ sinon.restore()
52
+
53
+ ;[psA, psB, psC].map((p) => p.stop())
54
+ await common.teardown()
55
+ })
56
+
57
+ it('subscribe to the topic on node a', async () => {
58
+ const topic = 'Z'
59
+
60
+ psA.subscribe(topic)
61
+ expectSet(psA.subscriptions, [topic])
62
+
63
+ await new Promise((resolve) => psB.once('pubsub:subscription-change', resolve))
64
+ expect(psB.peers.size).to.equal(2)
65
+
66
+ const aPeerId = psA.peerId.toString()
67
+ expectSet(psB.topics.get(topic), [aPeerId])
68
+
69
+ expect(psC.peers.size).to.equal(1)
70
+ expect(psC.topics.get(topic)).to.eql(undefined)
71
+ })
72
+
73
+ it('subscribe to the topic on node b', async () => {
74
+ const topic = 'Z'
75
+ psB.subscribe(topic)
76
+ expectSet(psB.subscriptions, [topic])
77
+
78
+ await Promise.all([
79
+ new Promise((resolve) => psA.once('pubsub:subscription-change', resolve)),
80
+ new Promise((resolve) => psC.once('pubsub:subscription-change', resolve))
81
+ ])
82
+
83
+ expect(psA.peers.size).to.equal(1)
84
+ expectSet(psA.topics.get(topic), [psB.peerId.toString()])
85
+
86
+ expect(psC.peers.size).to.equal(1)
87
+ expectSet(psC.topics.get(topic), [psB.peerId.toString()])
88
+ })
89
+
90
+ it('subscribe to the topic on node c', async () => {
91
+ const topic = 'Z'
92
+ const defer = pDefer()
93
+
94
+ psC.subscribe(topic)
95
+ expectSet(psC.subscriptions, [topic])
96
+
97
+ psB.once('pubsub:subscription-change', () => {
98
+ expect(psA.peers.size).to.equal(1)
99
+ expect(psB.peers.size).to.equal(2)
100
+ expectSet(psB.topics.get(topic), [psC.peerId.toString()])
101
+
102
+ defer.resolve()
103
+ })
104
+
105
+ return await defer.promise
106
+ })
107
+
108
+ it('publish on node a', async () => {
109
+ const topic = 'Z'
110
+ const defer = pDefer()
111
+
112
+ psA.subscribe(topic)
113
+ psB.subscribe(topic)
114
+ psC.subscribe(topic)
115
+
116
+ // await subscription change
117
+ await Promise.all([
118
+ new Promise(resolve => psA.once('pubsub:subscription-change', () => resolve(null))),
119
+ new Promise(resolve => psB.once('pubsub:subscription-change', () => resolve(null))),
120
+ new Promise(resolve => psC.once('pubsub:subscription-change', () => resolve(null)))
121
+ ])
122
+
123
+ // await a cycle
124
+ await delay(1000)
125
+
126
+ let counter = 0
127
+
128
+ psA.on(topic, incMsg)
129
+ psB.on(topic, incMsg)
130
+ psC.on(topic, incMsg)
131
+
132
+ void psA.publish(topic, uint8ArrayFromString('hey'))
133
+
134
+ function incMsg (msg: Message) {
135
+ expect(uint8ArrayToString(msg.data)).to.equal('hey')
136
+ check()
137
+ }
138
+
139
+ function check () {
140
+ if (++counter === 3) {
141
+ psA.removeListener(topic, incMsg)
142
+ psB.removeListener(topic, incMsg)
143
+ psC.removeListener(topic, incMsg)
144
+ defer.resolve()
145
+ }
146
+ }
147
+
148
+ return await defer.promise
149
+ })
150
+
151
+ // since the topology is the same, just the publish
152
+ // gets sent by other peer, we reused the same peers
153
+ describe('1 level tree', () => {
154
+ // 1 level tree
155
+ // ┌◉┐
156
+ // │b│
157
+ // ◉─┘ └─◉
158
+ // a c
159
+
160
+ it('publish on node b', async () => {
161
+ const topic = 'Z'
162
+ const defer = pDefer()
163
+ let counter = 0
164
+
165
+ psA.subscribe(topic)
166
+ psB.subscribe(topic)
167
+ psC.subscribe(topic)
168
+
169
+ // await subscription change
170
+ await Promise.all([
171
+ new Promise(resolve => psA.once('pubsub:subscription-change', () => resolve(null))),
172
+ new Promise(resolve => psB.once('pubsub:subscription-change', () => resolve(null))),
173
+ new Promise(resolve => psC.once('pubsub:subscription-change', () => resolve(null)))
174
+ ])
175
+
176
+ psA.on(topic, incMsg)
177
+ psB.on(topic, incMsg)
178
+ psC.on(topic, incMsg)
179
+
180
+ // await a cycle
181
+ await delay(1000)
182
+
183
+ void psB.publish(topic, uint8ArrayFromString('hey'))
184
+
185
+ function incMsg (msg: Message) {
186
+ expect(uint8ArrayToString(msg.data)).to.equal('hey')
187
+ check()
188
+ }
189
+
190
+ function check () {
191
+ if (++counter === 3) {
192
+ psA.removeListener(topic, incMsg)
193
+ psB.removeListener(topic, incMsg)
194
+ psC.removeListener(topic, incMsg)
195
+ defer.resolve()
196
+ }
197
+ }
198
+
199
+ return await defer.promise
200
+ })
201
+ })
202
+ })
203
+
204
+ describe('2 level tree', () => {
205
+ // 2 levels tree
206
+ // ┌◉┐
207
+ // │c│
208
+ // ┌◉─┘ └─◉┐
209
+ // │b d│
210
+ // ◉─┘ └─◉
211
+ // a
212
+ let psA: PubSub & Startable
213
+ let psB: PubSub & Startable
214
+ let psC: PubSub & Startable
215
+ let psD: PubSub & Startable
216
+ let psE: PubSub & Startable
217
+
218
+ // Create and start pubsub nodes
219
+ beforeEach(async () => {
220
+ psA = await common.setup()
221
+ psB = await common.setup()
222
+ psC = await common.setup()
223
+ psD = await common.setup()
224
+ psE = await common.setup()
225
+
226
+ // Start pubsub nodes
227
+ ;[psA, psB, psC, psD, psE].map((p) => p.start())
228
+ })
229
+
230
+ // connect nodes
231
+ beforeEach(async () => {
232
+ // @ts-expect-error protected field
233
+ await psA._libp2p.dial(psB.peerId)
234
+ // @ts-expect-error protected field
235
+ await psB._libp2p.dial(psC.peerId)
236
+ // @ts-expect-error protected field
237
+ await psC._libp2p.dial(psD.peerId)
238
+ // @ts-expect-error protected field
239
+ await psD._libp2p.dial(psE.peerId)
240
+
241
+ // Wait for peers to be ready in pubsub
242
+ await pWaitFor(() =>
243
+ psA.peers.size === 1 &&
244
+ psB.peers.size === 2 &&
245
+ psC.peers.size === 2 &&
246
+ psD.peers.size === 2 &&
247
+ psE.peers.size === 1
248
+ )
249
+ })
250
+
251
+ afterEach(async () => {
252
+ [psA, psB, psC, psD, psE].map((p) => p.stop())
253
+ await common.teardown()
254
+ })
255
+
256
+ it('subscribes', () => {
257
+ psA.subscribe('Z')
258
+ expectSet(psA.subscriptions, ['Z'])
259
+ psB.subscribe('Z')
260
+ expectSet(psB.subscriptions, ['Z'])
261
+ psC.subscribe('Z')
262
+ expectSet(psC.subscriptions, ['Z'])
263
+ psD.subscribe('Z')
264
+ expectSet(psD.subscriptions, ['Z'])
265
+ psE.subscribe('Z')
266
+ expectSet(psE.subscriptions, ['Z'])
267
+ })
268
+
269
+ it('publishes from c', async function () {
270
+ const defer = pDefer()
271
+ let counter = 0
272
+
273
+ psA.subscribe('Z')
274
+ psA.on('Z', incMsg)
275
+ psB.subscribe('Z')
276
+ psB.on('Z', incMsg)
277
+ psC.subscribe('Z')
278
+ psC.on('Z', incMsg)
279
+ psD.subscribe('Z')
280
+ psD.on('Z', incMsg)
281
+ psE.subscribe('Z')
282
+ psE.on('Z', incMsg)
283
+
284
+ await Promise.all([
285
+ new Promise((resolve) => psA.once('pubsub:subscription-change', resolve)),
286
+ new Promise((resolve) => psB.once('pubsub:subscription-change', resolve)),
287
+ new Promise((resolve) => psC.once('pubsub:subscription-change', resolve)),
288
+ new Promise((resolve) => psD.once('pubsub:subscription-change', resolve)),
289
+ new Promise((resolve) => psE.once('pubsub:subscription-change', resolve))
290
+ ])
291
+
292
+ // await a cycle
293
+ await delay(1000)
294
+
295
+ void psC.publish('Z', uint8ArrayFromString('hey from c'))
296
+
297
+ function incMsg (msg: Message) {
298
+ expect(uint8ArrayToString(msg.data)).to.equal('hey from c')
299
+ check()
300
+ }
301
+
302
+ function check () {
303
+ if (++counter === 5) {
304
+ psA.unsubscribe('Z')
305
+ psB.unsubscribe('Z')
306
+ psC.unsubscribe('Z')
307
+ psD.unsubscribe('Z')
308
+ psE.unsubscribe('Z')
309
+ defer.resolve()
310
+ }
311
+ }
312
+
313
+ return await defer.promise
314
+ })
315
+ })
316
+ })
317
+
318
+ describe('only some nodes subscribe the networks', () => {
319
+ describe('line', () => {
320
+ // line
321
+ // ◉────◎────◉
322
+ // a b c
323
+
324
+ before(() => { })
325
+ after(() => { })
326
+ })
327
+
328
+ describe('1 level tree', () => {
329
+ // 1 level tree
330
+ // ┌◉┐
331
+ // │b│
332
+ // ◎─┘ └─◉
333
+ // a c
334
+
335
+ before(() => { })
336
+ after(() => { })
337
+ })
338
+
339
+ describe('2 level tree', () => {
340
+ // 2 levels tree
341
+ // ┌◉┐
342
+ // │c│
343
+ // ┌◎─┘ └─◉┐
344
+ // │b d│
345
+ // ◉─┘ └─◎
346
+ // a e
347
+
348
+ before(() => { })
349
+ after(() => { })
350
+ })
351
+ })
352
+ })
353
+ }
@@ -0,0 +1,175 @@
1
+ /* eslint max-nested-callbacks: ["error", 6] */
2
+ import { expect } from 'aegir/utils/chai.js'
3
+ import sinon from 'sinon'
4
+ import pDefer from 'p-defer'
5
+ import pWaitFor from 'p-wait-for'
6
+ import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
7
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
8
+ import type { TestSetup } from '../index.js'
9
+ import type { PubSub, Message } from '@libp2p/interfaces/pubsub'
10
+ import {
11
+ first,
12
+ expectSet
13
+ } from './utils.js'
14
+ import type { Startable } from '@libp2p/interfaces'
15
+
16
+ const topic = 'foo'
17
+
18
+ function shouldNotHappen () {
19
+ expect.fail()
20
+ }
21
+
22
+ export default (common: TestSetup<PubSub & Startable>) => {
23
+ describe('pubsub with two nodes', () => {
24
+ let psA: PubSub & Startable
25
+ let psB: PubSub & Startable
26
+
27
+ // Create pubsub nodes and connect them
28
+ before(async () => {
29
+ psA = await common.setup()
30
+ psB = await common.setup()
31
+
32
+ expect(psA.peers.size).to.be.eql(0)
33
+ expect(psB.peers.size).to.be.eql(0)
34
+
35
+ // Start pubsub and connect nodes
36
+ await psA.start()
37
+ await psB.start()
38
+
39
+ // @ts-expect-error protected property
40
+ await psA._libp2p.dial(psB.peerId)
41
+
42
+ // Wait for peers to be ready in pubsub
43
+ await pWaitFor(() => psA.peers.size === 1 && psB.peers.size === 1)
44
+ })
45
+
46
+ after(async () => {
47
+ sinon.restore()
48
+
49
+ await psA.stop()
50
+ await psB.stop()
51
+
52
+ await common.teardown()
53
+ })
54
+
55
+ it('Subscribe to a topic in nodeA', async () => {
56
+ const defer = pDefer()
57
+
58
+ psB.once('pubsub:subscription-change', ({ peerId: changedPeerId, subscriptions: changedSubs }) => {
59
+ expectSet(psA.subscriptions, [topic])
60
+ expect(psB.peers.size).to.equal(1)
61
+ expectSet(psB.topics.get(topic), [psA.peerId.toString()])
62
+ expect(changedPeerId.toString()).to.equal(first(psB.peers).id.toString())
63
+ expect(changedSubs).to.have.lengthOf(1)
64
+ expect(changedSubs[0].topicID).to.equal(topic)
65
+ expect(changedSubs[0].subscribe).to.equal(true)
66
+ defer.resolve()
67
+ })
68
+ psA.subscribe(topic)
69
+
70
+ return await defer.promise
71
+ })
72
+
73
+ it('Publish to a topic in nodeA', async () => {
74
+ const defer = pDefer()
75
+
76
+ psA.once(topic, (msg) => {
77
+ expect(uint8ArrayToString(msg.data)).to.equal('hey')
78
+ psB.removeListener(topic, shouldNotHappen)
79
+ defer.resolve()
80
+ })
81
+
82
+ psB.once(topic, shouldNotHappen)
83
+
84
+ void psA.publish(topic, uint8ArrayFromString('hey'))
85
+
86
+ return await defer.promise
87
+ })
88
+
89
+ it('Publish to a topic in nodeB', async () => {
90
+ const defer = pDefer()
91
+
92
+ psA.once(topic, (msg) => {
93
+ psA.once(topic, shouldNotHappen)
94
+ expect(uint8ArrayToString(msg.data)).to.equal('banana')
95
+
96
+ setTimeout(() => {
97
+ psA.removeListener(topic, shouldNotHappen)
98
+ psB.removeListener(topic, shouldNotHappen)
99
+
100
+ defer.resolve()
101
+ }, 100)
102
+ })
103
+
104
+ psB.once(topic, shouldNotHappen)
105
+
106
+ void psB.publish(topic, uint8ArrayFromString('banana'))
107
+
108
+ return await defer.promise
109
+ })
110
+
111
+ it('Publish 10 msg to a topic in nodeB', async () => {
112
+ const defer = pDefer()
113
+ let counter = 0
114
+
115
+ psB.once(topic, shouldNotHappen)
116
+ psA.on(topic, receivedMsg)
117
+
118
+ function receivedMsg (msg: Message) {
119
+ expect(uint8ArrayToString(msg.data)).to.equal('banana')
120
+ expect(msg.from).to.be.eql(psB.peerId.toString())
121
+ expect(msg.seqno).to.be.a('Uint8Array')
122
+ expect(msg.topicIDs).to.be.eql([topic])
123
+
124
+ if (++counter === 10) {
125
+ psA.removeListener(topic, receivedMsg)
126
+ psB.removeListener(topic, shouldNotHappen)
127
+
128
+ defer.resolve()
129
+ }
130
+ }
131
+
132
+ Array.from({ length: 10 }, async (_, i) => await psB.publish(topic, uint8ArrayFromString('banana')))
133
+
134
+ return await defer.promise
135
+ })
136
+
137
+ it('Unsubscribe from topic in nodeA', async () => {
138
+ const defer = pDefer()
139
+
140
+ psA.unsubscribe(topic)
141
+ expect(psA.subscriptions.size).to.equal(0)
142
+
143
+ psB.once('pubsub:subscription-change', ({ peerId: changedPeerId, subscriptions: changedSubs }) => {
144
+ expect(psB.peers.size).to.equal(1)
145
+ expectSet(psB.topics.get(topic), [])
146
+ expect(changedPeerId.toString()).to.equal(first(psB.peers).id.toString())
147
+ expect(changedSubs).to.have.lengthOf(1)
148
+ expect(changedSubs[0].topicID).to.equal(topic)
149
+ expect(changedSubs[0].subscribe).to.equal(false)
150
+
151
+ defer.resolve()
152
+ })
153
+
154
+ return await defer.promise
155
+ })
156
+
157
+ it('Publish to a topic:Z in nodeA nodeB', async () => {
158
+ const defer = pDefer()
159
+
160
+ psA.once('Z', shouldNotHappen)
161
+ psB.once('Z', shouldNotHappen)
162
+
163
+ setTimeout(() => {
164
+ psA.removeListener('Z', shouldNotHappen)
165
+ psB.removeListener('Z', shouldNotHappen)
166
+ defer.resolve()
167
+ }, 100)
168
+
169
+ void psB.publish('Z', uint8ArrayFromString('banana'))
170
+ void psA.publish('Z', uint8ArrayFromString('banana'))
171
+
172
+ return await defer.promise
173
+ })
174
+ })
175
+ }
@@ -0,0 +1,13 @@
1
+ import { expect } from 'aegir/utils/chai.js'
2
+
3
+ export function first <V> (map: Map<any, V>): V {
4
+ return map.values().next().value
5
+ }
6
+
7
+ export function expectSet <T> (set?: Set<T>, subs?: T[]) {
8
+ if ((set == null) || (subs == null)) {
9
+ throw new Error('No set or subs passed')
10
+ }
11
+
12
+ expect(Array.from(set.values())).to.eql(subs)
13
+ }
@@ -0,0 +1,32 @@
1
+ import { expect } from 'aegir/utils/chai.js'
2
+ import type { TestSetup } from '../index.js'
3
+ import type { Record } from '@libp2p/interfaces/record'
4
+
5
+ export default (test: TestSetup<Record>) => {
6
+ describe('record', () => {
7
+ let record: Record
8
+
9
+ beforeEach(async () => {
10
+ record = await test.setup()
11
+ })
12
+
13
+ afterEach(async () => {
14
+ await test.teardown()
15
+ })
16
+
17
+ it('has domain and codec', () => {
18
+ expect(record.domain).to.exist()
19
+ expect(record.codec).to.exist()
20
+ })
21
+
22
+ it('is able to marshal', () => {
23
+ const rawData = record.marshal()
24
+ expect(rawData).to.be.an.instanceof(Uint8Array)
25
+ })
26
+
27
+ it('is able to compare two records', () => {
28
+ const equals = record.equals(record)
29
+ expect(equals).to.eql(true)
30
+ })
31
+ })
32
+ }