@libp2p/interface-compliance-tests 6.5.0-6059227cb → 6.5.0-87bc8d4fb
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/connection-encryption/index.d.ts.map +1 -1
- package/dist/src/connection-encryption/index.js +15 -24
- package/dist/src/connection-encryption/index.js.map +1 -1
- package/dist/src/connection-encryption/utils/index.d.ts +3 -0
- package/dist/src/connection-encryption/utils/index.d.ts.map +1 -0
- package/dist/src/connection-encryption/utils/index.js +21 -0
- package/dist/src/connection-encryption/utils/index.js.map +1 -0
- package/dist/src/matchers.d.ts +12 -0
- package/dist/src/matchers.d.ts.map +1 -0
- package/dist/src/matchers.js +14 -0
- package/dist/src/matchers.js.map +1 -0
- package/dist/src/mocks/connection-manager.d.ts +27 -0
- package/dist/src/mocks/connection-manager.d.ts.map +1 -0
- package/dist/src/mocks/connection-manager.js +147 -0
- package/dist/src/mocks/connection-manager.js.map +1 -0
- package/dist/src/mocks/connection.d.ts +41 -0
- package/dist/src/mocks/connection.d.ts.map +1 -0
- package/dist/src/mocks/connection.js +236 -0
- package/dist/src/mocks/connection.js.map +1 -0
- package/dist/src/mocks/duplex.d.ts +4 -0
- package/dist/src/mocks/duplex.d.ts.map +1 -0
- package/dist/src/mocks/duplex.js +9 -0
- package/dist/src/mocks/duplex.js.map +1 -0
- package/dist/src/mocks/index.d.ts +12 -0
- package/dist/src/mocks/index.d.ts.map +1 -0
- package/dist/src/mocks/index.js +8 -0
- package/dist/src/mocks/index.js.map +1 -0
- package/dist/src/mocks/multiaddr-connection.d.ts +17 -0
- package/dist/src/mocks/multiaddr-connection.d.ts.map +1 -0
- package/dist/src/mocks/multiaddr-connection.js +64 -0
- package/dist/src/mocks/multiaddr-connection.js.map +1 -0
- package/dist/src/mocks/muxer.d.ts +36 -0
- package/dist/src/mocks/muxer.d.ts.map +1 -0
- package/dist/src/mocks/muxer.js +234 -0
- package/dist/src/mocks/muxer.js.map +1 -0
- package/dist/src/mocks/registrar.d.ts +16 -0
- package/dist/src/mocks/registrar.d.ts.map +1 -0
- package/dist/src/mocks/registrar.js +66 -0
- package/dist/src/mocks/registrar.js.map +1 -0
- package/dist/src/mocks/upgrader.d.ts +9 -0
- package/dist/src/mocks/upgrader.d.ts.map +1 -0
- package/dist/src/mocks/upgrader.js +46 -0
- package/dist/src/mocks/upgrader.js.map +1 -0
- package/dist/src/pubsub/api.d.ts +6 -0
- package/dist/src/pubsub/api.d.ts.map +1 -0
- package/dist/src/pubsub/api.js +88 -0
- package/dist/src/pubsub/api.js.map +1 -0
- package/dist/src/pubsub/connection-handlers.d.ts +6 -0
- package/dist/src/pubsub/connection-handlers.d.ts.map +1 -0
- package/dist/src/pubsub/connection-handlers.js +329 -0
- package/dist/src/pubsub/connection-handlers.js.map +1 -0
- package/dist/src/pubsub/emit-self.d.ts +6 -0
- package/dist/src/pubsub/emit-self.d.ts.map +1 -0
- package/dist/src/pubsub/emit-self.js +80 -0
- package/dist/src/pubsub/emit-self.js.map +1 -0
- package/dist/src/pubsub/index.d.ts +18 -0
- package/dist/src/pubsub/index.d.ts.map +1 -0
- package/dist/src/pubsub/index.js +17 -0
- package/dist/src/pubsub/index.js.map +1 -0
- package/dist/src/pubsub/messages.d.ts +6 -0
- package/dist/src/pubsub/messages.d.ts.map +1 -0
- package/dist/src/pubsub/messages.js +48 -0
- package/dist/src/pubsub/messages.js.map +1 -0
- package/dist/src/pubsub/multiple-nodes.d.ts +6 -0
- package/dist/src/pubsub/multiple-nodes.d.ts.map +1 -0
- package/dist/src/pubsub/multiple-nodes.js +350 -0
- package/dist/src/pubsub/multiple-nodes.js.map +1 -0
- package/dist/src/pubsub/two-nodes.d.ts +6 -0
- package/dist/src/pubsub/two-nodes.d.ts.map +1 -0
- package/dist/src/pubsub/two-nodes.js +216 -0
- package/dist/src/pubsub/two-nodes.js.map +1 -0
- package/dist/src/pubsub/utils.d.ts +5 -0
- package/dist/src/pubsub/utils.d.ts.map +1 -0
- package/dist/src/pubsub/utils.js +27 -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 +345 -62
- 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 +320 -254
- package/dist/src/stream-muxer/close-test.js.map +1 -1
- package/dist/src/stream-muxer/index.js +2 -2
- package/dist/src/stream-muxer/index.js.map +1 -1
- package/dist/src/stream-muxer/{stream-test.d.ts → mega-stress-test.d.ts} +2 -2
- package/dist/src/stream-muxer/mega-stress-test.d.ts.map +1 -0
- package/dist/src/stream-muxer/mega-stress-test.js +11 -0
- package/dist/src/stream-muxer/mega-stress-test.js.map +1 -0
- package/dist/src/stream-muxer/spawner.d.ts +4 -0
- package/dist/src/stream-muxer/spawner.d.ts.map +1 -0
- package/dist/src/stream-muxer/spawner.js +39 -0
- package/dist/src/stream-muxer/spawner.js.map +1 -0
- package/dist/src/stream-muxer/stress-test.d.ts.map +1 -1
- package/dist/src/stream-muxer/stress-test.js +16 -70
- package/dist/src/stream-muxer/stress-test.js.map +1 -1
- package/dist/src/transport/index.d.ts.map +1 -1
- package/dist/src/transport/index.js +205 -235
- package/dist/src/transport/index.js.map +1 -1
- package/dist/src/transport/utils.d.ts.map +1 -1
- package/dist/src/transport/utils.js +2 -3
- package/dist/src/transport/utils.js.map +1 -1
- package/package.json +51 -23
- package/src/connection-encryption/index.ts +20 -27
- package/src/connection-encryption/utils/index.ts +27 -0
- package/src/matchers.ts +18 -0
- package/src/mocks/connection-manager.ts +216 -0
- package/src/mocks/connection.ts +309 -0
- package/src/mocks/duplex.ts +11 -0
- package/src/mocks/index.ts +11 -0
- package/src/mocks/multiaddr-connection.ts +80 -0
- package/src/mocks/muxer.ts +331 -0
- package/src/mocks/registrar.ts +86 -0
- package/src/mocks/upgrader.ts +65 -0
- package/src/pubsub/api.ts +116 -0
- package/src/pubsub/connection-handlers.ts +413 -0
- package/src/pubsub/emit-self.ts +99 -0
- package/src/pubsub/index.ts +34 -0
- package/src/pubsub/messages.ts +59 -0
- package/src/pubsub/multiple-nodes.ts +440 -0
- package/src/pubsub/two-nodes.ts +272 -0
- package/src/pubsub/utils.ts +34 -0
- package/src/stream-muxer/base-test.ts +413 -75
- package/src/stream-muxer/close-test.ts +343 -305
- package/src/stream-muxer/index.ts +2 -2
- package/src/stream-muxer/mega-stress-test.ts +14 -0
- package/src/stream-muxer/spawner.ts +57 -0
- package/src/stream-muxer/stress-test.ts +18 -92
- package/src/transport/index.ts +241 -281
- package/src/transport/utils.ts +2 -3
- package/dist/src/stream-muxer/stream-test.d.ts.map +0 -1
- package/dist/src/stream-muxer/stream-test.js +0 -290
- package/dist/src/stream-muxer/stream-test.js.map +0 -1
- package/src/stream-muxer/stream-test.ts +0 -381
package/src/transport/index.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import { stop
|
|
2
|
-
import { prefixLogger } from '@libp2p/logger'
|
|
1
|
+
import { stop } from '@libp2p/interface'
|
|
3
2
|
import { expect } from 'aegir/chai'
|
|
4
3
|
import delay from 'delay'
|
|
5
|
-
import all from 'it-all'
|
|
6
4
|
import drain from 'it-drain'
|
|
7
5
|
import { pushable } from 'it-pushable'
|
|
6
|
+
import pDefer from 'p-defer'
|
|
8
7
|
import { pEvent } from 'p-event'
|
|
9
8
|
import pRetry from 'p-retry'
|
|
10
9
|
import pWaitFor from 'p-wait-for'
|
|
11
10
|
import { raceSignal } from 'race-signal'
|
|
12
|
-
import { Uint8ArrayList } from 'uint8arraylist'
|
|
13
11
|
import { isValidTick } from '../is-valid-tick.js'
|
|
14
12
|
import { createPeer, getTransportManager, getUpgrader } from './utils.js'
|
|
15
13
|
import type { TestSetup } from '../index.js'
|
|
@@ -18,6 +16,7 @@ import type { Connection, Libp2p, Stream, StreamHandler } from '@libp2p/interfac
|
|
|
18
16
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
19
17
|
import type { MultiaddrMatcher } from '@multiformats/multiaddr-matcher'
|
|
20
18
|
import type { Libp2pInit } from 'libp2p'
|
|
19
|
+
import type { DeferredPromise } from 'p-defer'
|
|
21
20
|
|
|
22
21
|
export interface TransportTestFixtures {
|
|
23
22
|
/**
|
|
@@ -49,113 +48,34 @@ export interface TransportTestFixtures {
|
|
|
49
48
|
|
|
50
49
|
async function getSetup (common: TestSetup<TransportTestFixtures>): Promise<{ dialer: Libp2p<{ echo: Echo }>, listener?: Libp2p<{ echo: Echo }>, dialAddrs: Multiaddr[], dialMultiaddrMatcher: MultiaddrMatcher, listenMultiaddrMatcher: MultiaddrMatcher }> {
|
|
51
50
|
const setup = await common.setup()
|
|
52
|
-
const dialer = await createPeer(
|
|
53
|
-
logger: prefixLogger('dialer'),
|
|
54
|
-
...setup.dialer
|
|
55
|
-
})
|
|
51
|
+
const dialer = await createPeer(setup.dialer)
|
|
56
52
|
let listener
|
|
57
53
|
|
|
58
54
|
if (setup.listener != null) {
|
|
59
|
-
listener = await createPeer(
|
|
60
|
-
logger: prefixLogger('listener'),
|
|
61
|
-
...setup.listener
|
|
62
|
-
})
|
|
55
|
+
listener = await createPeer(setup.listener)
|
|
63
56
|
}
|
|
64
57
|
|
|
65
|
-
|
|
58
|
+
const dialAddrs = listener?.getMultiaddrs() ?? setup.dialAddrs
|
|
66
59
|
|
|
67
60
|
if (dialAddrs == null) {
|
|
68
61
|
throw new Error('Listener config or dial addresses must be specified')
|
|
69
62
|
}
|
|
70
63
|
|
|
71
|
-
dialAddrs = dialAddrs.filter(ma => setup.dialMultiaddrMatcher.exactMatch(ma))
|
|
72
|
-
|
|
73
|
-
if (dialAddrs.length === 0) {
|
|
74
|
-
throw new Error('Listener was not listening on any addresses that the dialMultiaddrMatcher matched')
|
|
75
|
-
}
|
|
76
|
-
|
|
77
64
|
return {
|
|
78
65
|
dialer,
|
|
79
66
|
listener,
|
|
80
|
-
dialAddrs,
|
|
67
|
+
dialAddrs: dialAddrs.filter(ma => setup.dialMultiaddrMatcher.exactMatch(ma)),
|
|
81
68
|
dialMultiaddrMatcher: setup.dialMultiaddrMatcher,
|
|
82
69
|
listenMultiaddrMatcher: setup.listenMultiaddrMatcher
|
|
83
70
|
}
|
|
84
71
|
}
|
|
85
72
|
|
|
86
73
|
export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
87
|
-
describe('transport events', () => {
|
|
88
|
-
let dialer: Libp2p<{ echo: Echo }>
|
|
89
|
-
let listener: Libp2p<{ echo: Echo }> | undefined
|
|
90
|
-
let listenMultiaddrMatcher: MultiaddrMatcher
|
|
91
|
-
|
|
92
|
-
afterEach(async () => {
|
|
93
|
-
await stop(dialer, listener)
|
|
94
|
-
await common.teardown()
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it('emits listening', async function () {
|
|
98
|
-
({ dialer, listener, listenMultiaddrMatcher } = await getSetup(common))
|
|
99
|
-
|
|
100
|
-
if (listener == null) {
|
|
101
|
-
return this.skip()
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
await listener.stop()
|
|
105
|
-
|
|
106
|
-
const transportListeningPromise = Promise.withResolvers<void>()
|
|
107
|
-
|
|
108
|
-
listener.addEventListener('transport:listening', (event) => {
|
|
109
|
-
const transportListener = event.detail
|
|
110
|
-
|
|
111
|
-
if (transportListener.getAddrs().some(ma => listenMultiaddrMatcher.exactMatch(ma))) {
|
|
112
|
-
transportListeningPromise.resolve()
|
|
113
|
-
}
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
await listener.start()
|
|
117
|
-
|
|
118
|
-
await raceSignal(transportListeningPromise.promise, AbortSignal.timeout(1000), {
|
|
119
|
-
translateError: () => {
|
|
120
|
-
return new TimeoutError('Did not emit listening event')
|
|
121
|
-
}
|
|
122
|
-
})
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
it('emits close', async function () {
|
|
126
|
-
({ dialer, listener } = await getSetup(common))
|
|
127
|
-
|
|
128
|
-
if (listener == null) {
|
|
129
|
-
return this.skip()
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const transportManager = getTransportManager(listener)
|
|
133
|
-
const transportListener = transportManager.getListeners()
|
|
134
|
-
.filter(listener => listener.getAddrs().some(ma => listenMultiaddrMatcher.exactMatch(ma)))
|
|
135
|
-
.pop()
|
|
136
|
-
|
|
137
|
-
if (transportListener == null) {
|
|
138
|
-
throw new Error('Could not find address listener')
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const p = pEvent(transportListener, 'close')
|
|
142
|
-
|
|
143
|
-
await listener.stop()
|
|
144
|
-
|
|
145
|
-
await raceSignal(p, AbortSignal.timeout(1000), {
|
|
146
|
-
translateError: () => {
|
|
147
|
-
return new TimeoutError('Did not emit close event')
|
|
148
|
-
}
|
|
149
|
-
})
|
|
150
|
-
})
|
|
151
|
-
})
|
|
152
|
-
|
|
153
74
|
describe('interface-transport', () => {
|
|
154
75
|
let dialer: Libp2p<{ echo: Echo }>
|
|
155
76
|
let listener: Libp2p<{ echo: Echo }> | undefined
|
|
156
77
|
let dialAddrs: Multiaddr[]
|
|
157
78
|
let dialMultiaddrMatcher: MultiaddrMatcher
|
|
158
|
-
let listenMultiaddrMatcher: MultiaddrMatcher
|
|
159
79
|
|
|
160
80
|
afterEach(async () => {
|
|
161
81
|
await stop(dialer, listener)
|
|
@@ -170,7 +90,7 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
170
90
|
signal: AbortSignal.timeout(5000)
|
|
171
91
|
})
|
|
172
92
|
|
|
173
|
-
expect(output
|
|
93
|
+
expect(output).to.equalBytes(input)
|
|
174
94
|
})
|
|
175
95
|
|
|
176
96
|
it('should listen on multiple addresses', async () => {
|
|
@@ -178,16 +98,13 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
178
98
|
|
|
179
99
|
const input = Uint8Array.from([0, 1, 2, 3, 4])
|
|
180
100
|
|
|
181
|
-
|
|
101
|
+
await expect(dialer.services.echo.echo(dialAddrs[0], input, {
|
|
182
102
|
signal: AbortSignal.timeout(5000)
|
|
183
|
-
})
|
|
184
|
-
expect(output1.subarray()).to.equalBytes(input)
|
|
103
|
+
})).to.eventually.deep.equal(input)
|
|
185
104
|
|
|
186
|
-
|
|
187
|
-
signal: AbortSignal.timeout(5000)
|
|
188
|
-
|
|
189
|
-
})
|
|
190
|
-
expect(output2.subarray()).to.equalBytes(input)
|
|
105
|
+
await expect(dialer.services.echo.echo(dialAddrs[1], input, {
|
|
106
|
+
signal: AbortSignal.timeout(5000)
|
|
107
|
+
})).to.eventually.deep.equal(input)
|
|
191
108
|
})
|
|
192
109
|
|
|
193
110
|
it('can close connections', async () => {
|
|
@@ -214,20 +131,16 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
214
131
|
})
|
|
215
132
|
|
|
216
133
|
it('should close all streams when the connection closes', async () => {
|
|
217
|
-
({ dialer, listener, dialAddrs
|
|
134
|
+
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
218
135
|
|
|
219
|
-
let incomingConnectionPromise:
|
|
136
|
+
let incomingConnectionPromise: DeferredPromise<Connection> | undefined
|
|
220
137
|
|
|
221
138
|
if (listener != null) {
|
|
222
|
-
incomingConnectionPromise =
|
|
139
|
+
incomingConnectionPromise = pDefer<Connection>()
|
|
223
140
|
|
|
224
141
|
listener.addEventListener('connection:open', (event) => {
|
|
225
142
|
const conn = event.detail
|
|
226
143
|
|
|
227
|
-
if (!listenMultiaddrMatcher.matches(conn.remoteAddr)) {
|
|
228
|
-
return
|
|
229
|
-
}
|
|
230
|
-
|
|
231
144
|
if (conn.remotePeer.equals(dialer.peerId)) {
|
|
232
145
|
incomingConnectionPromise?.resolve(conn)
|
|
233
146
|
}
|
|
@@ -247,29 +160,22 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
247
160
|
})
|
|
248
161
|
}
|
|
249
162
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (remoteConn != null) {
|
|
253
|
-
await pWaitFor(() => remoteConn.streams.filter(s => s.protocol === '/echo/1.0.0').length === 5, {
|
|
254
|
-
timeout: 5_000,
|
|
255
|
-
interval: 1_000
|
|
256
|
-
})
|
|
257
|
-
}
|
|
163
|
+
const streams = connection.streams
|
|
258
164
|
|
|
259
165
|
// Close the connection and verify all streams have been closed
|
|
260
|
-
await
|
|
261
|
-
pEvent(connection, 'close'),
|
|
262
|
-
pEvent(remoteConn ?? connection, 'close'),
|
|
263
|
-
connection.close()
|
|
264
|
-
])
|
|
166
|
+
await connection.close()
|
|
265
167
|
|
|
266
|
-
|
|
267
|
-
|
|
168
|
+
await pWaitFor(() => connection.streams.length === 0, {
|
|
169
|
+
timeout: 5000
|
|
170
|
+
})
|
|
268
171
|
|
|
269
172
|
if (remoteConn != null) {
|
|
270
|
-
|
|
271
|
-
|
|
173
|
+
await pWaitFor(() => remoteConn.streams.length === 0, {
|
|
174
|
+
timeout: 5000
|
|
175
|
+
})
|
|
272
176
|
}
|
|
177
|
+
|
|
178
|
+
expect(streams.find(stream => stream.status === 'open')).to.be.undefined()
|
|
273
179
|
})
|
|
274
180
|
|
|
275
181
|
it('should not handle connection if upgradeInbound rejects', async function () {
|
|
@@ -321,138 +227,189 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
321
227
|
}
|
|
322
228
|
})
|
|
323
229
|
|
|
324
|
-
it('should handle one
|
|
230
|
+
it('should handle one big write', async function () {
|
|
325
231
|
const timeout = 120_000
|
|
326
232
|
this.timeout(timeout);
|
|
327
233
|
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
328
234
|
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
const input = new Uint8Array(1024).fill(5)
|
|
332
|
-
const output = await dialer.services.echo.echo(connection.remotePeer, input, {
|
|
235
|
+
const input = new Uint8Array(1024 * 1024 * 10).fill(5)
|
|
236
|
+
const output = await dialer.services.echo.echo(dialAddrs[0], input, {
|
|
333
237
|
signal: AbortSignal.timeout(timeout)
|
|
334
238
|
})
|
|
335
239
|
|
|
336
|
-
expect(output
|
|
337
|
-
expect(connection.streams.filter(s => s.protocol === dialer.services.echo.protocol)).to.be.empty()
|
|
240
|
+
expect(output).to.equalBytes(input)
|
|
338
241
|
})
|
|
339
242
|
|
|
340
|
-
it('should handle
|
|
341
|
-
const timeout =
|
|
243
|
+
it('should handle many small writes', async function () {
|
|
244
|
+
const timeout = 360_000
|
|
342
245
|
this.timeout(timeout);
|
|
343
246
|
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
344
247
|
|
|
345
|
-
|
|
248
|
+
for (let i = 0; i < 2000; i++) {
|
|
249
|
+
const input = new Uint8Array(1024).fill(5)
|
|
250
|
+
const output = await dialer.services.echo.echo(dialAddrs[0], input, {
|
|
251
|
+
signal: AbortSignal.timeout(timeout)
|
|
252
|
+
})
|
|
346
253
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
254
|
+
expect(output).to.equalBytes(input)
|
|
255
|
+
}
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
it('can close a stream for reading but send a large amount of data', async function () {
|
|
259
|
+
const timeout = 120_000
|
|
260
|
+
this.timeout(timeout);
|
|
261
|
+
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
262
|
+
|
|
263
|
+
if (listener == null) {
|
|
264
|
+
return this.skip()
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const protocol = '/send-data/1.0.0'
|
|
268
|
+
const chunkSize = 1024
|
|
269
|
+
const bytes = chunkSize * 1024 * 10
|
|
270
|
+
const deferred = pDefer()
|
|
271
|
+
|
|
272
|
+
await listener.handle(protocol, ({ stream }) => {
|
|
273
|
+
Promise.resolve().then(async () => {
|
|
274
|
+
let read = 0
|
|
275
|
+
|
|
276
|
+
for await (const buf of stream.source) {
|
|
277
|
+
read += buf.byteLength
|
|
278
|
+
|
|
279
|
+
if (read === bytes) {
|
|
280
|
+
deferred.resolve()
|
|
281
|
+
break
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
})
|
|
285
|
+
.catch(err => {
|
|
286
|
+
deferred.reject(err)
|
|
287
|
+
stream.abort(err)
|
|
288
|
+
})
|
|
350
289
|
})
|
|
351
290
|
|
|
352
|
-
|
|
353
|
-
|
|
291
|
+
const stream = await dialer.dialProtocol(dialAddrs[0], protocol)
|
|
292
|
+
|
|
293
|
+
await stream.closeRead()
|
|
294
|
+
|
|
295
|
+
await stream.sink((async function * () {
|
|
296
|
+
for (let i = 0; i < bytes; i += chunkSize) {
|
|
297
|
+
yield new Uint8Array(chunkSize)
|
|
298
|
+
}
|
|
299
|
+
})())
|
|
300
|
+
|
|
301
|
+
await stream.close()
|
|
302
|
+
|
|
303
|
+
await deferred.promise
|
|
354
304
|
})
|
|
355
305
|
|
|
356
|
-
it('
|
|
357
|
-
const timeout =
|
|
306
|
+
it('can close a stream for writing but receive a large amount of data', async function () {
|
|
307
|
+
const timeout = 120_000
|
|
358
308
|
this.timeout(timeout);
|
|
359
309
|
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
360
310
|
|
|
361
|
-
|
|
362
|
-
|
|
311
|
+
if (listener == null) {
|
|
312
|
+
return this.skip()
|
|
313
|
+
}
|
|
363
314
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
315
|
+
const protocol = '/receive-data/1.0.0'
|
|
316
|
+
const chunkSize = 1024
|
|
317
|
+
const bytes = chunkSize * 1024 * 10
|
|
318
|
+
const deferred = pDefer()
|
|
319
|
+
|
|
320
|
+
await listener.handle(protocol, ({ stream }) => {
|
|
321
|
+
Promise.resolve().then(async () => {
|
|
322
|
+
await stream.sink((async function * () {
|
|
323
|
+
for (let i = 0; i < bytes; i += chunkSize) {
|
|
324
|
+
yield new Uint8Array(chunkSize)
|
|
325
|
+
}
|
|
326
|
+
})())
|
|
327
|
+
|
|
328
|
+
await stream.close()
|
|
368
329
|
})
|
|
330
|
+
.catch(err => {
|
|
331
|
+
deferred.reject(err)
|
|
332
|
+
stream.abort(err)
|
|
333
|
+
})
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
const stream = await dialer.dialProtocol(dialAddrs[0], protocol)
|
|
337
|
+
|
|
338
|
+
await stream.closeWrite()
|
|
369
339
|
|
|
370
|
-
|
|
371
|
-
|
|
340
|
+
let read = 0
|
|
341
|
+
|
|
342
|
+
for await (const buf of stream.source) {
|
|
343
|
+
read += buf.byteLength
|
|
372
344
|
}
|
|
345
|
+
|
|
346
|
+
expect(read).to.equal(bytes)
|
|
373
347
|
})
|
|
374
348
|
|
|
375
|
-
it('can close local stream while a remote stream is writing', async function () {
|
|
349
|
+
it('can close local stream for writing and reading while a remote stream is writing', async function () {
|
|
376
350
|
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
377
351
|
|
|
378
352
|
if (listener == null) {
|
|
379
353
|
return this.skip()
|
|
380
354
|
}
|
|
381
355
|
|
|
382
|
-
// 1. remote stream close read
|
|
383
|
-
// 2. local stream close write
|
|
384
|
-
// 3. remote stream close write
|
|
385
|
-
|
|
386
356
|
/**
|
|
387
357
|
* NodeA NodeB
|
|
388
358
|
* | <--- STOP_SENDING |
|
|
389
359
|
* | FIN ---> |
|
|
390
|
-
* | <--- DATA |
|
|
391
360
|
* | <--- FIN |
|
|
392
361
|
* | FIN_ACK ---> |
|
|
393
362
|
* | <--- FIN_ACK |
|
|
394
363
|
*/
|
|
395
364
|
|
|
396
|
-
const getRemoteStream =
|
|
365
|
+
const getRemoteStream = pDefer<Stream>()
|
|
397
366
|
const protocol = '/close-local-while-remote-writes/1.0.0'
|
|
398
367
|
|
|
399
|
-
const streamHandler: StreamHandler = (stream) => {
|
|
400
|
-
|
|
368
|
+
const streamHandler: StreamHandler = ({ stream }) => {
|
|
369
|
+
void Promise.resolve().then(async () => {
|
|
370
|
+
getRemoteStream.resolve(stream)
|
|
371
|
+
})
|
|
401
372
|
}
|
|
402
373
|
|
|
403
|
-
await listener.handle(protocol,
|
|
374
|
+
await listener.handle(protocol, (info) => {
|
|
375
|
+
streamHandler(info)
|
|
376
|
+
}, {
|
|
404
377
|
runOnLimitedConnection: true
|
|
405
378
|
})
|
|
406
379
|
|
|
407
380
|
const connection = await dialer.dial(dialAddrs[0])
|
|
408
381
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
// ignore incoming data
|
|
421
|
-
void drain(localStream)
|
|
422
|
-
|
|
423
|
-
// close the remote readable end
|
|
382
|
+
// open a stream on the echo protocol
|
|
383
|
+
const stream = await connection.newStream(protocol, {
|
|
384
|
+
runOnLimitedConnection: true
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
// close the write end immediately
|
|
388
|
+
const p = stream.closeWrite()
|
|
389
|
+
|
|
390
|
+
const remoteStream = await getRemoteStream.promise
|
|
391
|
+
// close the readable end of the remote stream
|
|
424
392
|
await remoteStream.closeRead()
|
|
425
393
|
|
|
426
|
-
//
|
|
394
|
+
// keep the remote write end open, this should delay the FIN_ACK reply to the local stream
|
|
427
395
|
const remoteInputStream = pushable<Uint8Array>()
|
|
428
|
-
|
|
429
|
-
for await (const buf of remoteInputStream) {
|
|
430
|
-
const sendMore = remoteStream.send(buf)
|
|
431
|
-
|
|
432
|
-
if (sendMore === false) {
|
|
433
|
-
await pEvent(remoteStream, 'drain', {
|
|
434
|
-
rejectionEvents: [
|
|
435
|
-
'close'
|
|
436
|
-
]
|
|
437
|
-
})
|
|
438
|
-
}
|
|
439
|
-
}
|
|
396
|
+
void remoteStream.sink(remoteInputStream)
|
|
440
397
|
|
|
441
|
-
|
|
442
|
-
|
|
398
|
+
// wait for remote to receive local close-write
|
|
399
|
+
await pRetry(() => {
|
|
400
|
+
if (remoteStream.readStatus !== 'closed') {
|
|
401
|
+
throw new Error('Remote stream read status ' + remoteStream.readStatus)
|
|
402
|
+
}
|
|
403
|
+
}, {
|
|
404
|
+
minTimeout: 100
|
|
443
405
|
})
|
|
444
406
|
|
|
445
|
-
|
|
446
|
-
// wait for remote to receive local FIN
|
|
447
|
-
pEvent(remoteStream, 'remoteCloseWrite'),
|
|
448
|
-
|
|
449
|
-
// wait to receive FIN_ACK
|
|
450
|
-
localStream.close()
|
|
451
|
-
])
|
|
452
|
-
|
|
453
|
-
// stop sending remote -> local
|
|
407
|
+
// remote closes write
|
|
454
408
|
remoteInputStream.end()
|
|
455
409
|
|
|
410
|
+
// wait to receive FIN_ACK
|
|
411
|
+
await p
|
|
412
|
+
|
|
456
413
|
// wait for remote to notice closure
|
|
457
414
|
await pRetry(() => {
|
|
458
415
|
if (remoteStream.status !== 'closed') {
|
|
@@ -460,12 +417,11 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
460
417
|
}
|
|
461
418
|
})
|
|
462
419
|
|
|
463
|
-
|
|
464
|
-
assertStreamClosed(localStream)
|
|
420
|
+
assertStreamClosed(stream)
|
|
465
421
|
assertStreamClosed(remoteStream)
|
|
466
422
|
})
|
|
467
423
|
|
|
468
|
-
it('can close local stream for writing while a remote stream is
|
|
424
|
+
it('can close local stream for writing and reading while a remote stream is writing using source/sink', async function () {
|
|
469
425
|
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
470
426
|
|
|
471
427
|
if (listener == null) {
|
|
@@ -474,80 +430,62 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
474
430
|
|
|
475
431
|
/**
|
|
476
432
|
* NodeA NodeB
|
|
477
|
-
* | DATA ---> |
|
|
478
433
|
* | FIN ---> |
|
|
479
434
|
* | <--- FIN |
|
|
480
435
|
* | FIN_ACK ---> |
|
|
481
436
|
* | <--- FIN_ACK |
|
|
482
437
|
*/
|
|
483
438
|
|
|
484
|
-
const getRemoteStream =
|
|
439
|
+
const getRemoteStream = pDefer<Stream>()
|
|
485
440
|
const protocol = '/close-local-while-remote-reads/1.0.0'
|
|
486
441
|
|
|
487
|
-
const streamHandler: StreamHandler = (stream) => {
|
|
488
|
-
|
|
442
|
+
const streamHandler: StreamHandler = ({ stream }) => {
|
|
443
|
+
void Promise.resolve().then(async () => {
|
|
444
|
+
getRemoteStream.resolve(stream)
|
|
445
|
+
})
|
|
489
446
|
}
|
|
490
447
|
|
|
491
|
-
await listener.handle(protocol,
|
|
448
|
+
await listener.handle(protocol, (info) => {
|
|
449
|
+
streamHandler(info)
|
|
450
|
+
}, {
|
|
492
451
|
runOnLimitedConnection: true
|
|
493
452
|
})
|
|
494
453
|
|
|
495
454
|
const connection = await dialer.dial(dialAddrs[0])
|
|
496
455
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
] = await Promise.all([
|
|
501
|
-
// open a stream on the echo protocol
|
|
502
|
-
connection.newStream(protocol, {
|
|
503
|
-
runOnLimitedConnection: true
|
|
504
|
-
}),
|
|
505
|
-
getRemoteStream.promise
|
|
506
|
-
])
|
|
507
|
-
|
|
508
|
-
// ignore incoming data
|
|
509
|
-
void drain(remoteStream)
|
|
510
|
-
|
|
511
|
-
// close the remote stream writable end when the local sends a FIN
|
|
512
|
-
remoteStream.addEventListener('remoteCloseWrite', () => {
|
|
513
|
-
remoteStream.close()
|
|
514
|
-
.catch(err => {
|
|
515
|
-
remoteStream.abort(err)
|
|
516
|
-
})
|
|
456
|
+
// open a stream on the echo protocol
|
|
457
|
+
const stream = await connection.newStream(protocol, {
|
|
458
|
+
runOnLimitedConnection: true
|
|
517
459
|
})
|
|
518
460
|
|
|
519
|
-
//
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
]
|
|
540
|
-
})
|
|
541
|
-
}
|
|
542
|
-
}
|
|
461
|
+
// keep the remote write end open, this should delay the FIN_ACK reply to the local stream
|
|
462
|
+
const p = stream.sink([])
|
|
463
|
+
|
|
464
|
+
const remoteStream = await getRemoteStream.promise
|
|
465
|
+
// close the readable end of the remote stream
|
|
466
|
+
await remoteStream.closeRead()
|
|
467
|
+
// readable end should finish
|
|
468
|
+
await drain(remoteStream.source)
|
|
469
|
+
|
|
470
|
+
// wait for remote to receive local close-write
|
|
471
|
+
await pRetry(() => {
|
|
472
|
+
if (remoteStream.readStatus !== 'closed') {
|
|
473
|
+
throw new Error('Remote stream read status ' + remoteStream.readStatus)
|
|
474
|
+
}
|
|
475
|
+
}, {
|
|
476
|
+
minTimeout: 100
|
|
477
|
+
})
|
|
478
|
+
|
|
479
|
+
// remote closes write
|
|
480
|
+
await remoteStream.sink([])
|
|
543
481
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
})()
|
|
547
|
-
])
|
|
482
|
+
// wait to receive FIN_ACK
|
|
483
|
+
await p
|
|
548
484
|
|
|
549
|
-
|
|
550
|
-
|
|
485
|
+
// close read end of stream
|
|
486
|
+
await stream.closeRead()
|
|
487
|
+
// readable end should finish
|
|
488
|
+
await drain(stream.source)
|
|
551
489
|
|
|
552
490
|
// wait for remote to notice closure
|
|
553
491
|
await pRetry(() => {
|
|
@@ -556,50 +494,70 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
556
494
|
}
|
|
557
495
|
})
|
|
558
496
|
|
|
559
|
-
|
|
560
|
-
assertStreamClosed(localStream)
|
|
497
|
+
assertStreamClosed(stream)
|
|
561
498
|
assertStreamClosed(remoteStream)
|
|
562
499
|
})
|
|
500
|
+
})
|
|
563
501
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
502
|
+
describe('events', () => {
|
|
503
|
+
let dialer: Libp2p<{ echo: Echo }>
|
|
504
|
+
let listener: Libp2p<{ echo: Echo }> | undefined
|
|
505
|
+
let listenMultiaddrMatcher: MultiaddrMatcher
|
|
506
|
+
|
|
507
|
+
afterEach(async () => {
|
|
508
|
+
await stop(dialer, listener)
|
|
509
|
+
await common.teardown()
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
it('emits listening', async function () {
|
|
513
|
+
({ dialer, listener, listenMultiaddrMatcher } = await getSetup(common))
|
|
568
514
|
|
|
569
515
|
if (listener == null) {
|
|
570
516
|
return this.skip()
|
|
571
517
|
}
|
|
572
518
|
|
|
573
|
-
|
|
574
|
-
const chunkSize = 1024
|
|
575
|
-
const bytes = chunkSize * 1024 * 10
|
|
519
|
+
await listener.stop()
|
|
576
520
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
'close'
|
|
585
|
-
]
|
|
586
|
-
})
|
|
587
|
-
}
|
|
521
|
+
const transportListeningPromise = pDefer()
|
|
522
|
+
|
|
523
|
+
listener.addEventListener('transport:listening', (event) => {
|
|
524
|
+
const transportListener = event.detail
|
|
525
|
+
|
|
526
|
+
if (transportListener.getAddrs().some(ma => listenMultiaddrMatcher.exactMatch(ma))) {
|
|
527
|
+
transportListeningPromise.resolve()
|
|
588
528
|
}
|
|
529
|
+
})
|
|
589
530
|
|
|
590
|
-
|
|
531
|
+
await listener.start()
|
|
532
|
+
|
|
533
|
+
await raceSignal(transportListeningPromise.promise, AbortSignal.timeout(1000), {
|
|
534
|
+
errorMessage: 'Did not emit listening event'
|
|
591
535
|
})
|
|
536
|
+
})
|
|
592
537
|
|
|
593
|
-
|
|
538
|
+
it('emits close', async function () {
|
|
539
|
+
({ dialer, listener } = await getSetup(common))
|
|
540
|
+
|
|
541
|
+
if (listener == null) {
|
|
542
|
+
return this.skip()
|
|
543
|
+
}
|
|
594
544
|
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
545
|
+
const transportManager = getTransportManager(listener)
|
|
546
|
+
const transportListener = transportManager.getListeners()
|
|
547
|
+
.filter(listener => listener.getAddrs().some(ma => listenMultiaddrMatcher.exactMatch(ma)))
|
|
548
|
+
.pop()
|
|
549
|
+
|
|
550
|
+
if (transportListener == null) {
|
|
551
|
+
throw new Error('Could not find address listener')
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
const p = pEvent(transportListener, 'close')
|
|
601
555
|
|
|
602
|
-
|
|
556
|
+
await listener.stop()
|
|
557
|
+
|
|
558
|
+
await raceSignal(p, AbortSignal.timeout(1000), {
|
|
559
|
+
errorMessage: 'Did not emit close event'
|
|
560
|
+
})
|
|
603
561
|
})
|
|
604
562
|
})
|
|
605
563
|
}
|
|
@@ -610,4 +568,6 @@ function assertStreamClosed (stream: Stream): void {
|
|
|
610
568
|
expect(stream.writeStatus).to.equal('closed')
|
|
611
569
|
|
|
612
570
|
expect(stream.timeline.close).to.be.a('number')
|
|
571
|
+
expect(stream.timeline.closeRead).to.be.a('number')
|
|
572
|
+
expect(stream.timeline.closeWrite).to.be.a('number')
|
|
613
573
|
}
|