@libp2p/interface-compliance-tests 1.1.14 → 1.1.17

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 (146) hide show
  1. package/dist/src/connection-encrypter/index.d.ts +5 -0
  2. package/dist/src/connection-encrypter/index.d.ts.map +1 -0
  3. package/dist/src/{crypto → connection-encrypter}/index.js +2 -2
  4. package/dist/src/connection-encrypter/index.js.map +1 -0
  5. package/dist/src/{crypto → connection-encrypter}/utils/index.d.ts +0 -0
  6. package/dist/src/connection-encrypter/utils/index.d.ts.map +1 -0
  7. package/dist/src/{crypto → connection-encrypter}/utils/index.js +0 -0
  8. package/dist/src/connection-encrypter/utils/index.js.map +1 -0
  9. package/dist/src/mocks/connection-encrypter.d.ts +3 -0
  10. package/dist/src/mocks/connection-encrypter.d.ts.map +1 -0
  11. package/dist/src/mocks/connection-encrypter.js +93 -0
  12. package/dist/src/mocks/connection-encrypter.js.map +1 -0
  13. package/dist/src/mocks/connection-manager.d.ts +6 -3
  14. package/dist/src/mocks/connection-manager.d.ts.map +1 -1
  15. package/dist/src/mocks/connection-manager.js +9 -0
  16. package/dist/src/mocks/connection-manager.js.map +1 -1
  17. package/dist/src/mocks/connection.d.ts +1 -1
  18. package/dist/src/mocks/connection.d.ts.map +1 -1
  19. package/dist/src/mocks/connection.js +68 -49
  20. package/dist/src/mocks/connection.js.map +1 -1
  21. package/dist/src/mocks/duplex.d.ts +3 -0
  22. package/dist/src/mocks/duplex.d.ts.map +1 -0
  23. package/dist/src/mocks/duplex.js +7 -0
  24. package/dist/src/mocks/duplex.js.map +1 -0
  25. package/dist/src/mocks/index.d.ts +3 -2
  26. package/dist/src/mocks/index.d.ts.map +1 -1
  27. package/dist/src/mocks/index.js +2 -1
  28. package/dist/src/mocks/index.js.map +1 -1
  29. package/dist/src/mocks/multiaddr-connection.d.ts +12 -0
  30. package/dist/src/mocks/multiaddr-connection.d.ts.map +1 -1
  31. package/dist/src/mocks/multiaddr-connection.js +37 -0
  32. package/dist/src/mocks/multiaddr-connection.js.map +1 -1
  33. package/dist/src/mocks/muxer.d.ts +8 -2
  34. package/dist/src/mocks/muxer.d.ts.map +1 -1
  35. package/dist/src/mocks/muxer.js +22 -13
  36. package/dist/src/mocks/muxer.js.map +1 -1
  37. package/dist/src/mocks/registrar.d.ts +6 -6
  38. package/dist/src/mocks/registrar.d.ts.map +1 -1
  39. package/dist/src/mocks/registrar.js +23 -33
  40. package/dist/src/mocks/registrar.js.map +1 -1
  41. package/dist/src/mocks/upgrader.d.ts +11 -3
  42. package/dist/src/mocks/upgrader.d.ts.map +1 -1
  43. package/dist/src/mocks/upgrader.js +28 -23
  44. package/dist/src/mocks/upgrader.js.map +1 -1
  45. package/dist/src/pubsub/api.d.ts +3 -4
  46. package/dist/src/pubsub/api.d.ts.map +1 -1
  47. package/dist/src/pubsub/api.js +8 -3
  48. package/dist/src/pubsub/api.js.map +1 -1
  49. package/dist/src/pubsub/connection-handlers.d.ts +3 -4
  50. package/dist/src/pubsub/connection-handlers.d.ts.map +1 -1
  51. package/dist/src/pubsub/connection-handlers.js +41 -16
  52. package/dist/src/pubsub/connection-handlers.js.map +1 -1
  53. package/dist/src/pubsub/emit-self.d.ts +3 -4
  54. package/dist/src/pubsub/emit-self.d.ts.map +1 -1
  55. package/dist/src/pubsub/emit-self.js +15 -6
  56. package/dist/src/pubsub/emit-self.js.map +1 -1
  57. package/dist/src/pubsub/index.d.ts +8 -3
  58. package/dist/src/pubsub/index.d.ts.map +1 -1
  59. package/dist/src/pubsub/index.js.map +1 -1
  60. package/dist/src/pubsub/messages.d.ts +3 -4
  61. package/dist/src/pubsub/messages.d.ts.map +1 -1
  62. package/dist/src/pubsub/messages.js +13 -6
  63. package/dist/src/pubsub/messages.js.map +1 -1
  64. package/dist/src/pubsub/multiple-nodes.d.ts +3 -4
  65. package/dist/src/pubsub/multiple-nodes.d.ts.map +1 -1
  66. package/dist/src/pubsub/multiple-nodes.js +57 -24
  67. package/dist/src/pubsub/multiple-nodes.js.map +1 -1
  68. package/dist/src/pubsub/two-nodes.d.ts +3 -4
  69. package/dist/src/pubsub/two-nodes.d.ts.map +1 -1
  70. package/dist/src/pubsub/two-nodes.js +16 -7
  71. package/dist/src/pubsub/two-nodes.js.map +1 -1
  72. package/dist/src/pubsub/utils.d.ts +2 -2
  73. package/dist/src/pubsub/utils.js +1 -1
  74. package/dist/src/pubsub/utils.js.map +1 -1
  75. package/dist/src/stream-muxer/base-test.d.ts +2 -2
  76. package/dist/src/stream-muxer/base-test.d.ts.map +1 -1
  77. package/dist/src/stream-muxer/base-test.js +17 -8
  78. package/dist/src/stream-muxer/base-test.js.map +1 -1
  79. package/dist/src/stream-muxer/close-test.d.ts +2 -2
  80. package/dist/src/stream-muxer/close-test.d.ts.map +1 -1
  81. package/dist/src/stream-muxer/close-test.js +9 -4
  82. package/dist/src/stream-muxer/close-test.js.map +1 -1
  83. package/dist/src/stream-muxer/index.d.ts +2 -2
  84. package/dist/src/stream-muxer/index.d.ts.map +1 -1
  85. package/dist/src/stream-muxer/index.js.map +1 -1
  86. package/dist/src/stream-muxer/mega-stress-test.d.ts +2 -2
  87. package/dist/src/stream-muxer/mega-stress-test.d.ts.map +1 -1
  88. package/dist/src/stream-muxer/mega-stress-test.js +5 -1
  89. package/dist/src/stream-muxer/mega-stress-test.js.map +1 -1
  90. package/dist/src/stream-muxer/spawner.d.ts +2 -2
  91. package/dist/src/stream-muxer/spawner.d.ts.map +1 -1
  92. package/dist/src/stream-muxer/spawner.js.map +1 -1
  93. package/dist/src/stream-muxer/stress-test.d.ts +2 -2
  94. package/dist/src/stream-muxer/stress-test.d.ts.map +1 -1
  95. package/dist/src/stream-muxer/stress-test.js +5 -1
  96. package/dist/src/stream-muxer/stress-test.js.map +1 -1
  97. package/dist/src/transport/dial-test.d.ts +2 -2
  98. package/dist/src/transport/dial-test.d.ts.map +1 -1
  99. package/dist/src/transport/dial-test.js +17 -9
  100. package/dist/src/transport/dial-test.js.map +1 -1
  101. package/dist/src/transport/filter-test.d.ts +2 -2
  102. package/dist/src/transport/filter-test.d.ts.map +1 -1
  103. package/dist/src/transport/filter-test.js +1 -2
  104. package/dist/src/transport/filter-test.js.map +1 -1
  105. package/dist/src/transport/index.d.ts +3 -6
  106. package/dist/src/transport/index.d.ts.map +1 -1
  107. package/dist/src/transport/index.js.map +1 -1
  108. package/dist/src/transport/listen-test.d.ts +2 -2
  109. package/dist/src/transport/listen-test.d.ts.map +1 -1
  110. package/dist/src/transport/listen-test.js +34 -17
  111. package/dist/src/transport/listen-test.js.map +1 -1
  112. package/package.json +10 -10
  113. package/src/{crypto → connection-encrypter}/index.ts +5 -5
  114. package/src/{crypto → connection-encrypter}/utils/index.ts +0 -0
  115. package/src/mocks/connection-encrypter.ts +110 -0
  116. package/src/mocks/connection-manager.ts +15 -3
  117. package/src/mocks/connection.ts +104 -57
  118. package/src/mocks/duplex.ts +8 -0
  119. package/src/mocks/index.ts +3 -2
  120. package/src/mocks/multiaddr-connection.ts +47 -0
  121. package/src/mocks/muxer.ts +32 -22
  122. package/src/mocks/registrar.ts +30 -40
  123. package/src/mocks/upgrader.ts +33 -23
  124. package/src/pubsub/api.ts +15 -10
  125. package/src/pubsub/connection-handlers.ts +64 -39
  126. package/src/pubsub/emit-self.ts +21 -13
  127. package/src/pubsub/index.ts +9 -3
  128. package/src/pubsub/messages.ts +23 -14
  129. package/src/pubsub/multiple-nodes.ts +75 -42
  130. package/src/pubsub/two-nodes.ts +29 -20
  131. package/src/pubsub/utils.ts +4 -4
  132. package/src/stream-muxer/base-test.ts +19 -10
  133. package/src/stream-muxer/close-test.ts +11 -6
  134. package/src/stream-muxer/index.ts +2 -2
  135. package/src/stream-muxer/mega-stress-test.ts +7 -3
  136. package/src/stream-muxer/spawner.ts +2 -2
  137. package/src/stream-muxer/stress-test.ts +7 -3
  138. package/src/transport/dial-test.ts +21 -13
  139. package/src/transport/filter-test.ts +4 -5
  140. package/src/transport/index.ts +3 -7
  141. package/src/transport/listen-test.ts +39 -22
  142. package/dist/src/crypto/index.d.ts +0 -5
  143. package/dist/src/crypto/index.d.ts.map +0 -1
  144. package/dist/src/crypto/index.js.map +0 -1
  145. package/dist/src/crypto/utils/index.d.ts.map +0 -1
  146. package/dist/src/crypto/utils/index.js.map +0 -1
