@streamr/trackerless-network 0.0.1-tatum.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 (262) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc +3 -0
  3. package/README.md +6 -0
  4. package/bin/bootstrap-node.ts +73 -0
  5. package/bin/full-node-webrtc.ts +102 -0
  6. package/bin/full-node-websocket.ts +102 -0
  7. package/bin/network.ts +43 -0
  8. package/dist/package.json +53 -0
  9. package/dist/src/NameDirectory.d.ts +5 -0
  10. package/dist/src/NameDirectory.js +44 -0
  11. package/dist/src/NameDirectory.js.map +1 -0
  12. package/dist/src/NetworkNode.d.ts +35 -0
  13. package/dist/src/NetworkNode.js +130 -0
  14. package/dist/src/NetworkNode.js.map +1 -0
  15. package/dist/src/NetworkStack.d.ts +32 -0
  16. package/dist/src/NetworkStack.js +108 -0
  17. package/dist/src/NetworkStack.js.map +1 -0
  18. package/dist/src/exports.d.ts +6 -0
  19. package/dist/src/exports.js +12 -0
  20. package/dist/src/exports.js.map +1 -0
  21. package/dist/src/identifiers.d.ts +1 -0
  22. package/dist/src/identifiers.js +3 -0
  23. package/dist/src/identifiers.js.map +1 -0
  24. package/dist/src/logic/DuplicateMessageDetector.d.ts +55 -0
  25. package/dist/src/logic/DuplicateMessageDetector.js +155 -0
  26. package/dist/src/logic/DuplicateMessageDetector.js.map +1 -0
  27. package/dist/src/logic/ILayer0.d.ts +13 -0
  28. package/dist/src/logic/ILayer0.js +3 -0
  29. package/dist/src/logic/ILayer0.js.map +1 -0
  30. package/dist/src/logic/IStreamNode.d.ts +12 -0
  31. package/dist/src/logic/IStreamNode.js +3 -0
  32. package/dist/src/logic/IStreamNode.js.map +1 -0
  33. package/dist/src/logic/PeerList.d.ts +27 -0
  34. package/dist/src/logic/PeerList.js +84 -0
  35. package/dist/src/logic/PeerList.js.map +1 -0
  36. package/dist/src/logic/RandomGraphNode.d.ts +68 -0
  37. package/dist/src/logic/RandomGraphNode.js +201 -0
  38. package/dist/src/logic/RandomGraphNode.js.map +1 -0
  39. package/dist/src/logic/Remote.d.ts +9 -0
  40. package/dist/src/logic/Remote.js +15 -0
  41. package/dist/src/logic/Remote.js.map +1 -0
  42. package/dist/src/logic/RemoteRandomGraphNode.d.ts +8 -0
  43. package/dist/src/logic/RemoteRandomGraphNode.js +35 -0
  44. package/dist/src/logic/RemoteRandomGraphNode.js.map +1 -0
  45. package/dist/src/logic/StreamEntryPointDiscovery.d.ts +36 -0
  46. package/dist/src/logic/StreamEntryPointDiscovery.js +179 -0
  47. package/dist/src/logic/StreamEntryPointDiscovery.js.map +1 -0
  48. package/dist/src/logic/StreamNodeServer.d.ts +20 -0
  49. package/dist/src/logic/StreamNodeServer.js +26 -0
  50. package/dist/src/logic/StreamNodeServer.js.map +1 -0
  51. package/dist/src/logic/StreamrNode.d.ts +76 -0
  52. package/dist/src/logic/StreamrNode.js +303 -0
  53. package/dist/src/logic/StreamrNode.js.map +1 -0
  54. package/dist/src/logic/createRandomGraphNode.d.ts +5 -0
  55. package/dist/src/logic/createRandomGraphNode.js +110 -0
  56. package/dist/src/logic/createRandomGraphNode.js.map +1 -0
  57. package/dist/src/logic/inspect/InspectSession.d.ts +18 -0
  58. package/dist/src/logic/inspect/InspectSession.js +38 -0
  59. package/dist/src/logic/inspect/InspectSession.js.map +1 -0
  60. package/dist/src/logic/inspect/Inspector.d.ts +33 -0
  61. package/dist/src/logic/inspect/Inspector.js +63 -0
  62. package/dist/src/logic/inspect/Inspector.js.map +1 -0
  63. package/dist/src/logic/neighbor-discovery/Handshaker.d.ts +35 -0
  64. package/dist/src/logic/neighbor-discovery/Handshaker.js +121 -0
  65. package/dist/src/logic/neighbor-discovery/Handshaker.js.map +1 -0
  66. package/dist/src/logic/neighbor-discovery/HandshakerServer.d.ts +30 -0
  67. package/dist/src/logic/neighbor-discovery/HandshakerServer.js +78 -0
  68. package/dist/src/logic/neighbor-discovery/HandshakerServer.js.map +1 -0
  69. package/dist/src/logic/neighbor-discovery/NeighborFinder.d.ts +23 -0
  70. package/dist/src/logic/neighbor-discovery/NeighborFinder.js +44 -0
  71. package/dist/src/logic/neighbor-discovery/NeighborFinder.js.map +1 -0
  72. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.d.ts +30 -0
  73. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js +42 -0
  74. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js.map +1 -0
  75. package/dist/src/logic/neighbor-discovery/NeighborUpdateManagerServer.d.ts +20 -0
  76. package/dist/src/logic/neighbor-discovery/NeighborUpdateManagerServer.js +42 -0
  77. package/dist/src/logic/neighbor-discovery/NeighborUpdateManagerServer.js.map +1 -0
  78. package/dist/src/logic/neighbor-discovery/RemoteHandshaker.d.ts +12 -0
  79. package/dist/src/logic/neighbor-discovery/RemoteHandshaker.js +54 -0
  80. package/dist/src/logic/neighbor-discovery/RemoteHandshaker.js.map +1 -0
  81. package/dist/src/logic/neighbor-discovery/RemoteNeighborUpdateManager.d.ts +11 -0
  82. package/dist/src/logic/neighbor-discovery/RemoteNeighborUpdateManager.js +37 -0
  83. package/dist/src/logic/neighbor-discovery/RemoteNeighborUpdateManager.js.map +1 -0
  84. package/dist/src/logic/propagation/FifoMapWithTTL.d.ts +36 -0
  85. package/dist/src/logic/propagation/FifoMapWithTTL.js +81 -0
  86. package/dist/src/logic/propagation/FifoMapWithTTL.js.map +1 -0
  87. package/dist/src/logic/propagation/Propagation.d.ts +31 -0
  88. package/dist/src/logic/propagation/Propagation.js +64 -0
  89. package/dist/src/logic/propagation/Propagation.js.map +1 -0
  90. package/dist/src/logic/propagation/PropagationTaskStore.d.ts +21 -0
  91. package/dist/src/logic/propagation/PropagationTaskStore.js +32 -0
  92. package/dist/src/logic/propagation/PropagationTaskStore.js.map +1 -0
  93. package/dist/src/logic/protocol-integration/stream-message/ContentMessageTranslator.d.ts +5 -0
  94. package/dist/src/logic/protocol-integration/stream-message/ContentMessageTranslator.js +17 -0
  95. package/dist/src/logic/protocol-integration/stream-message/ContentMessageTranslator.js.map +1 -0
  96. package/dist/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.d.ts +6 -0
  97. package/dist/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.js +27 -0
  98. package/dist/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.js.map +1 -0
  99. package/dist/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.d.ts +6 -0
  100. package/dist/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.js +33 -0
  101. package/dist/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.js.map +1 -0
  102. package/dist/src/logic/protocol-integration/stream-message/StreamMessageTranslator.d.ts +6 -0
  103. package/dist/src/logic/protocol-integration/stream-message/StreamMessageTranslator.js +109 -0
  104. package/dist/src/logic/protocol-integration/stream-message/StreamMessageTranslator.js.map +1 -0
  105. package/dist/src/logic/proxy/ProxyStreamConnectionClient.d.ts +44 -0
  106. package/dist/src/logic/proxy/ProxyStreamConnectionClient.js +189 -0
  107. package/dist/src/logic/proxy/ProxyStreamConnectionClient.js.map +1 -0
  108. package/dist/src/logic/proxy/ProxyStreamConnectionServer.d.ts +34 -0
  109. package/dist/src/logic/proxy/ProxyStreamConnectionServer.js +64 -0
  110. package/dist/src/logic/proxy/ProxyStreamConnectionServer.js.map +1 -0
  111. package/dist/src/logic/proxy/RemoteProxyServer.d.ts +7 -0
  112. package/dist/src/logic/proxy/RemoteProxyServer.js +36 -0
  113. package/dist/src/logic/proxy/RemoteProxyServer.js.map +1 -0
  114. package/dist/src/logic/temporary-connection/RemoteTemporaryConnectionRpcServer.d.ts +6 -0
  115. package/dist/src/logic/temporary-connection/RemoteTemporaryConnectionRpcServer.js +28 -0
  116. package/dist/src/logic/temporary-connection/RemoteTemporaryConnectionRpcServer.js.map +1 -0
  117. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcServer.d.ts +20 -0
  118. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcServer.js +29 -0
  119. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcServer.js.map +1 -0
  120. package/dist/src/logic/utils.d.ts +3 -0
  121. package/dist/src/logic/utils.js +16 -0
  122. package/dist/src/logic/utils.js.map +1 -0
  123. package/dist/src/proto/google/protobuf/any.d.ts +173 -0
  124. package/dist/src/proto/google/protobuf/any.js +155 -0
  125. package/dist/src/proto/google/protobuf/any.js.map +1 -0
  126. package/dist/src/proto/google/protobuf/empty.d.ts +32 -0
  127. package/dist/src/proto/google/protobuf/empty.js +34 -0
  128. package/dist/src/proto/google/protobuf/empty.js.map +1 -0
  129. package/dist/src/proto/google/protobuf/timestamp.d.ts +149 -0
  130. package/dist/src/proto/google/protobuf/timestamp.js +136 -0
  131. package/dist/src/proto/google/protobuf/timestamp.js.map +1 -0
  132. package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +320 -0
  133. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +245 -0
  134. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -0
  135. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +1089 -0
  136. package/dist/src/proto/packages/dht/protos/DhtRpc.js +710 -0
  137. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -0
  138. package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +145 -0
  139. package/dist/src/proto/packages/dht/protos/DhtRpc.server.js +3 -0
  140. package/dist/src/proto/packages/dht/protos/DhtRpc.server.js.map +1 -0
  141. package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.d.ts +87 -0
  142. package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.js +66 -0
  143. package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.js.map +1 -0
  144. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.d.ts +156 -0
  145. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js +122 -0
  146. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js.map +1 -0
  147. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.d.ts +524 -0
  148. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js +350 -0
  149. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js.map +1 -0
  150. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.server.d.ts +65 -0
  151. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.server.js +3 -0
  152. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.server.js.map +1 -0
  153. package/dist/test/benchmark/first-message.d.ts +1 -0
  154. package/dist/test/benchmark/first-message.js +137 -0
  155. package/dist/test/benchmark/first-message.js.map +1 -0
  156. package/dist/test/utils/utils.d.ts +12 -0
  157. package/dist/test/utils/utils.js +86 -0
  158. package/dist/test/utils/utils.js.map +1 -0
  159. package/jest.config.js +36 -0
  160. package/karma.config.js +20 -0
  161. package/log.txt +501 -0
  162. package/package.json +53 -0
  163. package/proto.sh +2 -0
  164. package/protos/NetworkRpc.proto +161 -0
  165. package/src/NameDirectory.ts +44 -0
  166. package/src/NetworkNode.ts +169 -0
  167. package/src/NetworkStack.ts +144 -0
  168. package/src/exports.ts +6 -0
  169. package/src/identifiers.ts +1 -0
  170. package/src/logic/DuplicateMessageDetector.ts +167 -0
  171. package/src/logic/ILayer0.ts +14 -0
  172. package/src/logic/IStreamNode.ts +17 -0
  173. package/src/logic/PeerList.ts +106 -0
  174. package/src/logic/RandomGraphNode.ts +310 -0
  175. package/src/logic/Remote.ts +19 -0
  176. package/src/logic/RemoteRandomGraphNode.ts +39 -0
  177. package/src/logic/StreamEntryPointDiscovery.ts +221 -0
  178. package/src/logic/StreamNodeServer.ts +44 -0
  179. package/src/logic/StreamrNode.ts +416 -0
  180. package/src/logic/createRandomGraphNode.ts +114 -0
  181. package/src/logic/inspect/InspectSession.ts +49 -0
  182. package/src/logic/inspect/Inspector.ts +89 -0
  183. package/src/logic/neighbor-discovery/Handshaker.ts +180 -0
  184. package/src/logic/neighbor-discovery/HandshakerServer.ts +99 -0
  185. package/src/logic/neighbor-discovery/NeighborFinder.ts +61 -0
  186. package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +67 -0
  187. package/src/logic/neighbor-discovery/NeighborUpdateManagerServer.ts +61 -0
  188. package/src/logic/neighbor-discovery/RemoteHandshaker.ts +64 -0
  189. package/src/logic/neighbor-discovery/RemoteNeighborUpdateManager.ts +41 -0
  190. package/src/logic/propagation/FifoMapWithTTL.ts +108 -0
  191. package/src/logic/propagation/Propagation.ts +83 -0
  192. package/src/logic/propagation/PropagationTaskStore.ts +40 -0
  193. package/src/logic/protocol-integration/stream-message/ContentMessageTranslator.ts +16 -0
  194. package/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.ts +28 -0
  195. package/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.ts +38 -0
  196. package/src/logic/protocol-integration/stream-message/StreamMessageTranslator.ts +142 -0
  197. package/src/logic/proxy/ProxyStreamConnectionClient.ts +255 -0
  198. package/src/logic/proxy/ProxyStreamConnectionServer.ts +97 -0
  199. package/src/logic/proxy/RemoteProxyServer.ts +36 -0
  200. package/src/logic/temporary-connection/RemoteTemporaryConnectionRpcServer.ts +27 -0
  201. package/src/logic/temporary-connection/TemporaryConnectionRpcServer.ts +50 -0
  202. package/src/logic/utils.ts +17 -0
  203. package/src/proto/google/protobuf/any.ts +319 -0
  204. package/src/proto/google/protobuf/empty.ts +84 -0
  205. package/src/proto/google/protobuf/timestamp.ts +281 -0
  206. package/src/proto/packages/dht/protos/DhtRpc.client.ts +373 -0
  207. package/src/proto/packages/dht/protos/DhtRpc.server.ts +148 -0
  208. package/src/proto/packages/dht/protos/DhtRpc.ts +1399 -0
  209. package/src/proto/packages/proto-rpc/protos/ProtoRpc.ts +108 -0
  210. package/src/proto/packages/trackerless-network/protos/NetworkRpc.client.ts +176 -0
  211. package/src/proto/packages/trackerless-network/protos/NetworkRpc.server.ts +68 -0
  212. package/src/proto/packages/trackerless-network/protos/NetworkRpc.ts +667 -0
  213. package/test/benchmark/first-message.ts +155 -0
  214. package/test/end-to-end/inspect.test.ts +119 -0
  215. package/test/end-to-end/proxy-and-full-node.test.ts +140 -0
  216. package/test/end-to-end/proxy-connections.test.ts +228 -0
  217. package/test/end-to-end/proxy-key-exchange.test.ts +142 -0
  218. package/test/end-to-end/random-graph-with-real-connections.test.ts +154 -0
  219. package/test/end-to-end/webrtc-full-node-network.test.ts +97 -0
  220. package/test/end-to-end/websocket-full-node-network.test.ts +93 -0
  221. package/test/integration/Handshakes.test.ts +167 -0
  222. package/test/integration/Inspect.test.ts +102 -0
  223. package/test/integration/NetworkNode.test.ts +99 -0
  224. package/test/integration/NetworkRpc.test.ts +61 -0
  225. package/test/integration/NetworkStack.test.ts +74 -0
  226. package/test/integration/NetworkStackStoppedDuringStart.test.ts +45 -0
  227. package/test/integration/Propagation.test.ts +79 -0
  228. package/test/integration/RandomGraphNode-Layer1Node-Latencies.test.ts +141 -0
  229. package/test/integration/RandomGraphNode-Layer1Node.test.ts +226 -0
  230. package/test/integration/RemoteHandshaker.test.ts +78 -0
  231. package/test/integration/RemoteNeighborUpdateManager.test.ts +82 -0
  232. package/test/integration/RemoteRandomGraphNode.test.ts +102 -0
  233. package/test/integration/StreamrNode.test.ts +145 -0
  234. package/test/integration/stream-without-default-entrypoints.test.ts +132 -0
  235. package/test/unit/ContentMessageTranslator.test.ts +20 -0
  236. package/test/unit/DuplicateMessageDetector.test.ts +192 -0
  237. package/test/unit/FifoMapWithTtl.test.ts +229 -0
  238. package/test/unit/GroupKeyRequestTranslator.test.ts +36 -0
  239. package/test/unit/GroupKeyResponseTranslator.test.ts +39 -0
  240. package/test/unit/Handshaker.test.ts +63 -0
  241. package/test/unit/HandshakerServer.test.ts +123 -0
  242. package/test/unit/InspectSession.test.ts +78 -0
  243. package/test/unit/Inspector.test.ts +57 -0
  244. package/test/unit/NeighborFinder.test.ts +48 -0
  245. package/test/unit/NumberPair.test.ts +22 -0
  246. package/test/unit/PeerList.test.ts +150 -0
  247. package/test/unit/Propagation.test.ts +134 -0
  248. package/test/unit/RandomGraphNode.test.ts +73 -0
  249. package/test/unit/StreamEntrypointDiscovery.test.ts +152 -0
  250. package/test/unit/StreamMessageTranslator.test.ts +67 -0
  251. package/test/unit/StreamNodeServer.test.ts +63 -0
  252. package/test/unit/StreamrNode.test.ts +74 -0
  253. package/test/utils/mock/MockHandshaker.ts +15 -0
  254. package/test/utils/mock/MockLayer0.ts +71 -0
  255. package/test/utils/mock/MockLayer1.ts +6 -0
  256. package/test/utils/mock/MockNeighborFinder.ts +19 -0
  257. package/test/utils/mock/MockNeighborUpdateManager.ts +21 -0
  258. package/test/utils/mock/Transport.ts +25 -0
  259. package/test/utils/utils.ts +104 -0
  260. package/tsconfig.browser.json +12 -0
  261. package/tsconfig.jest.json +15 -0
  262. package/tsconfig.node.json +18 -0
