@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.
Files changed (183) hide show
  1. package/README.md +9 -0
  2. package/dist/src/connection/index.d.ts +5 -0
  3. package/dist/src/connection/index.d.ts.map +1 -0
  4. package/dist/src/connection/index.js +150 -0
  5. package/dist/src/connection/index.js.map +1 -0
  6. package/dist/src/connection-encryption/index.d.ts +5 -0
  7. package/dist/src/connection-encryption/index.d.ts.map +1 -0
  8. package/dist/src/connection-encryption/index.js +71 -0
  9. package/dist/src/connection-encryption/index.js.map +1 -0
  10. package/dist/src/connection-encryption/utils/index.d.ts +3 -0
  11. package/dist/src/connection-encryption/utils/index.d.ts.map +1 -0
  12. package/dist/src/connection-encryption/utils/index.js +19 -0
  13. package/dist/src/connection-encryption/utils/index.js.map +1 -0
  14. package/dist/src/index.d.ts.map +1 -1
  15. package/dist/src/is-valid-tick.d.ts.map +1 -1
  16. package/dist/src/is-valid-tick.js.map +1 -1
  17. package/dist/src/mocks/connection-encrypter.d.ts +3 -0
  18. package/dist/src/mocks/connection-encrypter.d.ts.map +1 -0
  19. package/dist/src/mocks/connection-encrypter.js +98 -0
  20. package/dist/src/mocks/connection-encrypter.js.map +1 -0
  21. package/dist/src/mocks/connection-gater.d.ts +3 -0
  22. package/dist/src/mocks/connection-gater.d.ts.map +1 -0
  23. package/dist/src/mocks/connection-gater.js +17 -0
  24. package/dist/src/mocks/connection-gater.js.map +1 -0
  25. package/dist/src/mocks/connection-manager.d.ts +29 -0
  26. package/dist/src/mocks/connection-manager.d.ts.map +1 -0
  27. package/dist/src/mocks/connection-manager.js +145 -0
  28. package/dist/src/mocks/connection-manager.js.map +1 -0
  29. package/dist/src/mocks/connection.d.ts +32 -0
  30. package/dist/src/mocks/connection.d.ts.map +1 -0
  31. package/dist/src/mocks/connection.js +167 -0
  32. package/dist/src/mocks/connection.js.map +1 -0
  33. package/dist/src/mocks/duplex.d.ts +3 -0
  34. package/dist/src/mocks/duplex.d.ts.map +1 -0
  35. package/dist/src/mocks/duplex.js +9 -0
  36. package/dist/src/mocks/duplex.js.map +1 -0
  37. package/dist/src/mocks/index.d.ts +13 -0
  38. package/dist/src/mocks/index.d.ts.map +1 -0
  39. package/dist/src/mocks/index.js +11 -0
  40. package/dist/src/mocks/index.js.map +1 -0
  41. package/dist/src/mocks/metrics.d.ts +3 -0
  42. package/dist/src/mocks/metrics.d.ts.map +1 -0
  43. package/dist/src/mocks/metrics.js +115 -0
  44. package/dist/src/mocks/metrics.js.map +1 -0
  45. package/dist/src/mocks/multiaddr-connection.d.ts +17 -0
  46. package/dist/src/mocks/multiaddr-connection.d.ts.map +1 -0
  47. package/dist/src/mocks/multiaddr-connection.js +60 -0
  48. package/dist/src/mocks/multiaddr-connection.js.map +1 -0
  49. package/dist/src/mocks/muxer.d.ts +36 -0
  50. package/dist/src/mocks/muxer.d.ts.map +1 -0
  51. package/dist/src/mocks/muxer.js +213 -0
  52. package/dist/src/mocks/muxer.js.map +1 -0
  53. package/dist/src/mocks/peer-discovery.d.ts +22 -0
  54. package/dist/src/mocks/peer-discovery.d.ts.map +1 -0
  55. package/dist/src/mocks/peer-discovery.js +47 -0
  56. package/dist/src/mocks/peer-discovery.js.map +1 -0
  57. package/dist/src/mocks/registrar.d.ts +18 -0
  58. package/dist/src/mocks/registrar.d.ts.map +1 -0
  59. package/dist/src/mocks/registrar.js +66 -0
  60. package/dist/src/mocks/registrar.js.map +1 -0
  61. package/dist/src/mocks/upgrader.d.ts +10 -0
  62. package/dist/src/mocks/upgrader.d.ts.map +1 -0
  63. package/dist/src/mocks/upgrader.js +31 -0
  64. package/dist/src/mocks/upgrader.js.map +1 -0
  65. package/dist/src/peer-discovery/index.d.ts +5 -0
  66. package/dist/src/peer-discovery/index.d.ts.map +1 -0
  67. package/dist/src/peer-discovery/index.js +66 -0
  68. package/dist/src/peer-discovery/index.js.map +1 -0
  69. package/dist/src/pubsub/api.d.ts +6 -0
  70. package/dist/src/pubsub/api.d.ts.map +1 -0
  71. package/dist/src/pubsub/api.js +87 -0
  72. package/dist/src/pubsub/api.js.map +1 -0
  73. package/dist/src/pubsub/connection-handlers.d.ts +6 -0
  74. package/dist/src/pubsub/connection-handlers.d.ts.map +1 -0
  75. package/dist/src/pubsub/connection-handlers.js +329 -0
  76. package/dist/src/pubsub/connection-handlers.js.map +1 -0
  77. package/dist/src/pubsub/emit-self.d.ts +6 -0
  78. package/dist/src/pubsub/emit-self.d.ts.map +1 -0
  79. package/dist/src/pubsub/emit-self.js +80 -0
  80. package/dist/src/pubsub/emit-self.js.map +1 -0
  81. package/dist/src/pubsub/index.d.ts +18 -0
  82. package/dist/src/pubsub/index.d.ts.map +1 -0
  83. package/dist/src/pubsub/index.js +17 -0
  84. package/dist/src/pubsub/index.js.map +1 -0
  85. package/dist/src/pubsub/messages.d.ts +6 -0
  86. package/dist/src/pubsub/messages.d.ts.map +1 -0
  87. package/dist/src/pubsub/messages.js +48 -0
  88. package/dist/src/pubsub/messages.js.map +1 -0
  89. package/dist/src/pubsub/multiple-nodes.d.ts +6 -0
  90. package/dist/src/pubsub/multiple-nodes.d.ts.map +1 -0
  91. package/dist/src/pubsub/multiple-nodes.js +350 -0
  92. package/dist/src/pubsub/multiple-nodes.js.map +1 -0
  93. package/dist/src/pubsub/two-nodes.d.ts +6 -0
  94. package/dist/src/pubsub/two-nodes.d.ts.map +1 -0
  95. package/dist/src/pubsub/two-nodes.js +217 -0
  96. package/dist/src/pubsub/two-nodes.js.map +1 -0
  97. package/dist/src/pubsub/utils.d.ts +6 -0
  98. package/dist/src/pubsub/utils.d.ts.map +1 -0
  99. package/dist/src/pubsub/utils.js +22 -0
  100. package/dist/src/pubsub/utils.js.map +1 -0
  101. package/dist/src/stream-muxer/base-test.d.ts +5 -0
  102. package/dist/src/stream-muxer/base-test.d.ts.map +1 -0
  103. package/dist/src/stream-muxer/base-test.js +153 -0
  104. package/dist/src/stream-muxer/base-test.js.map +1 -0
  105. package/dist/src/stream-muxer/close-test.d.ts +5 -0
  106. package/dist/src/stream-muxer/close-test.d.ts.map +1 -0
  107. package/dist/src/stream-muxer/close-test.js +357 -0
  108. package/dist/src/stream-muxer/close-test.js.map +1 -0
  109. package/dist/src/stream-muxer/fixtures/pb/message.d.ts +13 -0
  110. package/dist/src/stream-muxer/fixtures/pb/message.d.ts.map +1 -0
  111. package/dist/src/stream-muxer/fixtures/pb/message.js +67 -0
  112. package/dist/src/stream-muxer/fixtures/pb/message.js.map +1 -0
  113. package/dist/src/stream-muxer/index.d.ts +5 -0
  114. package/dist/src/stream-muxer/index.d.ts.map +1 -0
  115. package/dist/src/stream-muxer/index.js +13 -0
  116. package/dist/src/stream-muxer/index.js.map +1 -0
  117. package/dist/src/stream-muxer/mega-stress-test.d.ts +5 -0
  118. package/dist/src/stream-muxer/mega-stress-test.d.ts.map +1 -0
  119. package/dist/src/stream-muxer/mega-stress-test.js +11 -0
  120. package/dist/src/stream-muxer/mega-stress-test.js.map +1 -0
  121. package/dist/src/stream-muxer/spawner.d.ts +4 -0
  122. package/dist/src/stream-muxer/spawner.d.ts.map +1 -0
  123. package/dist/src/stream-muxer/spawner.js +37 -0
  124. package/dist/src/stream-muxer/spawner.js.map +1 -0
  125. package/dist/src/stream-muxer/stress-test.d.ts +5 -0
  126. package/dist/src/stream-muxer/stress-test.d.ts.map +1 -0
  127. package/dist/src/stream-muxer/stress-test.js +23 -0
  128. package/dist/src/stream-muxer/stress-test.js.map +1 -0
  129. package/dist/src/transport/dial-test.d.ts +5 -0
  130. package/dist/src/transport/dial-test.d.ts.map +1 -0
  131. package/dist/src/transport/dial-test.js +98 -0
  132. package/dist/src/transport/dial-test.js.map +1 -0
  133. package/dist/src/transport/filter-test.d.ts +5 -0
  134. package/dist/src/transport/filter-test.d.ts.map +1 -0
  135. package/dist/src/transport/filter-test.js +18 -0
  136. package/dist/src/transport/filter-test.js.map +1 -0
  137. package/dist/src/transport/index.d.ts +15 -0
  138. package/dist/src/transport/index.d.ts.map +1 -0
  139. package/dist/src/transport/index.js +11 -0
  140. package/dist/src/transport/index.js.map +1 -0
  141. package/dist/src/transport/listen-test.d.ts +5 -0
  142. package/dist/src/transport/listen-test.d.ts.map +1 -0
  143. package/dist/src/transport/listen-test.js +152 -0
  144. package/dist/src/transport/listen-test.js.map +1 -0
  145. package/package.json +72 -5
  146. package/src/connection/index.ts +182 -0
  147. package/src/connection-encryption/index.ts +97 -0
  148. package/src/connection-encryption/utils/index.ts +24 -0
  149. package/src/index.ts +0 -1
  150. package/src/is-valid-tick.ts +0 -1
  151. package/src/mocks/connection-encrypter.ts +113 -0
  152. package/src/mocks/connection-gater.ts +18 -0
  153. package/src/mocks/connection-manager.ts +211 -0
  154. package/src/mocks/connection.ts +226 -0
  155. package/src/mocks/duplex.ts +10 -0
  156. package/src/mocks/index.ts +12 -0
  157. package/src/mocks/metrics.ts +162 -0
  158. package/src/mocks/multiaddr-connection.ts +76 -0
  159. package/src/mocks/muxer.ts +303 -0
  160. package/src/mocks/peer-discovery.ts +60 -0
  161. package/src/mocks/registrar.ts +88 -0
  162. package/src/mocks/upgrader.ts +49 -0
  163. package/src/peer-discovery/index.ts +90 -0
  164. package/src/pubsub/api.ts +114 -0
  165. package/src/pubsub/connection-handlers.ts +413 -0
  166. package/src/pubsub/emit-self.ts +99 -0
  167. package/src/pubsub/index.ts +34 -0
  168. package/src/pubsub/messages.ts +59 -0
  169. package/src/pubsub/multiple-nodes.ts +440 -0
  170. package/src/pubsub/two-nodes.ts +273 -0
  171. package/src/pubsub/utils.ts +29 -0
  172. package/src/stream-muxer/base-test.ts +196 -0
  173. package/src/stream-muxer/close-test.ts +442 -0
  174. package/src/stream-muxer/fixtures/pb/message.proto +7 -0
  175. package/src/stream-muxer/fixtures/pb/message.ts +87 -0
  176. package/src/stream-muxer/index.ts +15 -0
  177. package/src/stream-muxer/mega-stress-test.ts +14 -0
  178. package/src/stream-muxer/spawner.ts +55 -0
  179. package/src/stream-muxer/stress-test.ts +27 -0
  180. package/src/transport/dial-test.ts +124 -0
  181. package/src/transport/filter-test.ts +25 -0
  182. package/src/transport/index.ts +25 -0
  183. package/src/transport/listen-test.ts +191 -0