@@ -4,16 +4,16 @@ import * as PeerIdFactory from '@libp2p/peer-id-factory'
4
4
  import all from 'it-all'
5
5
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
6
6
  import peers from '../utils/peers.js'
7
- import { UnexpectedPeerError } from '@libp2p/interfaces/crypto/errors'
7
+ import { UnexpectedPeerError } from '@libp2p/interfaces/connection-encrypter/errors'
8
8
  import { createMaConnPair } from './utils/index.js'
9
9
  import type { TestSetup } from '../index.js'
10
- import type { Crypto } from '@libp2p/interfaces/crypto'
10
+ import type { ConnectionEncrypter } from '@libp2p/interfaces/connection-encrypter'
11
11
  import type { PeerId } from '@libp2p/interfaces/peer-id'
12
12
  import type { Source } from 'it-stream-types'
13
13
 
14
- export default (common: TestSetup<Crypto>) => {
15
- describe('interface-crypto compliance tests', () => {
16
- let crypto: Crypto
14
+ export default (common: TestSetup<ConnectionEncrypter>) => {
15
+ describe('interface-connection-encrypter compliance tests', () => {
16
+ let crypto: ConnectionEncrypter
17
17
  let localPeer: PeerId
18
18
  let remotePeer: PeerId
19
19
  let mitmPeer: PeerId
@@ -0,0 +1,110 @@
1
+ import { peerIdFromBytes } from '@libp2p/peer-id'
2
+ import { handshake } from 'it-handshake'
3
+ import { duplexPair } from 'it-pair/duplex'
4
+ import { pipe } from 'it-pipe'
5
+ import { UnexpectedPeerError } from '@libp2p/interfaces/connection-encrypter/errors'
6
+ import { Multiaddr } from '@multiformats/multiaddr'
7
+ import type { ConnectionEncrypter } from '@libp2p/interfaces/connection-encrypter'
8
+ import type { Transform, Source } from 'it-stream-types'
9
+
10
+ // A basic transform that does nothing to the data
11
+ const transform = (): Transform<Uint8Array, Uint8Array> => {
12
+ return (source: Source<Uint8Array>) => (async function * () {
13
+ for await (const chunk of source) {
14
+ yield chunk
15
+ }
16
+ })()
17
+ }
18
+
19
+ export function mockConnectionEncrypter () {
20
+ const encrypter: ConnectionEncrypter = {
21
+ protocol: 'insecure',
22
+ secureInbound: async (localPeer, duplex, expectedPeer) => {
23
+ // 1. Perform a basic handshake.
24
+ const shake = handshake(duplex)
25
+ shake.write(localPeer.toBytes())
26
+ const remoteId = await shake.read()
27
+
28
+ if (remoteId == null) {
29
+ throw new Error('Could not read remote ID')
30
+ }
31
+
32
+ const remotePeer = peerIdFromBytes(remoteId.slice())
33
+ shake.rest()
34
+
35
+ if (expectedPeer != null && !expectedPeer.equals(remotePeer)) {
36
+ throw new UnexpectedPeerError()
37
+ }
38
+
39
+ // 2. Create your encryption box/unbox wrapper
40
+ const wrapper = duplexPair<Uint8Array>()
41
+ const encrypt = transform() // Use transform iterables to modify data
42
+ const decrypt = transform()
43
+
44
+ void pipe(
45
+ wrapper[0], // We write to wrapper
46
+ encrypt, // The data is encrypted
47
+ shake.stream, // It goes to the remote peer
48
+ decrypt, // Decrypt the incoming data
49
+ wrapper[0] // Pipe to the wrapper
50
+ )
51
+
52
+ return {
53
+ conn: {
54
+ ...wrapper[1],
55
+ close: async () => {},
56
+ localAddr: new Multiaddr('/ip4/127.0.0.1/tcp/4001'),
57
+ remoteAddr: new Multiaddr('/ip4/127.0.0.1/tcp/4002'),
58
+ timeline: {
59
+ open: Date.now()
60
+ },
61
+ conn: true
62
+ },
63
+ remotePeer,
64
+ remoteEarlyData: new Uint8Array(0)
65
+ }
66
+ },
67
+ secureOutbound: async (localPeer, duplex, remotePeer) => {
68
+ // 1. Perform a basic handshake.
69
+ const shake = handshake(duplex)
70
+ shake.write(localPeer.toBytes())
71
+ const remoteId = await shake.read()
72
+
73
+ if (remoteId == null) {
74
+ throw new Error('Could not read remote ID')
75
+ }
76
+
77
+ shake.rest()
78
+
79
+ // 2. Create your encryption box/unbox wrapper
80
+ const wrapper = duplexPair<Uint8Array>()
81
+ const encrypt = transform()
82
+ const decrypt = transform()
83
+
84
+ void pipe(
85
+ wrapper[0], // We write to wrapper
86
+ encrypt, // The data is encrypted
87
+ shake.stream, // It goes to the remote peer
88
+ decrypt, // Decrypt the incoming data
89
+ wrapper[0] // Pipe to the wrapper
90
+ )
91
+
92
+ return {
93
+ conn: {
94
+ ...wrapper[1],
95
+ close: async () => {},
96
+ localAddr: new Multiaddr('/ip4/127.0.0.1/tcp/4001'),
97
+ remoteAddr: new Multiaddr('/ip4/127.0.0.1/tcp/4002'),
98
+ timeline: {
99
+ open: Date.now()
100
+ },
101
+ conn: true
102
+ },
103
+ remotePeer: peerIdFromBytes(remoteId.slice()),
104
+ remoteEarlyData: new Uint8Array(0)
105
+ }
106
+ }
107
+ }
108
+
109
+ return encrypter
110
+ }
@@ -1,9 +1,21 @@
1
1
  import { EventEmitter } from '@libp2p/interfaces'
2
- import type { Connection } from '@libp2p/interfaces/src/connection'
3
- import type { PeerId } from '@libp2p/interfaces/src/peer-id'
4
- import type { ConnectionManager, ConnectionManagerEvents } from '@libp2p/interfaces/src/registrar'
2
+ import type { Connection } from '@libp2p/interfaces/connection'
3
+ import type { PeerId } from '@libp2p/interfaces/peer-id'
4
+ import type { ConnectionManager, ConnectionManagerEvents } from '@libp2p/interfaces/registrar'
5
5
 
6
6
  class MockConnectionManager extends EventEmitter<ConnectionManagerEvents> implements ConnectionManager {
7
+ getConnectionMap (): Map<string, Connection[]> {
8
+ throw new Error('Method not implemented.')
9
+ }
10
+
11
+ getConnectionList (): Connection[] {
12
+ throw new Error('Method not implemented.')
13
+ }
14
+
15
+ getConnections (): Connection[] {
16
+ throw new Error('Method not implemented.')
17
+ }
18
+
7
19
  getConnection (peerId: PeerId): Connection | undefined {
8
20
  throw new Error('Method not implemented.')
9
21
  }
@@ -2,16 +2,19 @@ import { peerIdFromString } from '@libp2p/peer-id'
2
2
  import { pipe } from 'it-pipe'
3
3
  import { duplexPair } from 'it-pair/duplex'
4
4
  import type { MultiaddrConnection } from '@libp2p/interfaces/transport'
5
- import type { Connection, Stream, Metadata, ProtocolStream } from '@libp2p/interfaces/connection'
5
+ import type { Connection, Stream, Metadata, ProtocolStream, ConnectionStat } from '@libp2p/interfaces/connection'
6
6
  import type { Duplex } from 'it-stream-types'
7
7
  import { mockMuxer } from './muxer.js'
8
- import type { PeerId } from '@libp2p/interfaces/src/peer-id'
8
+ import type { PeerId } from '@libp2p/interfaces/peer-id'
9
9
  import { mockMultiaddrConnection } from './multiaddr-connection.js'
10
10
  import type { Registrar } from '@libp2p/interfaces/registrar'
11
11
  import { mockRegistrar } from './registrar.js'
12
12
  import { Dialer, Listener } from '@libp2p/multistream-select'
13
13
  import { logger } from '@libp2p/logger'
14
- import { CustomEvent } from '@libp2p/interfaces'
14
+ import * as STATUS from '@libp2p/interfaces/connection/status'
15
+ import type { Multiaddr } from '@multiformats/multiaddr'
16
+ import type { StreamMuxer } from '@libp2p/interfaces/stream-muxer'
17
+ import { Components } from '@libp2p/interfaces/components'
15
18
 
16
19
  const log = logger('libp2p:mock-connection')
17
20
 
@@ -20,6 +23,96 @@ export interface MockConnectionOptions {
20
23
  registrar?: Registrar
21
24
  }
22
25
 
26
+ interface MockConnectionInit {
27
+ remoteAddr: Multiaddr
28
+ remotePeer: PeerId
29
+ direction: 'inbound' | 'outbound'
30
+ maConn: MultiaddrConnection
31
+ muxer: StreamMuxer
32
+ }
33
+
34
+ class MockConnection implements Connection {
35
+ public id: string
36
+ public remoteAddr: Multiaddr
37
+ public remotePeer: PeerId
38
+ public direction: 'inbound' | 'outbound'
39
+ public stat: ConnectionStat
40
+ public registry: Map<string, Metadata>
41
+ public streams: Stream[]
42
+ public tags: string[]
43
+
44
+ private readonly muxer: StreamMuxer
45
+ private readonly maConn: MultiaddrConnection
46
+
47
+ constructor (init: MockConnectionInit) {
48
+ const { remoteAddr, remotePeer, direction, maConn, muxer } = init
49
+
50
+ this.id = `mock-connection-${Math.random()}`
51
+ this.remoteAddr = remoteAddr
52
+ this.remotePeer = remotePeer
53
+ this.direction = direction
54
+ this.stat = {
55
+ status: STATUS.OPEN,
56
+ direction,
57
+ timeline: maConn.timeline,
58
+ multiplexer: 'test-multiplexer',
59
+ encryption: 'yes-yes-very-secure'
60
+ }
61
+ this.registry = new Map()
62
+ this.streams = []
63
+ this.tags = []
64
+ this.muxer = muxer
65
+ this.maConn = maConn
66
+ }
67
+
68
+ async newStream (protocols: string | string[]) {
69
+ if (!Array.isArray(protocols)) {
70
+ protocols = [protocols]
71
+ }
72
+
73
+ if (protocols.length === 0) {
74
+ throw new Error('protocols must have a length')
75
+ }
76
+
77
+ const id = `${Math.random()}`
78
+ const stream: Stream = this.muxer.newStream(id)
79
+ const mss = new Dialer(stream)
80
+ const result = await mss.select(protocols)
81
+
82
+ const streamData: ProtocolStream = {
83
+ protocol: result.protocol,
84
+ stream: {
85
+ ...stream,
86
+ ...result.stream
87
+ }
88
+ }
89
+
90
+ this.addStream(stream, { protocol: result.protocol, metadata: {} })
91
+
92
+ return streamData
93
+ }
94
+
95
+ addStream (stream: Stream, metadata: Partial<Metadata>) {
96
+ this.registry.set(stream.id, {
97
+ protocol: metadata.protocol ?? '',
98
+ metadata: metadata.metadata ?? {}
99
+ })
100
+
101
+ this.streams.push(stream)
102
+ }
103
+
104
+ removeStream (id: string) {
105
+ this.registry.delete(id)
106
+ this.streams = this.streams.filter(stream => stream.id !== id)
107
+ }
108
+
109
+ async close () {
110
+ this.stat.status = STATUS.CLOSING
111
+ await this.maConn.close()
112
+ this.stat.status = STATUS.CLOSED
113
+ }
114
+ }
115
+
23
116
  export function mockConnection (maConn: MultiaddrConnection, opts: MockConnectionOptions = {}): Connection {
24
117
  const remoteAddr = maConn.remoteAddr
25
118
  const remotePeerIdStr = remoteAddr.getPeerId() ?? '12D3KooWCrhmFM1BCPGBkNzbPfDk4cjYmtAYSpZwUBC69Qg2kZyq'
@@ -29,12 +122,11 @@ export function mockConnection (maConn: MultiaddrConnection, opts: MockConnectio
29
122
  }
30
123
 
31
124
  const remotePeer = peerIdFromString(remotePeerIdStr)
32
- const registry = new Map()
33
- const streams: Stream[] = []
34
125
  const direction = opts.direction ?? 'inbound'
35
126
  const registrar = opts.registrar ?? mockRegistrar()
127
+ const muxerFactory = mockMuxer()
36
128
 
37
- const muxer = mockMuxer({
129
+ const muxer = muxerFactory.createStreamMuxer(new Components(), {
38
130
  onIncomingStream: (muxedStream) => {
39
131
  const mss = new Listener(muxedStream)
40
132
  try {
@@ -46,9 +138,7 @@ export function mockConnection (maConn: MultiaddrConnection, opts: MockConnectio
46
138
  connection.addStream(muxedStream, { protocol, metadata: {} })
47
139
  const handler = registrar.getHandler(protocol)
48
140
 
49
- handler(new CustomEvent('incomingStream', {
50
- detail: { connection, stream: muxedStream, protocol }
51
- }))
141
+ handler({ connection, stream: muxedStream, protocol })
52
142
  }).catch(err => {
53
143
  log.error(err)
54
144
  })
@@ -65,56 +155,13 @@ export function mockConnection (maConn: MultiaddrConnection, opts: MockConnectio
65
155
  maConn, muxer, maConn
66
156
  )
67
157
 
68
- const connection: Connection = {
69
- id: 'mock-connection',
158
+ const connection = new MockConnection({
70
159
  remoteAddr,
71
160
  remotePeer,
72
- stat: {
73
- status: 'OPEN',
74
- direction,
75
- timeline: maConn.timeline,
76
- multiplexer: 'test-multiplexer',
77
- encryption: 'yes-yes-very-secure'
78
- },
79
- registry,
80
- tags: [],
81
- streams,
82
- newStream: async (protocols) => {
83
- if (!Array.isArray(protocols)) {
84
- protocols = [protocols]
85
- }
86
-
87
- if (protocols.length === 0) {
88
- throw new Error('protocols must have a length')
89
- }
90
-
91
- const id = `${Math.random()}`
92
- const stream: Stream = muxer.newStream(id)
93
- const mss = new Dialer(stream)
94
- const result = await mss.select(protocols)
95
-
96
- const streamData: ProtocolStream = {
97
- protocol: result.protocol,
98
- stream: {
99
- ...stream,
100
- ...result.stream
101
- }
102
- }
103
-
104
- registry.set(id, streamData)
105
-
106
- return streamData
107
- },
108
- addStream: (stream: Stream, metadata: Metadata) => {
109
-
110
- },
111
- removeStream: (id: string) => {
112
- registry.delete(id)
113
- },
114
- close: async () => {
115
- await maConn.close()
116
- }
117
- }
161
+ direction,
162
+ maConn,
163
+ muxer
164
+ })
118
165
 
119
166
  return connection
120
167
  }
@@ -0,0 +1,8 @@
1
+ import type { Duplex } from 'it-stream-types'
2
+
3
+ export function mockDuplex (): Duplex<Uint8Array> {
4
+ return {
5
+ source: [],
6
+ sink: async () => {}
7
+ }
8
+ }
@@ -2,8 +2,9 @@
2
2
  export { mockConnectionGater } from './connection-gater.js'
3
3
  export { mockConnectionManager } from './connection-manager.js'
4
4
  export { mockConnection, mockStream, connectionPair } from './connection.js'
5
- export { mockMultiaddrConnection } from './multiaddr-connection.js'
5
+ export { mockMultiaddrConnection, mockMultiaddrConnPair } from './multiaddr-connection.js'
6
6
  export { mockMuxer } from './muxer.js'
7
7
  export { mockRegistrar } from './registrar.js'
8
8
  export { mockUpgrader } from './upgrader.js'
9
- export type { MockUpgraderOptions } from './upgrader.js'
9
+ export { mockDuplex } from './duplex.js'
10
+ export type { MockUpgraderInit } from './upgrader.js'
@@ -1,4 +1,6 @@
1
1
  import { Multiaddr } from '@multiformats/multiaddr'
2
+ import { duplexPair } from 'it-pair/duplex'
3
+ import { abortableSource } from 'abortable-iterator'
2
4
  import type { MultiaddrConnection } from '@libp2p/interfaces/transport'
3
5
  import type { Duplex } from 'it-stream-types'
4
6
  import type { PeerId } from '@libp2p/interfaces/peer-id'
@@ -17,3 +19,48 @@ export function mockMultiaddrConnection (source: Duplex<Uint8Array> & Partial<Mu
17
19
 
18
20
  return maConn
19
21
  }
22
+
23
+ export interface MockMultiaddrConnPairOptions {
24
+ addrs: Multiaddr[]
25
+ remotePeer: PeerId
26
+ }
27
+
28
+ /**
29
+ * Returns both sides of a mocked MultiaddrConnection
30
+ */
31
+ export function mockMultiaddrConnPair (opts: MockMultiaddrConnPairOptions): { inbound: MultiaddrConnection, outbound: MultiaddrConnection } {
32
+ const { addrs, remotePeer } = opts
33
+ const controller = new AbortController()
34
+ const [localAddr, remoteAddr] = addrs
35
+ const [inboundStream, outboundStream] = duplexPair<Uint8Array>()
36
+
37
+ const outbound: MultiaddrConnection = {
38
+ ...outboundStream,
39
+ remoteAddr: remoteAddr.encapsulate(`/p2p/${remotePeer.toString()}`),
40
+ timeline: {
41
+ open: Date.now()
42
+ },
43
+ close: async () => {
44
+ outbound.timeline.close = Date.now()
45
+ controller.abort()
46
+ }
47
+ }
48
+
49
+ const inbound: MultiaddrConnection = {
50
+ ...inboundStream,
51
+ remoteAddr: localAddr,
52
+ timeline: {
53
+ open: Date.now()
54
+ },
55
+ close: async () => {
56
+ inbound.timeline.close = Date.now()
57
+ controller.abort()
58
+ }
59
+ }
60
+
61
+ // Make the sources abortable so we can close them easily
62
+ inbound.source = abortableSource(inbound.source, controller.signal)
63
+ outbound.source = abortableSource(outbound.source, controller.signal)
64
+
65
+ return { inbound, outbound }
66
+ }
@@ -7,10 +7,11 @@ import errCode from 'err-code'
7
7
  import { Logger, logger } from '@libp2p/logger'
8
8
  import * as ndjson from 'it-ndjson'
9
9
  import type { Stream } from '@libp2p/interfaces/connection'
10
- import type { Muxer, MuxerOptions } from '@libp2p/interfaces/stream-muxer'
10
+ import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer'
11
11
  import type { Source } from 'it-stream-types'
12
12
  import { pipe } from 'it-pipe'
13
13
  import map from 'it-map'
14
+ import type { Components } from '@libp2p/interfaces/components'
14
15
 
15
16
  let muxers = 0
16
17
  let streams = 0
@@ -54,8 +55,8 @@ class MuxedStream {
54
55
  private readonly resetController: AbortController
55
56
  private readonly log: Logger
56
57
 
57
- constructor (opts: { id: string, type: 'initiator' | 'recipient', push: Pushable<StreamMessage>, onEnd: (err?: Error) => void }) {
58
- const { id, type, push, onEnd } = opts
58
+ constructor (init: { id: string, type: 'initiator' | 'recipient', push: Pushable<StreamMessage>, onEnd: (err?: Error) => void }) {
59
+ const { id, type, push, onEnd } = init
59
60
 
60
61
  this.log = logger(`libp2p:mock-muxer:stream:${id}:${type}`)
61
62
 
@@ -216,25 +217,26 @@ class MuxedStream {
216
217
  }
217
218
  }
218
219
 
219
- class MockMuxer implements Muxer {
220
+ class MockMuxer implements StreamMuxer {
220
221
  public source: Source<Uint8Array>
221
222
  public input: Pushable<Uint8Array>
222
223
  public streamInput: Pushable<StreamMessage>
223
224
  public name: string
225
+ public protocol: string = '/mock-muxer/1.0.0'
224
226
 
225
227
  private readonly registryInitiatorStreams: Map<string, MuxedStream>
226
228
  private readonly registryRecipientStreams: Map<string, MuxedStream>
227
- private readonly options: MuxerOptions
229
+ private readonly options: StreamMuxerInit
228
230
 
229
231
  private readonly log: Logger
230
232
 
231
- constructor (options?: MuxerOptions) {
233
+ constructor (init?: StreamMuxerInit) {
232
234
  this.name = `muxer:${muxers++}`
233
235
  this.log = logger(`libp2p:mock-muxer:${this.name}`)
234
236
  this.registryInitiatorStreams = new Map()
235
237
  this.registryRecipientStreams = new Map()
236
238
  this.log('create muxer')
237
- this.options = options ?? {}
239
+ this.options = init ?? {}
238
240
  // receives data from the muxer at the other end of the stream
239
241
  this.source = this.input = pushable<Uint8Array>({
240
242
  onEnd: (err) => {
@@ -349,21 +351,29 @@ class MockMuxer implements Muxer {
349
351
  }
350
352
  }
351
353
 
352
- export function mockMuxer (options?: MuxerOptions): Muxer {
353
- const mockMuxer = new MockMuxer(options)
354
-
355
- void Promise.resolve().then(async () => {
356
- void pipe(
357
- mockMuxer.streamInput,
358
- ndjson.stringify,
359
- (source) => map(source, str => uint8ArrayFromString(str)),
360
- async (source) => {
361
- for await (const buf of source) {
362
- mockMuxer.input.push(buf)
354
+ class MockMuxerFactory implements StreamMuxerFactory {
355
+ public protocol: string = '/mock-muxer/1.0.0'
356
+
357
+ createStreamMuxer (c: Components, init?: StreamMuxerInit): StreamMuxer {
358
+ const mockMuxer = new MockMuxer(init)
359
+
360
+ void Promise.resolve().then(async () => {
361
+ void pipe(
362
+ mockMuxer.streamInput,
363
+ ndjson.stringify,
364
+ (source) => map(source, str => uint8ArrayFromString(str)),
365
+ async (source) => {
366
+ for await (const buf of source) {
367
+ mockMuxer.input.push(buf)
368
+ }
363
369
  }
364
- }
365
- )
366
- })
370
+ )
371
+ })
372
+
373
+ return mockMuxer
374
+ }
375
+ }
367
376
 
368
- return mockMuxer
377
+ export function mockMuxer (): MockMuxerFactory {
378
+ return new MockMuxerFactory()
369
379
  }
@@ -1,13 +1,12 @@
1
1
  import type { IncomingStreamData, Registrar, StreamHandler } from '@libp2p/interfaces/registrar'
2
- import type { Connection } from '@libp2p/interfaces/src/connection'
3
- import type { PeerId } from '@libp2p/interfaces/src/peer-id'
2
+ import type { Connection } from '@libp2p/interfaces/connection'
3
+ import type { PeerId } from '@libp2p/interfaces/peer-id'
4
4
  import type { Topology } from '@libp2p/interfaces/topology'
5
5
  import { connectionPair } from './connection.js'
6
- import { CustomEvent } from '@libp2p/interfaces'
7
6
 
8
7
  export class MockRegistrar implements Registrar {
9
8
  private readonly topologies: Map<string, { topology: Topology, protocols: string[] }> = new Map()
10
- private readonly handlers: Map<string, { handler: StreamHandler, protocols: string[] }> = new Map()
9
+ private readonly handlers: Map<string, StreamHandler> = new Map()
11
10
 
12
11
  getProtocols () {
13
12
  const protocols = new Set<string>()
@@ -16,51 +15,44 @@ export class MockRegistrar implements Registrar {
16
15
  topology.protocols.forEach(protocol => protocols.add(protocol))
17
16
  }
18
17
 
19
- for (const handler of this.handlers.values()) {
20
- handler.protocols.forEach(protocol => protocols.add(protocol))
18
+ for (const protocol of this.handlers.keys()) {
19
+ protocols.add(protocol)
21
20
  }
22
21
 
23
22
  return Array.from(protocols).sort()
24
23
  }
25
24
 
26
- async handle (protocols: string | string[], handler: StreamHandler) {
27
- if (!Array.isArray(protocols)) {
28
- protocols = [protocols]
29
- }
25
+ async handle (protocols: string | string[], handler: StreamHandler): Promise<void> {
26
+ const protocolList = Array.isArray(protocols) ? protocols : [protocols]
30
27
 
31
- for (const protocol of protocols) {
32
- for (const { protocols } of this.handlers.values()) {
33
- if (protocols.includes(protocol)) {
34
- throw new Error(`Handler already registered for protocol ${protocol}`)
35
- }
28
+ for (const protocol of protocolList) {
29
+ if (this.handlers.has(protocol)) {
30
+ throw new Error(`Handler already registered for protocol ${protocol}`)
36
31
  }
32
+
33
+ this.handlers.set(protocol, handler)
37
34
  }
35
+ }
38
36
 
39
- const id = `handler-id-${Math.random()}`
37
+ async unhandle (protocols: string | string[]) {
38
+ const protocolList = Array.isArray(protocols) ? protocols : [protocols]
40
39
 
41
- this.handlers.set(id, {
42
- handler,
43
- protocols
40
+ protocolList.forEach(protocol => {
41
+ this.handlers.delete(protocol)
44
42
  })
45
-
46
- return id
47
- }
48
-
49
- async unhandle (id: string) {
50
- this.handlers.delete(id)
51
43
  }
52
44
 
53
45
  getHandler (protocol: string) {
54
- for (const { handler, protocols } of this.handlers.values()) {
55
- if (protocols.includes(protocol)) {
56
- return handler
57
- }
46
+ const handler = this.handlers.get(protocol)
47
+
48
+ if (handler == null) {
49
+ throw new Error(`No handler registered for protocol ${protocol}`)
58
50
  }
59
51
 
60
- throw new Error(`No handler registered for protocol ${protocol}`)
52
+ return handler
61
53
  }
62
54
 
63
- register (protocols: string | string[], topology: Topology) {
55
+ async register (protocols: string | string[], topology: Topology) {
64
56
  if (!Array.isArray(protocols)) {
65
57
  protocols = [protocols]
66
58
  }
@@ -104,16 +96,14 @@ export function mockRegistrar () {
104
96
  return new MockRegistrar()
105
97
  }
106
98
 
107
- export async function mockIncomingStreamEvent (protocol: string, conn: Connection, remotePeer: PeerId): Promise<CustomEvent<IncomingStreamData>> {
108
- // @ts-expect-error incomplete implementation
109
- return new CustomEvent('incomingStream', {
110
- detail: {
111
- ...await conn.newStream([protocol]),
112
- connection: {
113
- remotePeer
114
- }
99
+ export async function mockIncomingStreamEvent (protocol: string, conn: Connection, remotePeer: PeerId): Promise<IncomingStreamData> {
100
+ return {
101
+ ...await conn.newStream([protocol]),
102
+ // @ts-expect-error incomplete implementation
103
+ connection: {
104
+ remotePeer
115
105
  }
116
- })
106
+ }
117
107
  }
118
108
 
119
109
  export interface Peer {