@@ -0,0 +1,63 @@
1
+ import { Handshaker } from '../../src/logic/neighbor-discovery/Handshaker'
2
+ import { ListeningRpcCommunicator, PeerDescriptor, PeerID, Simulator, SimulatorTransport } from '@streamr/dht'
3
+ import { mockConnectionLocker, createMockRemotePeer } from '../utils/utils'
4
+ import { PeerList } from '../../src/logic/PeerList'
5
+ import { range } from 'lodash'
6
+
7
+ describe('Handshaker', () => {
8
+
9
+ let handshaker: Handshaker
10
+ const peerId = PeerID.fromString('Handshaker')
11
+ const peerDescriptor: PeerDescriptor = {
12
+ kademliaId: peerId.value,
13
+ type: 0
14
+ }
15
+
16
+ const N = 4
17
+ const stream = 'stream#0'
18
+
19
+ let targetNeighbors: PeerList
20
+ let nearbyContactPool: PeerList
21
+ let randomContactPool: PeerList
22
+
23
+ let simulator: Simulator
24
+ let simulatorTransport: SimulatorTransport
25
+
26
+ beforeEach(() => {
27
+ simulator = new Simulator()
28
+ simulatorTransport = new SimulatorTransport(peerDescriptor, simulator)
29
+ const rpcCommunicator = new ListeningRpcCommunicator(stream, simulatorTransport)
30
+
31
+ targetNeighbors = new PeerList(peerId, 10)
32
+ nearbyContactPool = new PeerList(peerId, 20)
33
+ randomContactPool = new PeerList(peerId, 20)
34
+
35
+ handshaker = new Handshaker({
36
+ ownPeerDescriptor: peerDescriptor,
37
+ randomGraphId: stream,
38
+ connectionLocker: mockConnectionLocker,
39
+ targetNeighbors,
40
+ nearbyContactPool,
41
+ randomContactPool,
42
+ rpcCommunicator,
43
+ N
44
+ })
45
+ })
46
+
47
+ afterEach(async () => {
48
+ await simulatorTransport.stop()
49
+ simulator.stop()
50
+ })
51
+
52
+ it('attemptHandshakesOnContact works with empty structures', async () => {
53
+ const res = await handshaker.attemptHandshakesOnContacts([])
54
+ expect(res.length).toEqual(0)
55
+ })
56
+
57
+ it('attemptHandshakesOnContact with known peers that cannot be connected to', async () => {
58
+ range(2).forEach(() => nearbyContactPool.add(createMockRemotePeer()))
59
+ const res = await handshaker.attemptHandshakesOnContacts([])
60
+ expect(res.length).toEqual(2)
61
+ })
62
+
63
+ })
@@ -0,0 +1,123 @@
1
+ import { PeerID } from '@streamr/dht'
2
+ import { HandshakerServer } from '../../src/logic/neighbor-discovery/HandshakerServer'
3
+ import { PeerList } from '../../src/logic/PeerList'
4
+ import { InterleaveNotice, StreamHandshakeRequest } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
5
+ import { createMockRemoteHandshaker, createMockRemotePeer, mockConnectionLocker } from '../utils/utils'
6
+
7
+ describe('HandshakerServer', () => {
8
+
9
+ let handshakerServer: HandshakerServer
10
+
11
+ const peerId = PeerID.fromString('Handshaker')
12
+ const ownPeerDescriptor = {
13
+ kademliaId: peerId.value,
14
+ type: 0
15
+ }
16
+
17
+ let targetNeighbors: PeerList
18
+ let ongoingHandshakes: Set<string>
19
+ let handshakeWithInterleaving: jest.Mock
20
+
21
+ beforeEach(() => {
22
+ targetNeighbors = new PeerList(peerId, 10)
23
+ ongoingHandshakes = new Set()
24
+
25
+ handshakeWithInterleaving = jest.fn()
26
+
27
+ handshakerServer = new HandshakerServer({
28
+ randomGraphId: 'random-graph',
29
+ ownPeerDescriptor,
30
+ connectionLocker: mockConnectionLocker,
31
+ ongoingHandshakes,
32
+ createRemoteHandshaker: (_p) => createMockRemoteHandshaker(),
33
+ createRemoteNode: (_p) => createMockRemotePeer(),
34
+ handshakeWithInterleaving: async (_p, _t) => {
35
+ handshakeWithInterleaving()
36
+ return true
37
+ },
38
+ targetNeighbors,
39
+ N: 4
40
+ })
41
+ })
42
+
43
+ it('handshake', async () => {
44
+ const req = StreamHandshakeRequest.create({
45
+ randomGraphId: 'random-graph',
46
+ senderId: 'senderId',
47
+ requestId: 'requestId',
48
+ senderDescriptor: {
49
+ kademliaId: PeerID.fromString('senderId').value,
50
+ type: 0
51
+ }
52
+ })
53
+ const res = await handshakerServer.handshake(req, {} as any)
54
+ expect(res.accepted).toEqual(true)
55
+ expect(res.interleaveTarget).toBeUndefined()
56
+ expect(res.requestId).toEqual('requestId')
57
+ })
58
+
59
+ it('handshake interleave', async () => {
60
+ targetNeighbors.add(createMockRemotePeer())
61
+ targetNeighbors.add(createMockRemotePeer())
62
+ targetNeighbors.add(createMockRemotePeer())
63
+ targetNeighbors.add(createMockRemotePeer())
64
+ const req = StreamHandshakeRequest.create({
65
+ randomGraphId: 'random-graph',
66
+ senderId: 'senderId',
67
+ requestId: 'requestId',
68
+ senderDescriptor: {
69
+ kademliaId: PeerID.fromString('senderId').value,
70
+ type: 0
71
+ }
72
+ })
73
+ const res = await handshakerServer.handshake(req, {} as any)
74
+ expect(res.accepted).toEqual(true)
75
+ expect(res.interleaveTarget).toBeDefined()
76
+ })
77
+
78
+ it('unaccepted handshake', async () => {
79
+ ongoingHandshakes.add('mock1')
80
+ ongoingHandshakes.add('mock2')
81
+ ongoingHandshakes.add('mock3')
82
+ ongoingHandshakes.add('mock4')
83
+ const req = StreamHandshakeRequest.create({
84
+ randomGraphId: 'random-graph',
85
+ senderId: 'senderId',
86
+ requestId: 'requestId',
87
+ senderDescriptor: {
88
+ kademliaId: PeerID.fromString('senderId').value,
89
+ type: 0
90
+ }
91
+ })
92
+ const res = await handshakerServer.handshake(req, {} as any)
93
+ expect(res.accepted).toEqual(false)
94
+ })
95
+
96
+ it('handshakeWithInterleaving success', async () => {
97
+ const req: InterleaveNotice = {
98
+ randomGraphId: 'random-graph',
99
+ senderId: 'senderId',
100
+ interleaveTarget: {
101
+ kademliaId: PeerID.fromString('interleaveTarget').value,
102
+ type: 0
103
+ }
104
+
105
+ }
106
+ await handshakerServer.interleaveNotice(req, {} as any)
107
+ expect(handshakeWithInterleaving).toHaveBeenCalledTimes(1)
108
+ })
109
+
110
+ it('handshakeWithInterleaving success', async () => {
111
+ const req: InterleaveNotice = {
112
+ randomGraphId: 'wrong-random-graph',
113
+ senderId: 'senderId',
114
+ interleaveTarget: {
115
+ kademliaId: PeerID.fromString('interleaveTarget').value,
116
+ type: 0
117
+ }
118
+ }
119
+ await handshakerServer.interleaveNotice(req, {} as any)
120
+ expect(handshakeWithInterleaving).toHaveBeenCalledTimes(0)
121
+ })
122
+
123
+ })
@@ -0,0 +1,78 @@
1
+ import { PeerIDKey, PeerID } from '@streamr/dht'
2
+ import { InspectSession, Events } from '../../src/logic/inspect/InspectSession'
3
+ import { MessageRef } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
4
+ import { waitForEvent3 } from '../../../utils/dist/src/waitForEvent3'
5
+
6
+ describe('InspectSession', () => {
7
+
8
+ let inspectSession: InspectSession
9
+ let inspectedPeer: PeerIDKey
10
+ let anotherPeer: PeerIDKey
11
+
12
+ const messageRef1: MessageRef = {
13
+ streamId: 'stream',
14
+ messageChainId: 'messageChain0',
15
+ streamPartition: 0,
16
+ sequenceNumber: 0,
17
+ timestamp: 12345,
18
+ publisherId: 'publisher'
19
+ }
20
+
21
+ const messageRef2: MessageRef = {
22
+ streamId: 'stream',
23
+ messageChainId: 'messageChain1',
24
+ streamPartition: 0,
25
+ sequenceNumber: 0,
26
+ timestamp: 12345,
27
+ publisherId: 'publisher'
28
+ }
29
+
30
+ beforeEach(() => {
31
+ inspectedPeer = PeerID.fromString('inspectedPeer').toKey()
32
+ anotherPeer = PeerID.fromString('anotherPeer').toKey()
33
+ inspectSession = new InspectSession({
34
+ inspectedPeer
35
+ })
36
+ })
37
+
38
+ afterEach(() => {
39
+ inspectSession.stop()
40
+ })
41
+
42
+ it('should mark message', () => {
43
+ inspectSession.markMessage(inspectedPeer, messageRef1)
44
+ expect(inspectSession.getInspectedMessageCount()).toBe(1)
45
+ inspectSession.markMessage(inspectedPeer, messageRef2)
46
+ expect(inspectSession.getInspectedMessageCount()).toBe(2)
47
+ })
48
+
49
+ it('should emit done event when inspected peer sends seen message', async () => {
50
+ inspectSession.markMessage(anotherPeer, messageRef1)
51
+ await Promise.all([
52
+ waitForEvent3<Events>(inspectSession, 'done', 100),
53
+ inspectSession.markMessage(inspectedPeer, messageRef1)
54
+ ])
55
+ expect(inspectSession.getInspectedMessageCount()).toBe(1)
56
+ })
57
+
58
+ it('should emit done event another peer sends message after inspected peer', async () => {
59
+ inspectSession.markMessage(inspectedPeer, messageRef1)
60
+ await Promise.all([
61
+ waitForEvent3<Events>(inspectSession, 'done', 100),
62
+ inspectSession.markMessage(anotherPeer, messageRef1)
63
+ ])
64
+ expect(inspectSession.getInspectedMessageCount()).toBe(1)
65
+ })
66
+
67
+ it('should not emit done if messageRefs do not match', async () => {
68
+ inspectSession.markMessage(inspectedPeer, messageRef1)
69
+ await expect(async () => {
70
+ await Promise.all([
71
+ waitForEvent3<Events>(inspectSession, 'done', 100),
72
+ inspectSession.markMessage(anotherPeer, messageRef2)
73
+ ])
74
+ }).rejects.toThrow('waitForEvent3')
75
+
76
+ expect(inspectSession.getInspectedMessageCount()).toBe(2)
77
+ })
78
+ })
@@ -0,0 +1,57 @@
1
+ import { ListeningRpcCommunicator, NodeType, PeerDescriptor, PeerID, keyFromPeerDescriptor } from '@streamr/dht'
2
+ import { Inspector } from '../../src/logic/inspect/Inspector'
3
+ import { mockConnectionLocker } from '../utils/utils'
4
+ import { MockTransport } from '../utils/mock/Transport'
5
+
6
+ describe('Inspector', () => {
7
+
8
+ let inspector: Inspector
9
+ const inspectorPeerId = PeerID.fromString('inspector')
10
+ const inspectorDescriptor: PeerDescriptor = {
11
+ kademliaId: inspectorPeerId.value,
12
+ type: NodeType.NODEJS
13
+ }
14
+
15
+ const inspectedDescriptor: PeerDescriptor = {
16
+ kademliaId: PeerID.fromString('inspected').value,
17
+ type: NodeType.NODEJS
18
+ }
19
+
20
+ const otherPeerKey = PeerID.fromString('other').toKey()
21
+ let mockConnect: jest.Mock
22
+
23
+ const messageRef = {
24
+ streamId: 'stream',
25
+ messageChainId: 'messageChain0',
26
+ streamPartition: 0,
27
+ sequenceNumber: 0,
28
+ timestamp: 12345,
29
+ publisherId: 'publisher'
30
+ }
31
+
32
+ beforeEach(() => {
33
+ mockConnect = jest.fn(() => {})
34
+ inspector = new Inspector({
35
+ ownPeerDescriptor: inspectorDescriptor,
36
+ graphId: 'test',
37
+ rpcCommunicator: new ListeningRpcCommunicator('inspector', new MockTransport()),
38
+ connectionLocker: mockConnectionLocker,
39
+ openInspectConnection: async (_peerDescriptor: PeerDescriptor, _lockId: string) => mockConnect()
40
+ })
41
+ })
42
+
43
+ afterEach(() => {
44
+ inspector.stop()
45
+ })
46
+
47
+ it('Opens inspection connection and runs successfully', async () => {
48
+ setTimeout(() => {
49
+ inspector.markMessage(keyFromPeerDescriptor(inspectedDescriptor), messageRef)
50
+ inspector.markMessage(otherPeerKey, messageRef)
51
+ }, 250)
52
+ await inspector.inspect(inspectedDescriptor)
53
+ expect(inspector.isInspected(keyFromPeerDescriptor(inspectedDescriptor))).toBe(false)
54
+ expect(mockConnect).toBeCalledTimes(1)
55
+ })
56
+
57
+ })
@@ -0,0 +1,48 @@
1
+ import { NeighborFinder } from '../../src/logic/neighbor-discovery/NeighborFinder'
2
+ import { PeerList } from '../../src/logic/PeerList'
3
+ import { keyFromPeerDescriptor, PeerID } from '@streamr/dht'
4
+ import { waitForCondition } from '@streamr/utils'
5
+ import { range } from 'lodash'
6
+ import { expect } from 'expect'
7
+ import { createMockRemotePeer } from '../utils/utils'
8
+
9
+ describe('NeighborFinder', () => {
10
+
11
+ const peerId = PeerID.fromString('NeighborFinder')
12
+ let targetNeighbors: PeerList
13
+ let nearbyContactPool: PeerList
14
+ let neighborFinder: NeighborFinder
15
+
16
+ const N = 4
17
+
18
+ beforeEach(() => {
19
+ targetNeighbors = new PeerList(peerId, 15)
20
+ nearbyContactPool = new PeerList(peerId, 30)
21
+ range(30).forEach(() => nearbyContactPool.add(createMockRemotePeer()))
22
+ const mockDoFindNeighbors = async (excluded: string[]) => {
23
+ const target = nearbyContactPool.getRandom(excluded)
24
+ if (Math.random() < 0.5) {
25
+ targetNeighbors.add(target!)
26
+ } else {
27
+ excluded.push(keyFromPeerDescriptor(target!.getPeerDescriptor()))
28
+ }
29
+ return excluded
30
+ }
31
+ neighborFinder = new NeighborFinder({
32
+ targetNeighbors,
33
+ nearbyContactPool,
34
+ doFindNeighbors: (excluded) => mockDoFindNeighbors(excluded),
35
+ N
36
+ })
37
+ })
38
+
39
+ afterEach(() => {
40
+ neighborFinder.stop()
41
+ })
42
+
43
+ it('Finds target number of peers', async () => {
44
+ neighborFinder.start()
45
+ await waitForCondition(() => targetNeighbors.size() >= N, 10000)
46
+ expect(neighborFinder.isRunning()).toEqual(false)
47
+ })
48
+ })
@@ -0,0 +1,22 @@
1
+ import { NumberPair } from '../../src/logic/DuplicateMessageDetector'
2
+
3
+ test('equalTo', () => {
4
+ expect(new NumberPair(5, 2).equalTo(new NumberPair(5, 3))).toEqual(false)
5
+ expect(new NumberPair(5, 2).equalTo(new NumberPair(5, 2))).toEqual(true)
6
+ })
7
+
8
+ test('greaterThan', () => {
9
+ expect(new NumberPair(5, 2).greaterThan(new NumberPair(6, 2))).toEqual(false)
10
+ expect(new NumberPair(5, 2).greaterThan(new NumberPair(5, 3))).toEqual(false)
11
+ expect(new NumberPair(5, 2).greaterThan(new NumberPair(5, 2))).toEqual(false)
12
+ expect(new NumberPair(5, 2).greaterThan(new NumberPair(5, 1))).toEqual(true)
13
+ expect(new NumberPair(5, 2).greaterThan(new NumberPair(3, 2))).toEqual(true)
14
+ })
15
+
16
+ test('greaterThanOrEqual', () => {
17
+ expect(new NumberPair(5, 2).greaterThanOrEqual(new NumberPair(6, 2))).toEqual(false)
18
+ expect(new NumberPair(5, 2).greaterThanOrEqual(new NumberPair(5, 3))).toEqual(false)
19
+ expect(new NumberPair(5, 2).greaterThanOrEqual(new NumberPair(5, 2))).toEqual(true)
20
+ expect(new NumberPair(5, 2).greaterThanOrEqual(new NumberPair(5, 1))).toEqual(true)
21
+ expect(new NumberPair(5, 2).greaterThanOrEqual(new NumberPair(3, 2))).toEqual(true)
22
+ })
@@ -0,0 +1,150 @@
1
+ import { PeerList } from '../../src/logic/PeerList'
2
+ import { RemoteRandomGraphNode } from '../../src/logic/RemoteRandomGraphNode'
3
+ import {
4
+ PeerDescriptor,
5
+ ListeningRpcCommunicator,
6
+ Simulator,
7
+ PeerID,
8
+ SimulatorTransport,
9
+ keyFromPeerDescriptor
10
+ } from '@streamr/dht'
11
+ import { NetworkRpcClient } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc.client'
12
+ import { toProtoRpcClient } from '@streamr/proto-rpc'
13
+ import { expect } from 'expect'
14
+
15
+ describe('PeerList', () => {
16
+
17
+ const ids = [
18
+ new Uint8Array([1, 1, 1]),
19
+ new Uint8Array([1, 1, 2]),
20
+ new Uint8Array([1, 1, 3]),
21
+ new Uint8Array([1, 1, 4]),
22
+ new Uint8Array([1, 1, 5])
23
+ ]
24
+ const ownId = PeerID.fromString('test')
25
+ const graphId = 'test'
26
+ let peerList: PeerList
27
+ let simulator: Simulator
28
+ let mockTransports: SimulatorTransport[]
29
+
30
+ const createRemoteGraphNode = (peerDescriptor: PeerDescriptor) => {
31
+ const mockTransport = new SimulatorTransport(peerDescriptor, simulator)
32
+ const mockCommunicator = new ListeningRpcCommunicator(`layer2-${ graphId }`, mockTransport)
33
+ const mockClient = mockCommunicator.getRpcClientTransport()
34
+
35
+ mockTransports.push(mockTransport)
36
+ return new RemoteRandomGraphNode(peerDescriptor, graphId, toProtoRpcClient(new NetworkRpcClient(mockClient)))
37
+ }
38
+
39
+ beforeEach(() => {
40
+ simulator = new Simulator()
41
+ mockTransports = []
42
+ peerList = new PeerList(ownId, 6)
43
+ ids.forEach((peerId) => {
44
+ const peerDescriptor: PeerDescriptor = {
45
+ kademliaId: peerId,
46
+ type: 0
47
+ }
48
+ peerList.add(createRemoteGraphNode(peerDescriptor))
49
+ })
50
+ })
51
+
52
+ afterEach(async ()=> {
53
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
54
+ for (let i = 0; i < mockTransports.length; i++) {
55
+ await mockTransports[i].stop()
56
+ }
57
+ simulator.stop()
58
+ })
59
+
60
+ it('add', () => {
61
+ const newDescriptor = {
62
+ kademliaId: new Uint8Array([1, 2, 3]),
63
+ type: 0
64
+ }
65
+ const newNode = createRemoteGraphNode(newDescriptor)
66
+ peerList.add(newNode)
67
+ expect(peerList.hasPeer(newDescriptor)).toEqual(true)
68
+
69
+ const newDescriptor2 = {
70
+ kademliaId: new Uint8Array([1, 2, 4]),
71
+ type: 0
72
+ }
73
+ const newNode2 = createRemoteGraphNode(newDescriptor2)
74
+ peerList.add(newNode2)
75
+ expect(peerList.hasPeer(newDescriptor2)).toEqual(false)
76
+ })
77
+
78
+ it('remove', () => {
79
+ const toRemove = peerList.getClosest([])
80
+ peerList.remove(toRemove!.getPeerDescriptor())
81
+ expect(peerList.hasPeer(toRemove!.getPeerDescriptor())).toEqual(false)
82
+ })
83
+
84
+ it('removeById', () => {
85
+ const toRemove = peerList.getClosest([])
86
+ const stringId = keyFromPeerDescriptor(toRemove!.getPeerDescriptor())
87
+ peerList.removeById(stringId)
88
+ expect(peerList.hasPeer(toRemove!.getPeerDescriptor())).toEqual(false)
89
+ })
90
+
91
+ it('getClosest', () => {
92
+ const closest = peerList.getClosest([])
93
+ expect(keyFromPeerDescriptor(closest!.getPeerDescriptor()))
94
+ .toEqual(PeerID.fromValue(new Uint8Array([1, 1, 1])).toKey())
95
+ })
96
+
97
+ it('getClosest with exclude', () => {
98
+ const closest = peerList.getClosest([PeerID.fromValue(new Uint8Array([1, 1, 1])).toKey()])
99
+ expect(keyFromPeerDescriptor(closest!.getPeerDescriptor()))
100
+ .toEqual(PeerID.fromValue(new Uint8Array([1, 1, 2])).toKey())
101
+ })
102
+
103
+ it('getFurthest', () => {
104
+ const closest = peerList.getFurthest([])
105
+ expect(keyFromPeerDescriptor(closest!.getPeerDescriptor()))
106
+ .toEqual(PeerID.fromValue(new Uint8Array([1, 1, 5])).toKey())
107
+ })
108
+
109
+ it('getFurthest with exclude', () => {
110
+ const closest = peerList.getFurthest([PeerID.fromValue(new Uint8Array([1, 1, 5])).toKey()])
111
+ expect(keyFromPeerDescriptor(closest!.getPeerDescriptor()))
112
+ .toEqual(PeerID.fromValue(new Uint8Array([1, 1, 4])).toKey())
113
+ })
114
+
115
+ it('getClosestAndFurthest', () => {
116
+ const results = peerList.getClosestAndFurthest([])
117
+ expect(results).toEqual([peerList.getClosest([]), peerList.getFurthest([])])
118
+ })
119
+
120
+ it('getClosest empty', () => {
121
+ const emptyPeerList = new PeerList(ownId, 2)
122
+ expect(emptyPeerList.getClosest([])).toBeUndefined()
123
+ })
124
+
125
+ it('getFurthest empty', () => {
126
+ const emptyPeerList = new PeerList(ownId, 2)
127
+ expect(emptyPeerList.getFurthest([])).toBeUndefined()
128
+ })
129
+
130
+ it('getRandom empty', () => {
131
+ const emptyPeerList = new PeerList(ownId, 2)
132
+ expect(emptyPeerList.getRandom([])).toBeUndefined()
133
+ })
134
+
135
+ it('getClosestAndFurthest empty', () => {
136
+ const emptyPeerList = new PeerList(ownId, 2)
137
+ expect(emptyPeerList.getClosestAndFurthest([])).toEqual([])
138
+ })
139
+
140
+ it('getClosestAndFurthest with exclude', () => {
141
+ const results = peerList.getClosestAndFurthest([
142
+ PeerID.fromValue(new Uint8Array([1, 1, 1])).toKey(),
143
+ PeerID.fromValue(new Uint8Array([1, 1, 5])).toKey()
144
+ ])
145
+ expect(results).toEqual([
146
+ peerList.getClosest([PeerID.fromValue(new Uint8Array([1, 1, 1])).toKey()]),
147
+ peerList.getFurthest([PeerID.fromValue(new Uint8Array([1, 1, 5])).toKey()])
148
+ ])
149
+ })
150
+ })
@@ -0,0 +1,134 @@
1
+ import {
2
+ MessageRef,
3
+ StreamMessage,
4
+ StreamMessageType,
5
+ } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
6
+ import { Propagation } from '../../src/logic/propagation/Propagation'
7
+ import { toEthereumAddress, wait } from '@streamr/utils'
8
+
9
+ const PUBLISHER_ID = toEthereumAddress('0x1111111111111111111111111111111111111111')
10
+
11
+ function makeMsg(streamId: string, partition: number, ts: number, msgNo: number): StreamMessage {
12
+ const ref: MessageRef = {
13
+ streamId,
14
+ streamPartition: partition,
15
+ timestamp: ts,
16
+ sequenceNumber: msgNo,
17
+ messageChainId: 'msgChain',
18
+ publisherId: PUBLISHER_ID
19
+ }
20
+ return {
21
+ messageRef: ref,
22
+ content: new Uint8Array([1]),
23
+ signature: 'signature',
24
+ messageType: StreamMessageType.MESSAGE
25
+ }
26
+ }
27
+
28
+ const TTL = 100
29
+
30
+ describe(Propagation, () => {
31
+ let getNeighbors: jest.Mock<ReadonlyArray<string>, [string]>
32
+ let sendToNeighbor: jest.Mock<Promise<void>, [string, StreamMessage]>
33
+ let propagation: Propagation
34
+
35
+ beforeEach(() => {
36
+ getNeighbors = jest.fn()
37
+ sendToNeighbor = jest.fn()
38
+ propagation = new Propagation({
39
+ sendToNeighbor,
40
+ minPropagationTargets: 3,
41
+ ttl: TTL,
42
+ maxMessages: 5
43
+ })
44
+ })
45
+
46
+ describe('#feedUnseenMessage', () => {
47
+ it('message is propagated to nodes returned by getNeighbors', () => {
48
+ getNeighbors.mockReturnValueOnce(['n1', 'n2', 'n3'])
49
+ const msg = makeMsg('s1', 0, 1000, 1)
50
+ propagation.feedUnseenMessage(msg, [...getNeighbors('s1#0')], null)
51
+
52
+ expect(sendToNeighbor).toHaveBeenCalledTimes(3)
53
+ expect(sendToNeighbor).toHaveBeenNthCalledWith(1, 'n1', msg)
54
+ expect(sendToNeighbor).toHaveBeenNthCalledWith(2, 'n2', msg)
55
+ expect(sendToNeighbor).toHaveBeenNthCalledWith(3, 'n3', msg)
56
+ })
57
+
58
+ it('message does not get propagated to source node (if present in getNeighbors)', () => {
59
+ getNeighbors.mockReturnValueOnce(['n1', 'n2', 'n3'])
60
+ const msg = makeMsg('s1', 0, 1000, 1)
61
+ propagation.feedUnseenMessage(msg, [...getNeighbors('s1#0')], 'n2')
62
+
63
+ expect(sendToNeighbor).toHaveBeenCalledTimes(2)
64
+ expect(sendToNeighbor).toHaveBeenNthCalledWith(1, 'n1', msg)
65
+ expect(sendToNeighbor).toHaveBeenNthCalledWith(2, 'n3', msg)
66
+ })
67
+ })
68
+
69
+ describe('#onNeighborJoined', () => {
70
+ let msg: StreamMessage
71
+
72
+ async function setUpAndFeed(neighbors: string[]): Promise<void> {
73
+ getNeighbors.mockReturnValueOnce(neighbors)
74
+ msg = makeMsg('s1', 0, 1000, 1)
75
+ propagation.feedUnseenMessage(msg, [...getNeighbors('s1#0')], 'n2')
76
+ await wait(0)
77
+ sendToNeighbor.mockClear()
78
+ getNeighbors.mockClear()
79
+ }
80
+
81
+ it('sends to new neighbor', async () => {
82
+ await setUpAndFeed(['n1', 'n2', 'n3'])
83
+ propagation.onNeighborJoined('n4')
84
+ expect(sendToNeighbor).toHaveBeenCalledTimes(1)
85
+ expect(sendToNeighbor).toHaveBeenNthCalledWith(1, 'n4', msg)
86
+ })
87
+
88
+ it('sends to previously failed neighbor', async () => {
89
+ sendToNeighbor.mockImplementation(async (neighbor) => {
90
+ if (neighbor === 'n3') {
91
+ throw new Error('failed to send')
92
+ }
93
+ })
94
+ await setUpAndFeed(['n1', 'n2', 'n3'])
95
+ propagation.onNeighborJoined('n3')
96
+ expect(sendToNeighbor).toHaveBeenCalledTimes(1)
97
+ expect(sendToNeighbor).toHaveBeenNthCalledWith(1, 'n3', msg)
98
+ })
99
+
100
+ it('no-op if passed source node', async () => {
101
+ await setUpAndFeed(['n1', 'n2', 'n3'])
102
+ propagation.onNeighborJoined('n2')
103
+ expect(sendToNeighbor).toHaveBeenCalledTimes(0)
104
+ })
105
+
106
+ it('no-op if passed already handled neighbor', async () => {
107
+ await setUpAndFeed(['n1', 'n2', 'n3'])
108
+ propagation.onNeighborJoined('n3')
109
+ expect(sendToNeighbor).toHaveBeenCalledTimes(0)
110
+ })
111
+
112
+ it('no-op if initially `minPropagationTargets` were propagated to', async () => {
113
+ await setUpAndFeed(['n1', 'n2', 'n3', 'n4'])
114
+ propagation.onNeighborJoined('n5')
115
+ expect(sendToNeighbor).toHaveBeenCalledTimes(0)
116
+ })
117
+
118
+ it('no-op if later `minPropagationTargets` have been propagated to', async () => {
119
+ await setUpAndFeed(['n1', 'n2', 'n3'])
120
+ propagation.onNeighborJoined('n4')
121
+ await wait(0)
122
+ sendToNeighbor.mockClear()
123
+ propagation.onNeighborJoined('n5')
124
+ expect(sendToNeighbor).toHaveBeenCalledTimes(0)
125
+ })
126
+
127
+ it('no-op if TTL expires', async () => {
128
+ await setUpAndFeed(['n1', 'n2', 'n3'])
129
+ await wait(200)
130
+ propagation.onNeighborJoined('n3')
131
+ expect(sendToNeighbor).toHaveBeenCalledTimes(0)
132
+ })
133
+ })
134
+ })