@@ -0,0 +1,99 @@
1
+ import { start, stop } from '@libp2p/interface/startable'
2
+ import { expect } from 'aegir/chai'
3
+ import sinon from 'sinon'
4
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
5
+ import { mockNetwork } from '../mocks/index.js'
6
+ import { createComponents } from './utils.js'
7
+ import type { PubSubArgs, PubSubComponents } from './index.js'
8
+ import type { TestSetup } from '../index.js'
9
+ import type { PubSub } from '@libp2p/interface/pubsub'
10
+
11
+ const topic = 'foo'
12
+ const data = uint8ArrayFromString('bar')
13
+ const shouldNotHappen = (): void => expect.fail()
14
+
15
+ export default (common: TestSetup<PubSub, PubSubArgs>): void => {
16
+ describe('emit self', () => {
17
+ describe('enabled', () => {
18
+ let pubsub: PubSub
19
+ let components: PubSubComponents
20
+
21
+ before(async () => {
22
+ mockNetwork.reset()
23
+ components = await createComponents()
24
+
25
+ pubsub = components.pubsub = await common.setup({
26
+ components,
27
+ init: {
28
+ emitSelf: true
29
+ }
30
+ })
31
+
32
+ await start(...Object.values(components))
33
+ pubsub.subscribe(topic)
34
+ })
35
+
36
+ after(async () => {
37
+ sinon.restore()
38
+ await stop(...Object.values(components))
39
+ await common.teardown()
40
+ mockNetwork.reset()
41
+ })
42
+
43
+ it('should emit to self on publish', async () => {
44
+ const promise = new Promise<void>((resolve) => {
45
+ pubsub.addEventListener('message', (evt) => {
46
+ if (evt.detail.topic === topic) {
47
+ resolve()
48
+ }
49
+ }, {
50
+ once: true
51
+ })
52
+ })
53
+
54
+ const result = await pubsub.publish(topic, data)
55
+
56
+ await promise
57
+
58
+ expect(result).to.have.property('recipients').with.lengthOf(1)
59
+ })
60
+ })
61
+
62
+ describe('disabled', () => {
63
+ let pubsub: PubSub
64
+ let components: PubSubComponents
65
+
66
+ before(async () => {
67
+ mockNetwork.reset()
68
+ components = await createComponents()
69
+ pubsub = components.pubsub = await common.setup({
70
+ components,
71
+ init: {
72
+ emitSelf: false
73
+ }
74
+ })
75
+
76
+ await start(...Object.values(components))
77
+ pubsub.subscribe(topic)
78
+ })
79
+
80
+ after(async () => {
81
+ sinon.restore()
82
+ await stop(...Object.values(components))
83
+ await common.teardown()
84
+ mockNetwork.reset()
85
+ })
86
+
87
+ it('should not emit to self on publish', async () => {
88
+ pubsub.addEventListener('message', shouldNotHappen, {
89
+ once: true
90
+ })
91
+
92
+ await pubsub.publish(topic, data)
93
+
94
+ // Wait 1 second to guarantee that self is not noticed
95
+ await new Promise((resolve) => setTimeout(resolve, 1000))
96
+ })
97
+ })
98
+ })
99
+ }
@@ -0,0 +1,34 @@
1
+ import apiTest from './api.js'
2
+ import connectionHandlersTest from './connection-handlers.js'
3
+ import emitSelfTest from './emit-self.js'
4
+ import messagesTest from './messages.js'
5
+ import multipleNodesTest from './multiple-nodes.js'
6
+ import twoNodesTest from './two-nodes.js'
7
+ import type { TestSetup } from '../index.js'
8
+ import type { PeerId } from '@libp2p/interface/peer-id'
9
+ import type { PubSub, PubSubInit } from '@libp2p/interface/pubsub'
10
+ import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager'
11
+ import type { Registrar } from '@libp2p/interface-internal/registrar'
12
+
13
+ export interface PubSubComponents {
14
+ peerId: PeerId
15
+ registrar: Registrar
16
+ connectionManager: ConnectionManager
17
+ pubsub?: PubSub
18
+ }
19
+
20
+ export interface PubSubArgs {
21
+ components: PubSubComponents
22
+ init: PubSubInit
23
+ }
24
+
25
+ export default (common: TestSetup<PubSub, PubSubArgs>): void => {
26
+ describe('interface-pubsub compliance tests', () => {
27
+ apiTest(common)
28
+ emitSelfTest(common)
29
+ messagesTest(common)
30
+ connectionHandlersTest(common)
31
+ twoNodesTest(common)
32
+ multipleNodesTest(common)
33
+ })
34
+ }
@@ -0,0 +1,59 @@
1
+ import { start, stop } from '@libp2p/interface/startable'
2
+ import { expect } from 'aegir/chai'
3
+ import { pEvent } from 'p-event'
4
+ import sinon from 'sinon'
5
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
6
+ import { mockNetwork } from '../mocks/index.js'
7
+ import { createComponents } from './utils.js'
8
+ import type { PubSubArgs, PubSubComponents } from './index.js'
9
+ import type { TestSetup } from '../index.js'
10
+ import type { Message, PubSub } from '@libp2p/interface/pubsub'
11
+
12
+ const topic = 'foo'
13
+ const data = uint8ArrayFromString('bar')
14
+
15
+ export default (common: TestSetup<PubSub, PubSubArgs>): void => {
16
+ describe('messages', () => {
17
+ let pubsub: PubSub
18
+ let components: PubSubComponents
19
+
20
+ // Create pubsub router
21
+ beforeEach(async () => {
22
+ mockNetwork.reset()
23
+ components = await createComponents()
24
+
25
+ pubsub = components.pubsub = await common.setup({
26
+ components,
27
+ init: {
28
+ emitSelf: true
29
+ }
30
+ })
31
+ await start(...Object.values(components))
32
+ })
33
+
34
+ afterEach(async () => {
35
+ sinon.restore()
36
+ await stop(...Object.values(components))
37
+ await common.teardown()
38
+ mockNetwork.reset()
39
+ })
40
+
41
+ it('should emit normalized signed messages on publish', async () => {
42
+ const eventPromise = pEvent<'message', CustomEvent<Message>>(pubsub, 'message')
43
+
44
+ pubsub.globalSignaturePolicy = 'StrictSign'
45
+ pubsub.subscribe(topic)
46
+ await pubsub.publish(topic, data)
47
+
48
+ const event = await eventPromise
49
+ const message = event.detail
50
+
51
+ if (message.type === 'signed') {
52
+ expect(message.from.toString()).to.equal(components.peerId.toString())
53
+ expect(message.sequenceNumber).to.not.eql(undefined)
54
+ expect(message.key).to.not.eql(undefined)
55
+ expect(message.signature).to.not.eql(undefined)
56
+ }
57
+ })
58
+ })
59
+ }
@@ -0,0 +1,440 @@
1
+ /* eslint max-nested-callbacks: ["error", 6] */
2
+ import { start, stop } from '@libp2p/interface/startable'
3
+ import { expect } from 'aegir/chai'
4
+ import delay from 'delay'
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
+ export default (common: TestSetup<PubSub, PubSubArgs>): void => {
17
+ describe('pubsub with multiple nodes', function () {
18
+ describe('every peer subscribes to the topic', () => {
19
+ describe('line', () => {
20
+ // line
21
+ // ◉────◉────◉
22
+ // a b c
23
+ let psA: PubSub
24
+ let psB: PubSub
25
+ let psC: PubSub
26
+ let componentsA: PubSubComponents
27
+ let componentsB: PubSubComponents
28
+ let componentsC: PubSubComponents
29
+
30
+ // Create and start pubsub nodes
31
+ beforeEach(async () => {
32
+ mockNetwork.reset()
33
+
34
+ componentsA = await createComponents()
35
+ componentsB = await createComponents()
36
+ componentsC = await createComponents()
37
+
38
+ psA = componentsA.pubsub = await common.setup({
39
+ components: componentsA,
40
+ init: {
41
+ emitSelf: true
42
+ }
43
+ })
44
+ psB = componentsB.pubsub = await common.setup({
45
+ components: componentsB,
46
+ init: {
47
+ emitSelf: true
48
+ }
49
+ })
50
+ psC = componentsC.pubsub = await common.setup({
51
+ components: componentsC,
52
+ init: {
53
+ emitSelf: true
54
+ }
55
+ })
56
+
57
+ // Start pubsub modes
58
+ await start(...Object.values(componentsA), ...Object.values(componentsB), ...Object.values(componentsC))
59
+
60
+ // Connect nodes
61
+ await componentsA.connectionManager.openConnection(componentsB.peerId)
62
+ await componentsB.connectionManager.openConnection(componentsC.peerId)
63
+
64
+ // Wait for peers to be ready in pubsub
65
+ await pWaitFor(() =>
66
+ psA.getPeers().length === 1 &&
67
+ psC.getPeers().length === 1 &&
68
+ psA.getPeers().length === 1
69
+ )
70
+ })
71
+
72
+ afterEach(async () => {
73
+ sinon.restore()
74
+ await stop(...Object.values(componentsA), ...Object.values(componentsB), ...Object.values(componentsC))
75
+ await common.teardown()
76
+ mockNetwork.reset()
77
+ })
78
+
79
+ it('subscribe to the topic on node a', async () => {
80
+ const topic = 'Z'
81
+
82
+ psA.subscribe(topic)
83
+ expect(psA.getTopics()).to.deep.equal([topic])
84
+
85
+ await waitForSubscriptionUpdate(psB, componentsA.peerId)
86
+
87
+ expect(psB.getPeers().length).to.equal(2)
88
+ expect(psB.getSubscribers(topic).map(p => p.toString())).to.deep.equal([componentsA.peerId.toString()])
89
+
90
+ expect(psC.getPeers().length).to.equal(1)
91
+ expect(psC.getSubscribers(topic)).to.be.empty()
92
+ })
93
+
94
+ it('subscribe to the topic on node b', async () => {
95
+ const topic = 'Z'
96
+ psB.subscribe(topic)
97
+ expect(psB.getTopics()).to.deep.equal([topic])
98
+
99
+ await Promise.all([
100
+ waitForSubscriptionUpdate(psA, componentsB.peerId),
101
+ waitForSubscriptionUpdate(psC, componentsB.peerId)
102
+ ])
103
+
104
+ expect(psA.getPeers().length).to.equal(1)
105
+ expect(psA.getSubscribers(topic).map(p => p.toString())).to.deep.equal([componentsB.peerId.toString()])
106
+
107
+ expect(psC.getPeers().length).to.equal(1)
108
+ expect(psC.getSubscribers(topic).map(p => p.toString())).to.deep.equal([componentsB.peerId.toString()])
109
+ })
110
+
111
+ it('subscribe to the topic on node c', async () => {
112
+ const topic = 'Z'
113
+ const defer = pDefer()
114
+
115
+ psC.subscribe(topic)
116
+ expect(psC.getTopics()).to.deep.equal([topic])
117
+
118
+ psB.addEventListener('subscription-change', () => {
119
+ expect(psA.getPeers().length).to.equal(1)
120
+ expect(psB.getPeers().length).to.equal(2)
121
+ expect(psB.getSubscribers(topic).map(p => p.toString())).to.deep.equal([componentsC.peerId.toString()])
122
+
123
+ defer.resolve()
124
+ }, {
125
+ once: true
126
+ })
127
+
128
+ return defer.promise
129
+ })
130
+
131
+ it('publish on node a', async () => {
132
+ const topic = 'Z'
133
+ const defer = pDefer()
134
+
135
+ psA.subscribe(topic)
136
+ psB.subscribe(topic)
137
+ psC.subscribe(topic)
138
+
139
+ await Promise.all([
140
+ waitForSubscriptionUpdate(psA, componentsB.peerId),
141
+ waitForSubscriptionUpdate(psB, componentsA.peerId),
142
+ waitForSubscriptionUpdate(psC, componentsB.peerId)
143
+ ])
144
+
145
+ // GossipSub needs time to build the mesh overlay
146
+ await delay(1000)
147
+
148
+ let counter = 0
149
+
150
+ psA.addEventListener('message', incMsg)
151
+ psB.addEventListener('message', incMsg)
152
+ psC.addEventListener('message', incMsg)
153
+
154
+ const result = await psA.publish(topic, uint8ArrayFromString('hey'))
155
+
156
+ expect(result).to.have.property('recipients').with.property('length').greaterThanOrEqual(1)
157
+
158
+ function incMsg (evt: CustomEvent<Message>): void {
159
+ const msg = evt.detail
160
+
161
+ if (msg.topic !== topic) {
162
+ return
163
+ }
164
+
165
+ expect(uint8ArrayToString(msg.data)).to.equal('hey')
166
+ check()
167
+ }
168
+
169
+ function check (): void {
170
+ if (++counter === 3) {
171
+ psA.removeEventListener('message', incMsg)
172
+ psB.removeEventListener('message', incMsg)
173
+ psC.removeEventListener('message', incMsg)
174
+ defer.resolve()
175
+ }
176
+ }
177
+
178
+ return defer.promise
179
+ })
180
+
181
+ // since the topology is the same, just the publish
182
+ // gets sent by other peer, we reused the same peers
183
+ describe('1 level tree', () => {
184
+ // 1 level tree
185
+ // ┌◉┐
186
+ // │b│
187
+ // ◉─┘ └─◉
188
+ // a c
189
+
190
+ it('publish on node b', async () => {
191
+ const topic = 'Z'
192
+ const defer = pDefer()
193
+ let counter = 0
194
+
195
+ psA.subscribe(topic)
196
+ psB.subscribe(topic)
197
+ psC.subscribe(topic)
198
+
199
+ await Promise.all([
200
+ waitForSubscriptionUpdate(psA, componentsB.peerId),
201
+ waitForSubscriptionUpdate(psB, componentsA.peerId),
202
+ waitForSubscriptionUpdate(psC, componentsB.peerId)
203
+ ])
204
+
205
+ // GossipSub needs time to build the mesh overlay
206
+ await delay(1000)
207
+
208
+ psA.addEventListener('message', incMsg)
209
+ psB.addEventListener('message', incMsg)
210
+ psC.addEventListener('message', incMsg)
211
+
212
+ await psB.publish(topic, uint8ArrayFromString('hey'))
213
+
214
+ function incMsg (evt: CustomEvent<Message>): void {
215
+ const msg = evt.detail
216
+
217
+ if (msg.topic !== topic) {
218
+ return
219
+ }
220
+
221
+ expect(uint8ArrayToString(msg.data)).to.equal('hey')
222
+ check()
223
+ }
224
+
225
+ function check (): void {
226
+ if (++counter === 3) {
227
+ psA.removeEventListener('message', incMsg)
228
+ psB.removeEventListener('message', incMsg)
229
+ psC.removeEventListener('message', incMsg)
230
+ defer.resolve()
231
+ }
232
+ }
233
+
234
+ return defer.promise
235
+ })
236
+ })
237
+ })
238
+
239
+ describe('2 level tree', () => {
240
+ // 2 levels tree
241
+ // ┌◉┐
242
+ // │c│
243
+ // ┌◉─┘ └─◉┐
244
+ // │b d│
245
+ // ◉─┘ └─◉
246
+ // a
247
+ let psA: PubSub
248
+ let psB: PubSub
249
+ let psC: PubSub
250
+ let psD: PubSub
251
+ let psE: PubSub
252
+ let componentsA: PubSubComponents
253
+ let componentsB: PubSubComponents
254
+ let componentsC: PubSubComponents
255
+ let componentsD: PubSubComponents
256
+ let componentsE: PubSubComponents
257
+
258
+ // Create and start pubsub nodes
259
+ beforeEach(async () => {
260
+ mockNetwork.reset()
261
+
262
+ componentsA = await createComponents()
263
+ componentsB = await createComponents()
264
+ componentsC = await createComponents()
265
+ componentsD = await createComponents()
266
+ componentsE = await createComponents()
267
+
268
+ psA = componentsA.pubsub = await common.setup({
269
+ components: componentsA,
270
+ init: {
271
+ emitSelf: true
272
+ }
273
+ })
274
+ psB = componentsB.pubsub = await common.setup({
275
+ components: componentsB,
276
+ init: {
277
+ emitSelf: true
278
+ }
279
+ })
280
+ psC = componentsC.pubsub = await common.setup({
281
+ components: componentsC,
282
+ init: {
283
+ emitSelf: true
284
+ }
285
+ })
286
+ psD = componentsD.pubsub = await common.setup({
287
+ components: componentsD,
288
+ init: {
289
+ emitSelf: true
290
+ }
291
+ })
292
+ psE = componentsE.pubsub = await common.setup({
293
+ components: componentsE,
294
+ init: {
295
+ emitSelf: true
296
+ }
297
+ })
298
+
299
+ // Start pubsub nodes
300
+ await start(
301
+ ...Object.values(componentsA),
302
+ ...Object.values(componentsB),
303
+ ...Object.values(componentsC),
304
+ ...Object.values(componentsD),
305
+ ...Object.values(componentsE)
306
+ )
307
+
308
+ // connect nodes
309
+ await componentsA.connectionManager.openConnection(componentsB.peerId)
310
+ await componentsB.connectionManager.openConnection(componentsC.peerId)
311
+ await componentsC.connectionManager.openConnection(componentsD.peerId)
312
+ await componentsD.connectionManager.openConnection(componentsE.peerId)
313
+
314
+ // Wait for peers to be ready in pubsub
315
+ await pWaitFor(() =>
316
+ psA.getPeers().length === 1 &&
317
+ psB.getPeers().length === 2 &&
318
+ psC.getPeers().length === 2 &&
319
+ psD.getPeers().length === 2 &&
320
+ psE.getPeers().length === 1
321
+ )
322
+ })
323
+
324
+ afterEach(async () => {
325
+ await stop(
326
+ ...Object.values(componentsA),
327
+ ...Object.values(componentsB),
328
+ ...Object.values(componentsC),
329
+ ...Object.values(componentsD),
330
+ ...Object.values(componentsE)
331
+ )
332
+ await common.teardown()
333
+ mockNetwork.reset()
334
+ })
335
+
336
+ it('subscribes', () => {
337
+ psA.subscribe('Z')
338
+ expect(psA.getTopics()).to.deep.equal(['Z'])
339
+ psB.subscribe('Z')
340
+ expect(psB.getTopics()).to.deep.equal(['Z'])
341
+ psC.subscribe('Z')
342
+ expect(psC.getTopics()).to.deep.equal(['Z'])
343
+ psD.subscribe('Z')
344
+ expect(psD.getTopics()).to.deep.equal(['Z'])
345
+ psE.subscribe('Z')
346
+ expect(psE.getTopics()).to.deep.equal(['Z'])
347
+ })
348
+
349
+ it('publishes from c', async function () {
350
+ const defer = pDefer()
351
+ let counter = 0
352
+ const topic = 'Z'
353
+
354
+ psA.subscribe(topic)
355
+ psA.addEventListener('message', incMsg)
356
+ psB.subscribe(topic)
357
+ psB.addEventListener('message', incMsg)
358
+ psC.subscribe(topic)
359
+ psC.addEventListener('message', incMsg)
360
+ psD.subscribe(topic)
361
+ psD.addEventListener('message', incMsg)
362
+ psE.subscribe(topic)
363
+ psE.addEventListener('message', incMsg)
364
+
365
+ await Promise.all([
366
+ waitForSubscriptionUpdate(psA, componentsB.peerId),
367
+ waitForSubscriptionUpdate(psB, componentsA.peerId),
368
+ waitForSubscriptionUpdate(psC, componentsB.peerId),
369
+ waitForSubscriptionUpdate(psD, componentsC.peerId),
370
+ waitForSubscriptionUpdate(psE, componentsD.peerId)
371
+ ])
372
+
373
+ // GossipSub needs time to build the mesh overlay
374
+ await delay(1000)
375
+
376
+ await psC.publish('Z', uint8ArrayFromString('hey from c'))
377
+
378
+ function incMsg (evt: CustomEvent<Message>): void {
379
+ const msg = evt.detail
380
+
381
+ if (msg.topic !== topic) {
382
+ return
383
+ }
384
+
385
+ expect(uint8ArrayToString(msg.data)).to.equal('hey from c')
386
+ check()
387
+ }
388
+
389
+ function check (): void {
390
+ if (++counter === 5) {
391
+ psA.unsubscribe('Z')
392
+ psB.unsubscribe('Z')
393
+ psC.unsubscribe('Z')
394
+ psD.unsubscribe('Z')
395
+ psE.unsubscribe('Z')
396
+ defer.resolve()
397
+ }
398
+ }
399
+
400
+ return defer.promise
401
+ })
402
+ })
403
+ })
404
+
405
+ describe('only some nodes subscribe the networks', () => {
406
+ describe('line', () => {
407
+ // line
408
+ // ◉────◎────◉
409
+ // a b c
410
+
411
+ before(() => { })
412
+ after(() => { })
413
+ })
414
+
415
+ describe('1 level tree', () => {
416
+ // 1 level tree
417
+ // ┌◉┐
418
+ // │b│
419
+ // ◎─┘ └─◉
420
+ // a c
421
+
422
+ before(() => { })
423
+ after(() => { })
424
+ })
425
+
426
+ describe('2 level tree', () => {
427
+ // 2 levels tree
428
+ // ┌◉┐
429
+ // │c│
430
+ // ┌◎─┘ └─◉┐
431
+ // │b d│
432
+ // ◉─┘ └─◎
433
+ // a e
434
+
435
+ before(() => { })
436
+ after(() => { })
437
+ })
438
+ })
439
+ })
440
+ }