@libp2p/interface-compliance-tests 1.1.9 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/mocks/connection.d.ts +5 -3
- package/dist/src/mocks/connection.d.ts.map +1 -1
- package/dist/src/mocks/connection.js +21 -13
- package/dist/src/mocks/connection.js.map +1 -1
- package/dist/src/mocks/muxer.d.ts.map +1 -1
- package/dist/src/mocks/muxer.js +201 -131
- package/dist/src/mocks/muxer.js.map +1 -1
- package/dist/src/mocks/registrar.d.ts +5 -1
- package/dist/src/mocks/registrar.d.ts.map +1 -1
- package/dist/src/mocks/registrar.js +8 -10
- package/dist/src/mocks/registrar.js.map +1 -1
- package/dist/src/mocks/upgrader.d.ts +2 -2
- package/dist/src/mocks/upgrader.d.ts.map +1 -1
- package/dist/src/mocks/upgrader.js +2 -2
- package/dist/src/mocks/upgrader.js.map +1 -1
- package/dist/src/pubsub/api.d.ts +3 -2
- package/dist/src/pubsub/api.d.ts.map +1 -1
- package/dist/src/pubsub/api.js +8 -6
- package/dist/src/pubsub/api.js.map +1 -1
- package/dist/src/pubsub/connection-handlers.d.ts +3 -2
- package/dist/src/pubsub/connection-handlers.d.ts.map +1 -1
- package/dist/src/pubsub/connection-handlers.js +128 -34
- package/dist/src/pubsub/connection-handlers.js.map +1 -1
- package/dist/src/pubsub/emit-self.d.ts +3 -2
- package/dist/src/pubsub/emit-self.d.ts.map +1 -1
- package/dist/src/pubsub/emit-self.js +3 -2
- package/dist/src/pubsub/emit-self.js.map +1 -1
- package/dist/src/pubsub/index.d.ts +5 -2
- package/dist/src/pubsub/index.d.ts.map +1 -1
- package/dist/src/pubsub/index.js.map +1 -1
- package/dist/src/pubsub/messages.d.ts +3 -2
- package/dist/src/pubsub/messages.d.ts.map +1 -1
- package/dist/src/pubsub/messages.js +16 -17
- package/dist/src/pubsub/messages.js.map +1 -1
- package/dist/src/pubsub/multiple-nodes.d.ts +3 -2
- package/dist/src/pubsub/multiple-nodes.d.ts.map +1 -1
- package/dist/src/pubsub/multiple-nodes.js +89 -58
- package/dist/src/pubsub/multiple-nodes.js.map +1 -1
- package/dist/src/pubsub/two-nodes.d.ts +3 -2
- package/dist/src/pubsub/two-nodes.d.ts.map +1 -1
- package/dist/src/pubsub/two-nodes.js +74 -32
- package/dist/src/pubsub/two-nodes.js.map +1 -1
- package/dist/src/pubsub/utils.d.ts +3 -0
- package/dist/src/pubsub/utils.d.ts.map +1 -0
- package/dist/src/pubsub/utils.js +9 -0
- package/dist/src/pubsub/utils.js.map +1 -0
- package/dist/src/stream-muxer/base-test.d.ts.map +1 -1
- package/dist/src/stream-muxer/base-test.js +27 -21
- package/dist/src/stream-muxer/base-test.js.map +1 -1
- package/dist/src/stream-muxer/close-test.d.ts.map +1 -1
- package/dist/src/stream-muxer/close-test.js +25 -28
- package/dist/src/stream-muxer/close-test.js.map +1 -1
- package/dist/src/stream-muxer/spawner.d.ts.map +1 -1
- package/dist/src/stream-muxer/spawner.js +2 -3
- package/dist/src/stream-muxer/spawner.js.map +1 -1
- package/dist/src/stream-muxer/stress-test.d.ts.map +1 -1
- package/dist/src/stream-muxer/stress-test.js +2 -1
- package/dist/src/stream-muxer/stress-test.js.map +1 -1
- package/dist/src/transport/dial-test.d.ts.map +1 -1
- package/dist/src/transport/dial-test.js +16 -5
- package/dist/src/transport/dial-test.js.map +1 -1
- package/dist/src/transport/listen-test.d.ts.map +1 -1
- package/dist/src/transport/listen-test.js +13 -2
- package/dist/src/transport/listen-test.js.map +1 -1
- package/package.json +5 -1
- package/src/mocks/connection.ts +27 -15
- package/src/mocks/muxer.ts +271 -147
- package/src/mocks/registrar.ts +12 -10
- package/src/mocks/upgrader.ts +4 -4
- package/src/pubsub/api.ts +13 -9
- package/src/pubsub/connection-handlers.ts +148 -43
- package/src/pubsub/emit-self.ts +9 -7
- package/src/pubsub/index.ts +5 -2
- package/src/pubsub/messages.ts +24 -23
- package/src/pubsub/multiple-nodes.ts +104 -74
- package/src/pubsub/two-nodes.ts +87 -39
- package/src/pubsub/utils.ts +12 -0
- package/src/stream-muxer/base-test.ts +35 -24
- package/src/stream-muxer/close-test.ts +32 -29
- package/src/stream-muxer/spawner.ts +3 -6
- package/src/stream-muxer/stress-test.ts +2 -1
- package/src/transport/dial-test.ts +23 -6
- package/src/transport/listen-test.ts +16 -2
package/src/mocks/muxer.ts
CHANGED
|
@@ -2,244 +2,368 @@ import { Pushable, pushable } from 'it-pushable'
|
|
|
2
2
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
3
3
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
4
4
|
import { abortableSource } from 'abortable-iterator'
|
|
5
|
+
import { anySignal } from 'any-signal'
|
|
6
|
+
import errCode from 'err-code'
|
|
7
|
+
import { Logger, logger } from '@libp2p/logger'
|
|
8
|
+
import * as ndjson from 'it-ndjson'
|
|
5
9
|
import type { Stream } from '@libp2p/interfaces/connection'
|
|
6
10
|
import type { Muxer, MuxerOptions } from '@libp2p/interfaces/stream-muxer'
|
|
7
11
|
import type { Source } from 'it-stream-types'
|
|
12
|
+
import { pipe } from 'it-pipe'
|
|
13
|
+
import map from 'it-map'
|
|
14
|
+
|
|
15
|
+
let muxers = 0
|
|
16
|
+
let streams = 0
|
|
8
17
|
|
|
9
18
|
interface DataMessage {
|
|
10
19
|
id: string
|
|
11
20
|
type: 'data'
|
|
21
|
+
direction: 'initiator' | 'recipient'
|
|
12
22
|
chunk: string
|
|
13
23
|
}
|
|
14
24
|
|
|
15
25
|
interface ResetMessage {
|
|
16
26
|
id: string
|
|
17
27
|
type: 'reset'
|
|
28
|
+
direction: 'initiator' | 'recipient'
|
|
18
29
|
}
|
|
19
30
|
|
|
20
31
|
interface CloseMessage {
|
|
21
32
|
id: string
|
|
22
33
|
type: 'close'
|
|
34
|
+
direction: 'initiator' | 'recipient'
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface CreateMessage {
|
|
38
|
+
id: string
|
|
39
|
+
type: 'create'
|
|
40
|
+
direction: 'initiator'
|
|
23
41
|
}
|
|
24
42
|
|
|
25
|
-
type StreamMessage = DataMessage | ResetMessage | CloseMessage
|
|
43
|
+
type StreamMessage = DataMessage | ResetMessage | CloseMessage | CreateMessage
|
|
26
44
|
|
|
27
45
|
class MuxedStream {
|
|
28
46
|
public id: string
|
|
29
47
|
public input: Pushable<Uint8Array>
|
|
30
48
|
public stream: Stream
|
|
49
|
+
public type: 'initiator' | 'recipient'
|
|
31
50
|
|
|
32
|
-
private
|
|
33
|
-
private
|
|
34
|
-
private readonly
|
|
35
|
-
private readonly
|
|
51
|
+
private sinkEnded: boolean
|
|
52
|
+
private sourceEnded: boolean
|
|
53
|
+
private readonly abortController: AbortController
|
|
54
|
+
private readonly resetController: AbortController
|
|
55
|
+
private readonly log: Logger
|
|
36
56
|
|
|
37
|
-
constructor (opts: { id: string, push: Pushable<StreamMessage>, onEnd: () => void }) {
|
|
38
|
-
const { id, push, onEnd } = opts
|
|
57
|
+
constructor (opts: { id: string, type: 'initiator' | 'recipient', push: Pushable<StreamMessage>, onEnd: (err?: Error) => void }) {
|
|
58
|
+
const { id, type, push, onEnd } = opts
|
|
59
|
+
|
|
60
|
+
this.log = logger(`libp2p:mock-muxer:stream:${id}:${type}`)
|
|
39
61
|
|
|
40
62
|
this.id = id
|
|
41
|
-
this.
|
|
42
|
-
this.
|
|
43
|
-
this.
|
|
44
|
-
|
|
45
|
-
this.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
63
|
+
this.type = type
|
|
64
|
+
this.abortController = new AbortController()
|
|
65
|
+
this.resetController = new AbortController()
|
|
66
|
+
|
|
67
|
+
this.sourceEnded = false
|
|
68
|
+
this.sinkEnded = false
|
|
69
|
+
|
|
70
|
+
let endErr: Error | undefined
|
|
71
|
+
|
|
72
|
+
const onSourceEnd = (err?: Error) => {
|
|
73
|
+
if (this.sourceEnded) {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this.log('onSourceEnd sink ended? %s', this.sinkEnded)
|
|
78
|
+
|
|
79
|
+
this.sourceEnded = true
|
|
80
|
+
|
|
81
|
+
if (err != null && endErr == null) {
|
|
82
|
+
endErr = err
|
|
49
83
|
}
|
|
84
|
+
|
|
85
|
+
if (this.sinkEnded) {
|
|
86
|
+
this.stream.timeline.close = Date.now()
|
|
87
|
+
|
|
88
|
+
if (onEnd != null) {
|
|
89
|
+
onEnd(endErr)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const onSinkEnd = (err?: Error) => {
|
|
95
|
+
if (this.sinkEnded) {
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this.log('onSinkEnd source ended? %s', this.sourceEnded)
|
|
100
|
+
|
|
101
|
+
this.sinkEnded = true
|
|
102
|
+
|
|
103
|
+
if (err != null && endErr == null) {
|
|
104
|
+
endErr = err
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (this.sourceEnded) {
|
|
108
|
+
this.stream.timeline.close = Date.now()
|
|
109
|
+
|
|
110
|
+
if (onEnd != null) {
|
|
111
|
+
onEnd(endErr)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
this.input = pushable<Uint8Array>({
|
|
117
|
+
onEnd: onSourceEnd
|
|
50
118
|
})
|
|
119
|
+
|
|
51
120
|
this.stream = {
|
|
52
121
|
id,
|
|
53
122
|
sink: async (source) => {
|
|
54
|
-
source = abortableSource(source,
|
|
123
|
+
source = abortableSource(source, anySignal([
|
|
124
|
+
this.abortController.signal,
|
|
125
|
+
this.resetController.signal
|
|
126
|
+
]))
|
|
55
127
|
|
|
56
128
|
try {
|
|
129
|
+
if (this.type === 'initiator') {
|
|
130
|
+
// If initiator, open a new stream
|
|
131
|
+
const createMsg: CreateMessage = {
|
|
132
|
+
id: this.id,
|
|
133
|
+
type: 'create',
|
|
134
|
+
direction: this.type
|
|
135
|
+
}
|
|
136
|
+
push.push(createMsg)
|
|
137
|
+
}
|
|
138
|
+
|
|
57
139
|
for await (const chunk of source) {
|
|
58
140
|
const dataMsg: DataMessage = {
|
|
59
141
|
id,
|
|
60
142
|
type: 'data',
|
|
61
|
-
chunk: uint8ArrayToString(chunk, 'base64')
|
|
143
|
+
chunk: uint8ArrayToString(chunk, 'base64'),
|
|
144
|
+
direction: this.type
|
|
62
145
|
}
|
|
63
146
|
|
|
64
147
|
push.push(dataMsg)
|
|
65
148
|
}
|
|
149
|
+
} catch (err: any) {
|
|
150
|
+
if (err.type === 'aborted' && err.message === 'The operation was aborted') {
|
|
151
|
+
if (this.resetController.signal.aborted) {
|
|
152
|
+
err.message = 'stream reset'
|
|
153
|
+
err.code = 'ERR_STREAM_RESET'
|
|
154
|
+
}
|
|
66
155
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
156
|
+
if (this.abortController.signal.aborted) {
|
|
157
|
+
err.message = 'stream aborted'
|
|
158
|
+
err.code = 'ERR_STREAM_ABORT'
|
|
159
|
+
}
|
|
70
160
|
}
|
|
71
161
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
162
|
+
// Send no more data if this stream was remotely reset
|
|
163
|
+
if (err.code !== 'ERR_STREAM_RESET') {
|
|
164
|
+
const resetMsg: ResetMessage = {
|
|
165
|
+
id,
|
|
166
|
+
type: 'reset',
|
|
167
|
+
direction: this.type
|
|
168
|
+
}
|
|
169
|
+
push.push(resetMsg)
|
|
76
170
|
}
|
|
171
|
+
|
|
172
|
+
this.log('sink erred', err)
|
|
173
|
+
|
|
174
|
+
this.input.end(err)
|
|
175
|
+
onSinkEnd(err)
|
|
176
|
+
return
|
|
77
177
|
}
|
|
78
178
|
|
|
79
|
-
this.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
179
|
+
this.log('sink ended')
|
|
180
|
+
|
|
181
|
+
onSinkEnd()
|
|
182
|
+
|
|
83
183
|
const closeMsg: CloseMessage = {
|
|
84
184
|
id,
|
|
85
|
-
type: 'close'
|
|
185
|
+
type: 'close',
|
|
186
|
+
direction: this.type
|
|
86
187
|
}
|
|
87
188
|
push.push(closeMsg)
|
|
189
|
+
},
|
|
190
|
+
source: this.input,
|
|
88
191
|
|
|
89
|
-
|
|
90
|
-
|
|
192
|
+
// Close for reading
|
|
193
|
+
close: () => {
|
|
194
|
+
this.input.end()
|
|
91
195
|
},
|
|
92
|
-
abort: () => {
|
|
93
|
-
const resetMsg: ResetMessage = {
|
|
94
|
-
id,
|
|
95
|
-
type: 'reset'
|
|
96
|
-
}
|
|
97
|
-
push.push(resetMsg)
|
|
98
196
|
|
|
99
|
-
|
|
100
|
-
|
|
197
|
+
// Close for reading and writing (local error)
|
|
198
|
+
abort: (err?: Error) => {
|
|
199
|
+
// End the source with the passed error
|
|
200
|
+
this.input.end()
|
|
201
|
+
this.abortController.abort()
|
|
202
|
+
onSinkEnd(err)
|
|
101
203
|
},
|
|
102
|
-
reset: () => {
|
|
103
|
-
const resetMsg: ResetMessage = {
|
|
104
|
-
id,
|
|
105
|
-
type: 'reset'
|
|
106
|
-
}
|
|
107
|
-
push.push(resetMsg)
|
|
108
204
|
|
|
109
|
-
|
|
110
|
-
|
|
205
|
+
// Close immediately for reading and writing (remote error)
|
|
206
|
+
reset: () => {
|
|
207
|
+
const err = errCode(new Error('stream reset'), 'ERR_STREAM_RESET')
|
|
208
|
+
this.resetController.abort()
|
|
209
|
+
this.input.end(err)
|
|
210
|
+
onSinkEnd(err)
|
|
111
211
|
},
|
|
112
212
|
timeline: {
|
|
113
213
|
open: Date.now()
|
|
114
214
|
}
|
|
115
215
|
}
|
|
116
216
|
}
|
|
217
|
+
}
|
|
117
218
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
219
|
+
class MockMuxer implements Muxer {
|
|
220
|
+
public source: Source<Uint8Array>
|
|
221
|
+
public input: Pushable<Uint8Array>
|
|
222
|
+
public streamInput: Pushable<StreamMessage>
|
|
223
|
+
public name: string
|
|
224
|
+
|
|
225
|
+
private readonly registryInitiatorStreams: Map<string, MuxedStream>
|
|
226
|
+
private readonly registryRecipientStreams: Map<string, MuxedStream>
|
|
227
|
+
private readonly options: MuxerOptions
|
|
228
|
+
|
|
229
|
+
private readonly log: Logger
|
|
230
|
+
|
|
231
|
+
constructor (options?: MuxerOptions) {
|
|
232
|
+
this.name = `muxer:${muxers++}`
|
|
233
|
+
this.log = logger(`libp2p:mock-muxer:${this.name}`)
|
|
234
|
+
this.registryInitiatorStreams = new Map()
|
|
235
|
+
this.registryRecipientStreams = new Map()
|
|
236
|
+
this.log('create muxer')
|
|
237
|
+
this.options = options ?? {}
|
|
238
|
+
// receives data from the muxer at the other end of the stream
|
|
239
|
+
this.source = this.input = pushable<Uint8Array>({
|
|
240
|
+
onEnd: (err) => {
|
|
241
|
+
this.log('closing muxed streams')
|
|
242
|
+
for (const stream of this.streams) {
|
|
243
|
+
stream.abort(err)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
})
|
|
123
247
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
this.onEnd()
|
|
127
|
-
}
|
|
248
|
+
// receives messages from all of the muxed streams
|
|
249
|
+
this.streamInput = pushable<StreamMessage>()
|
|
128
250
|
}
|
|
129
251
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
252
|
+
// receive incoming messages
|
|
253
|
+
async sink (source: Source<Uint8Array>) {
|
|
254
|
+
try {
|
|
255
|
+
await pipe(
|
|
256
|
+
source,
|
|
257
|
+
(source) => map(source, buf => uint8ArrayToString(buf)),
|
|
258
|
+
ndjson.parse,
|
|
259
|
+
async (source) => {
|
|
260
|
+
for await (const message of source) {
|
|
261
|
+
this.log('-> %s %s %s', message.type, message.direction, message.id)
|
|
262
|
+
this.handleMessage(message)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
)
|
|
134
266
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
267
|
+
this.log('muxed stream ended')
|
|
268
|
+
this.input.end()
|
|
269
|
+
} catch (err: any) {
|
|
270
|
+
this.log('muxed stream errored', err)
|
|
271
|
+
this.input.end(err)
|
|
272
|
+
}
|
|
139
273
|
}
|
|
140
|
-
}
|
|
141
274
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
muxedStream.stream.close()
|
|
275
|
+
handleMessage (message: StreamMessage) {
|
|
276
|
+
let muxedStream: MuxedStream | undefined
|
|
277
|
+
|
|
278
|
+
const registry = message.direction === 'initiator' ? this.registryRecipientStreams : this.registryInitiatorStreams
|
|
279
|
+
|
|
280
|
+
if (message.type === 'create') {
|
|
281
|
+
if (registry.has(message.id)) {
|
|
282
|
+
throw new Error(`Already had stream for ${message.id}`)
|
|
151
283
|
}
|
|
152
|
-
}
|
|
153
|
-
})
|
|
154
284
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
muxerSource.push(uint8ArrayFromString(JSON.stringify({
|
|
161
|
-
id: message.id,
|
|
162
|
-
type: message.type,
|
|
163
|
-
chunk: message.chunk
|
|
164
|
-
})))
|
|
165
|
-
} else {
|
|
166
|
-
muxerSource.push(uint8ArrayFromString(JSON.stringify({
|
|
167
|
-
id: message.id,
|
|
168
|
-
type: message.type
|
|
169
|
-
})))
|
|
285
|
+
muxedStream = this.createStream(message.id, 'recipient')
|
|
286
|
+
registry.set(muxedStream.stream.id, muxedStream)
|
|
287
|
+
|
|
288
|
+
if (this.options.onIncomingStream != null) {
|
|
289
|
+
this.options.onIncomingStream(muxedStream.stream)
|
|
170
290
|
}
|
|
171
291
|
}
|
|
172
|
-
})
|
|
173
292
|
|
|
174
|
-
|
|
175
|
-
const id = name ?? `${streamId++}`
|
|
293
|
+
muxedStream = registry.get(message.id)
|
|
176
294
|
|
|
177
|
-
|
|
178
|
-
id
|
|
179
|
-
|
|
180
|
-
onEnd: () => {
|
|
181
|
-
streams.delete(id)
|
|
182
|
-
|
|
183
|
-
if (options?.onStreamEnd != null) {
|
|
184
|
-
options?.onStreamEnd(muxedStream.stream)
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
})
|
|
295
|
+
if (muxedStream == null) {
|
|
296
|
+
throw new Error(`No stream found for ${message.id}`)
|
|
297
|
+
}
|
|
188
298
|
|
|
189
|
-
|
|
299
|
+
if (message.type === 'data') {
|
|
300
|
+
muxedStream.input.push(uint8ArrayFromString(message.chunk, 'base64'))
|
|
301
|
+
} else if (message.type === 'reset') {
|
|
302
|
+
this.log('-> reset stream %s %s', muxedStream.type, muxedStream.stream.id)
|
|
303
|
+
muxedStream.stream.reset()
|
|
304
|
+
} else if (message.type === 'close') {
|
|
305
|
+
this.log('-> closing stream %s %s', muxedStream.type, muxedStream.stream.id)
|
|
306
|
+
muxedStream.stream.close()
|
|
307
|
+
}
|
|
190
308
|
}
|
|
191
309
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
let muxedStream = streams.get(message.id)
|
|
310
|
+
get streams () {
|
|
311
|
+
return Array.from(this.registryRecipientStreams.values())
|
|
312
|
+
.concat(Array.from(this.registryInitiatorStreams.values()))
|
|
313
|
+
.map(({ stream }) => stream)
|
|
314
|
+
}
|
|
198
315
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
316
|
+
newStream (name?: string) {
|
|
317
|
+
this.log('newStream %s', name)
|
|
318
|
+
const storedStream = this.createStream(name, 'initiator')
|
|
319
|
+
this.registryInitiatorStreams.set(storedStream.stream.id, storedStream)
|
|
202
320
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
}
|
|
321
|
+
return storedStream.stream
|
|
322
|
+
}
|
|
207
323
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
} else if (message.type === 'reset') {
|
|
211
|
-
muxedStream.closeSink()
|
|
212
|
-
muxedStream.closeSource()
|
|
213
|
-
} else if (message.type === 'close') {
|
|
214
|
-
muxedStream.closeSource()
|
|
215
|
-
}
|
|
216
|
-
}
|
|
324
|
+
createStream (name?: string, type: 'initiator' | 'recipient' = 'initiator'): MuxedStream {
|
|
325
|
+
const id = name ?? `${this.name}:stream:${streams++}`
|
|
217
326
|
|
|
218
|
-
|
|
219
|
-
muxedStream.stream.close()
|
|
220
|
-
}
|
|
327
|
+
this.log('createStream %s %s', type, id)
|
|
221
328
|
|
|
222
|
-
|
|
223
|
-
|
|
329
|
+
const muxedStream: MuxedStream = new MuxedStream({
|
|
330
|
+
id,
|
|
331
|
+
type,
|
|
332
|
+
push: this.streamInput,
|
|
333
|
+
onEnd: () => {
|
|
334
|
+
this.log('stream ended %s %s', type, id)
|
|
224
335
|
|
|
225
|
-
|
|
336
|
+
if (type === 'initiator') {
|
|
337
|
+
this.registryInitiatorStreams.delete(id)
|
|
338
|
+
} else {
|
|
339
|
+
this.registryRecipientStreams.delete(id)
|
|
340
|
+
}
|
|
226
341
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
342
|
+
if (this.options.onStreamEnd != null) {
|
|
343
|
+
this.options.onStreamEnd(muxedStream.stream)
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
})
|
|
230
347
|
|
|
231
|
-
|
|
232
|
-
|
|
348
|
+
return muxedStream
|
|
349
|
+
}
|
|
350
|
+
}
|
|
233
351
|
|
|
234
|
-
|
|
352
|
+
export function mockMuxer (options?: MuxerOptions): Muxer {
|
|
353
|
+
const mockMuxer = new MockMuxer(options)
|
|
235
354
|
|
|
236
|
-
|
|
237
|
-
|
|
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)
|
|
363
|
+
}
|
|
238
364
|
}
|
|
365
|
+
)
|
|
366
|
+
})
|
|
239
367
|
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return muxer
|
|
368
|
+
return mockMuxer
|
|
245
369
|
}
|
package/src/mocks/registrar.ts
CHANGED
|
@@ -116,18 +116,20 @@ export async function mockIncomingStreamEvent (protocol: string, conn: Connectio
|
|
|
116
116
|
})
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
export
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// const handlerB = registrarB.getHandler(protocol)
|
|
119
|
+
export interface Peer {
|
|
120
|
+
peerId: PeerId
|
|
121
|
+
registrar: Registrar
|
|
122
|
+
}
|
|
124
123
|
|
|
124
|
+
export async function connectPeers (protocol: string, a: Peer, b: Peer) {
|
|
125
125
|
// Notify peers of connection
|
|
126
|
-
const [
|
|
126
|
+
const [aToB, bToA] = connectionPair(a, b)
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
for (const topology of a.registrar.getTopologies(protocol)) {
|
|
129
|
+
await topology.onConnect(b.peerId, aToB)
|
|
130
|
+
}
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
|
|
132
|
+
for (const topology of b.registrar.getTopologies(protocol)) {
|
|
133
|
+
await topology.onConnect(a.peerId, bToA)
|
|
134
|
+
}
|
|
133
135
|
}
|
package/src/mocks/upgrader.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { expect } from 'aegir/utils/chai.js'
|
|
2
2
|
import { mockConnection } from './connection.js'
|
|
3
3
|
import type { Upgrader, MultiaddrConnection } from '@libp2p/interfaces/transport'
|
|
4
|
-
import type {
|
|
4
|
+
import type { Registrar } from '@libp2p/interfaces/registrar'
|
|
5
5
|
|
|
6
6
|
export interface MockUpgraderOptions {
|
|
7
|
-
|
|
7
|
+
registrar?: Registrar
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export function mockUpgrader (options: MockUpgraderOptions = {}) {
|
|
@@ -20,14 +20,14 @@ export function mockUpgrader (options: MockUpgraderOptions = {}) {
|
|
|
20
20
|
ensureProps(multiaddrConnection)
|
|
21
21
|
return mockConnection(multiaddrConnection, {
|
|
22
22
|
direction: 'outbound',
|
|
23
|
-
|
|
23
|
+
registrar: options.registrar
|
|
24
24
|
})
|
|
25
25
|
},
|
|
26
26
|
async upgradeInbound (multiaddrConnection) {
|
|
27
27
|
ensureProps(multiaddrConnection)
|
|
28
28
|
return mockConnection(multiaddrConnection, {
|
|
29
29
|
direction: 'inbound',
|
|
30
|
-
|
|
30
|
+
registrar: options.registrar
|
|
31
31
|
})
|
|
32
32
|
}
|
|
33
33
|
}
|
package/src/pubsub/api.ts
CHANGED
|
@@ -3,17 +3,20 @@ import sinon from 'sinon'
|
|
|
3
3
|
import pDefer from 'p-defer'
|
|
4
4
|
import pWaitFor from 'p-wait-for'
|
|
5
5
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
6
|
+
import { mockRegistrar } from '../mocks/registrar.js'
|
|
7
|
+
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
|
|
8
|
+
import delay from 'delay'
|
|
9
|
+
import { CustomEvent } from '@libp2p/interfaces'
|
|
6
10
|
import type { TestSetup } from '../index.js'
|
|
7
11
|
import type { PubSub, PubSubOptions } from '@libp2p/interfaces/pubsub'
|
|
8
12
|
import type { EventMap } from './index.js'
|
|
9
13
|
import type { Registrar } from '@libp2p/interfaces/src/registrar'
|
|
10
|
-
import {
|
|
11
|
-
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
|
|
14
|
+
import type { PubsubBaseProtocol } from '@libp2p/pubsub'
|
|
12
15
|
|
|
13
16
|
const topic = 'foo'
|
|
14
17
|
const data = uint8ArrayFromString('bar')
|
|
15
18
|
|
|
16
|
-
export default (common: TestSetup<
|
|
19
|
+
export default (common: TestSetup<PubsubBaseProtocol<EventMap>, PubSubOptions>) => {
|
|
17
20
|
describe('pubsub api', () => {
|
|
18
21
|
let pubsub: PubSub<EventMap>
|
|
19
22
|
let registrar: Registrar
|
|
@@ -60,20 +63,22 @@ export default (common: TestSetup<PubSub<EventMap>, PubSubOptions>) => {
|
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
await pubsub.start()
|
|
63
|
-
pubsub.
|
|
64
|
-
pubsub.addEventListener('topic', handler)
|
|
66
|
+
pubsub.addEventListener(topic, handler)
|
|
65
67
|
|
|
66
68
|
await pWaitFor(() => {
|
|
67
69
|
const topics = pubsub.getTopics()
|
|
68
70
|
return topics.length === 1 && topics[0] === topic
|
|
69
71
|
})
|
|
70
72
|
|
|
71
|
-
pubsub.
|
|
73
|
+
pubsub.removeEventListener(topic, handler)
|
|
72
74
|
|
|
73
75
|
await pWaitFor(() => pubsub.getTopics().length === 0)
|
|
74
76
|
|
|
75
77
|
// Publish to guarantee the handler is not called
|
|
76
|
-
|
|
78
|
+
pubsub.dispatchEvent(new CustomEvent(topic, { detail: data }))
|
|
79
|
+
|
|
80
|
+
// handlers are called async
|
|
81
|
+
await delay(100)
|
|
77
82
|
|
|
78
83
|
await pubsub.stop()
|
|
79
84
|
})
|
|
@@ -83,13 +88,12 @@ export default (common: TestSetup<PubSub<EventMap>, PubSubOptions>) => {
|
|
|
83
88
|
|
|
84
89
|
await pubsub.start()
|
|
85
90
|
|
|
86
|
-
pubsub.subscribe(topic)
|
|
87
91
|
pubsub.addEventListener(topic, (evt) => {
|
|
88
92
|
const msg = evt.detail
|
|
89
93
|
expect(msg).to.not.eql(undefined)
|
|
90
94
|
defer.resolve()
|
|
91
95
|
})
|
|
92
|
-
|
|
96
|
+
pubsub.dispatchEvent(new CustomEvent(topic, { detail: data }))
|
|
93
97
|
await defer.promise
|
|
94
98
|
|
|
95
99
|
await pubsub.stop()
|