@libp2p/interface-compliance-tests 6.5.0-8484de8a2 → 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 -253
- 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 +203 -232
- package/dist/src/transport/index.js.map +1 -1
- package/dist/src/transport/utils.js +2 -2
- 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 -304
- 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 -280
- package/src/transport/utils.ts +2 -2
- package/dist/src/stream-muxer/stream-test.d.ts.map +0 -1
- package/dist/src/stream-muxer/stream-test.js +0 -289
- package/dist/src/stream-muxer/stream-test.js.map +0 -1
- package/src/stream-muxer/stream-test.ts +0 -380
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,28 +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.length === 5, {
|
|
254
|
-
timeout: 5000
|
|
255
|
-
})
|
|
256
|
-
}
|
|
163
|
+
const streams = connection.streams
|
|
257
164
|
|
|
258
165
|
// Close the connection and verify all streams have been closed
|
|
259
|
-
await
|
|
260
|
-
pEvent(connection, 'close'),
|
|
261
|
-
pEvent(remoteConn ?? connection, 'close'),
|
|
262
|
-
connection.close()
|
|
263
|
-
])
|
|
166
|
+
await connection.close()
|
|
264
167
|
|
|
265
|
-
|
|
266
|
-
|
|
168
|
+
await pWaitFor(() => connection.streams.length === 0, {
|
|
169
|
+
timeout: 5000
|
|
170
|
+
})
|
|
267
171
|
|
|
268
172
|
if (remoteConn != null) {
|
|
269
|
-
|
|
270
|
-
|
|
173
|
+
await pWaitFor(() => remoteConn.streams.length === 0, {
|
|
174
|
+
timeout: 5000
|
|
175
|
+
})
|
|
271
176
|
}
|
|
177
|
+
|
|
178
|
+
expect(streams.find(stream => stream.status === 'open')).to.be.undefined()
|
|
272
179
|
})
|
|
273
180
|
|
|
274
181
|
it('should not handle connection if upgradeInbound rejects', async function () {
|
|
@@ -320,138 +227,189 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
320
227
|
}
|
|
321
228
|
})
|
|
322
229
|
|
|
323
|
-
it('should handle one
|
|
230
|
+
it('should handle one big write', async function () {
|
|
324
231
|
const timeout = 120_000
|
|
325
232
|
this.timeout(timeout);
|
|
326
233
|
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
327
234
|
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
const input = new Uint8Array(1024).fill(5)
|
|
331
|
-
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, {
|
|
332
237
|
signal: AbortSignal.timeout(timeout)
|
|
333
238
|
})
|
|
334
239
|
|
|
335
|
-
expect(output
|
|
336
|
-
expect(connection.streams.filter(s => s.protocol === dialer.services.echo.protocol)).to.be.empty()
|
|
240
|
+
expect(output).to.equalBytes(input)
|
|
337
241
|
})
|
|
338
242
|
|
|
339
|
-
it('should handle
|
|
340
|
-
const timeout =
|
|
243
|
+
it('should handle many small writes', async function () {
|
|
244
|
+
const timeout = 360_000
|
|
341
245
|
this.timeout(timeout);
|
|
342
246
|
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
343
247
|
|
|
344
|
-
|
|
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
|
+
})
|
|
345
253
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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
|
+
})
|
|
349
289
|
})
|
|
350
290
|
|
|
351
|
-
|
|
352
|
-
|
|
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
|
|
353
304
|
})
|
|
354
305
|
|
|
355
|
-
it('
|
|
356
|
-
const timeout =
|
|
306
|
+
it('can close a stream for writing but receive a large amount of data', async function () {
|
|
307
|
+
const timeout = 120_000
|
|
357
308
|
this.timeout(timeout);
|
|
358
309
|
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
359
310
|
|
|
360
|
-
|
|
361
|
-
|
|
311
|
+
if (listener == null) {
|
|
312
|
+
return this.skip()
|
|
313
|
+
}
|
|
362
314
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
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()
|
|
367
329
|
})
|
|
330
|
+
.catch(err => {
|
|
331
|
+
deferred.reject(err)
|
|
332
|
+
stream.abort(err)
|
|
333
|
+
})
|
|
334
|
+
})
|
|
368
335
|
|
|
369
|
-
|
|
370
|
-
|
|
336
|
+
const stream = await dialer.dialProtocol(dialAddrs[0], protocol)
|
|
337
|
+
|
|
338
|
+
await stream.closeWrite()
|
|
339
|
+
|
|
340
|
+
let read = 0
|
|
341
|
+
|
|
342
|
+
for await (const buf of stream.source) {
|
|
343
|
+
read += buf.byteLength
|
|
371
344
|
}
|
|
345
|
+
|
|
346
|
+
expect(read).to.equal(bytes)
|
|
372
347
|
})
|
|
373
348
|
|
|
374
|
-
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 () {
|
|
375
350
|
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
376
351
|
|
|
377
352
|
if (listener == null) {
|
|
378
353
|
return this.skip()
|
|
379
354
|
}
|
|
380
355
|
|
|
381
|
-
// 1. remote stream close read
|
|
382
|
-
// 2. local stream close write
|
|
383
|
-
// 3. remote stream close write
|
|
384
|
-
|
|
385
356
|
/**
|
|
386
357
|
* NodeA NodeB
|
|
387
358
|
* | <--- STOP_SENDING |
|
|
388
359
|
* | FIN ---> |
|
|
389
|
-
* | <--- DATA |
|
|
390
360
|
* | <--- FIN |
|
|
391
361
|
* | FIN_ACK ---> |
|
|
392
362
|
* | <--- FIN_ACK |
|
|
393
363
|
*/
|
|
394
364
|
|
|
395
|
-
const getRemoteStream =
|
|
365
|
+
const getRemoteStream = pDefer<Stream>()
|
|
396
366
|
const protocol = '/close-local-while-remote-writes/1.0.0'
|
|
397
367
|
|
|
398
|
-
const streamHandler: StreamHandler = (stream) => {
|
|
399
|
-
|
|
368
|
+
const streamHandler: StreamHandler = ({ stream }) => {
|
|
369
|
+
void Promise.resolve().then(async () => {
|
|
370
|
+
getRemoteStream.resolve(stream)
|
|
371
|
+
})
|
|
400
372
|
}
|
|
401
373
|
|
|
402
|
-
await listener.handle(protocol,
|
|
374
|
+
await listener.handle(protocol, (info) => {
|
|
375
|
+
streamHandler(info)
|
|
376
|
+
}, {
|
|
403
377
|
runOnLimitedConnection: true
|
|
404
378
|
})
|
|
405
379
|
|
|
406
380
|
const connection = await dialer.dial(dialAddrs[0])
|
|
407
381
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
// ignore incoming data
|
|
420
|
-
void drain(localStream)
|
|
421
|
-
|
|
422
|
-
// 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
|
|
423
392
|
await remoteStream.closeRead()
|
|
424
393
|
|
|
425
|
-
//
|
|
394
|
+
// keep the remote write end open, this should delay the FIN_ACK reply to the local stream
|
|
426
395
|
const remoteInputStream = pushable<Uint8Array>()
|
|
427
|
-
|
|
428
|
-
for await (const buf of remoteInputStream) {
|
|
429
|
-
const sendMore = remoteStream.send(buf)
|
|
430
|
-
|
|
431
|
-
if (sendMore === false) {
|
|
432
|
-
await pEvent(remoteStream, 'drain', {
|
|
433
|
-
rejectionEvents: [
|
|
434
|
-
'close'
|
|
435
|
-
]
|
|
436
|
-
})
|
|
437
|
-
}
|
|
438
|
-
}
|
|
396
|
+
void remoteStream.sink(remoteInputStream)
|
|
439
397
|
|
|
440
|
-
|
|
441
|
-
|
|
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
|
|
442
405
|
})
|
|
443
406
|
|
|
444
|
-
|
|
445
|
-
// wait for remote to receive local FIN
|
|
446
|
-
pEvent(remoteStream, 'remoteCloseWrite'),
|
|
447
|
-
|
|
448
|
-
// wait to receive FIN_ACK
|
|
449
|
-
localStream.close()
|
|
450
|
-
])
|
|
451
|
-
|
|
452
|
-
// stop sending remote -> local
|
|
407
|
+
// remote closes write
|
|
453
408
|
remoteInputStream.end()
|
|
454
409
|
|
|
410
|
+
// wait to receive FIN_ACK
|
|
411
|
+
await p
|
|
412
|
+
|
|
455
413
|
// wait for remote to notice closure
|
|
456
414
|
await pRetry(() => {
|
|
457
415
|
if (remoteStream.status !== 'closed') {
|
|
@@ -459,12 +417,11 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
459
417
|
}
|
|
460
418
|
})
|
|
461
419
|
|
|
462
|
-
|
|
463
|
-
assertStreamClosed(localStream)
|
|
420
|
+
assertStreamClosed(stream)
|
|
464
421
|
assertStreamClosed(remoteStream)
|
|
465
422
|
})
|
|
466
423
|
|
|
467
|
-
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 () {
|
|
468
425
|
({ dialer, listener, dialAddrs } = await getSetup(common))
|
|
469
426
|
|
|
470
427
|
if (listener == null) {
|
|
@@ -473,80 +430,62 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
473
430
|
|
|
474
431
|
/**
|
|
475
432
|
* NodeA NodeB
|
|
476
|
-
* | DATA ---> |
|
|
477
433
|
* | FIN ---> |
|
|
478
434
|
* | <--- FIN |
|
|
479
435
|
* | FIN_ACK ---> |
|
|
480
436
|
* | <--- FIN_ACK |
|
|
481
437
|
*/
|
|
482
438
|
|
|
483
|
-
const getRemoteStream =
|
|
439
|
+
const getRemoteStream = pDefer<Stream>()
|
|
484
440
|
const protocol = '/close-local-while-remote-reads/1.0.0'
|
|
485
441
|
|
|
486
|
-
const streamHandler: StreamHandler = (stream) => {
|
|
487
|
-
|
|
442
|
+
const streamHandler: StreamHandler = ({ stream }) => {
|
|
443
|
+
void Promise.resolve().then(async () => {
|
|
444
|
+
getRemoteStream.resolve(stream)
|
|
445
|
+
})
|
|
488
446
|
}
|
|
489
447
|
|
|
490
|
-
await listener.handle(protocol,
|
|
448
|
+
await listener.handle(protocol, (info) => {
|
|
449
|
+
streamHandler(info)
|
|
450
|
+
}, {
|
|
491
451
|
runOnLimitedConnection: true
|
|
492
452
|
})
|
|
493
453
|
|
|
494
454
|
const connection = await dialer.dial(dialAddrs[0])
|
|
495
455
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
] = await Promise.all([
|
|
500
|
-
// open a stream on the echo protocol
|
|
501
|
-
connection.newStream(protocol, {
|
|
502
|
-
runOnLimitedConnection: true
|
|
503
|
-
}),
|
|
504
|
-
getRemoteStream.promise
|
|
505
|
-
])
|
|
506
|
-
|
|
507
|
-
// ignore incoming data
|
|
508
|
-
void drain(remoteStream)
|
|
509
|
-
|
|
510
|
-
// close the remote stream writable end when the local sends a FIN
|
|
511
|
-
remoteStream.addEventListener('remoteCloseWrite', () => {
|
|
512
|
-
remoteStream.close()
|
|
513
|
-
.catch(err => {
|
|
514
|
-
remoteStream.abort(err)
|
|
515
|
-
})
|
|
456
|
+
// open a stream on the echo protocol
|
|
457
|
+
const stream = await connection.newStream(protocol, {
|
|
458
|
+
runOnLimitedConnection: true
|
|
516
459
|
})
|
|
517
460
|
|
|
518
|
-
//
|
|
519
|
-
const
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
await pEvent(localStream, 'drain', {
|
|
536
|
-
rejectionEvents: [
|
|
537
|
-
'close'
|
|
538
|
-
]
|
|
539
|
-
})
|
|
540
|
-
}
|
|
541
|
-
}
|
|
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
|
+
})
|
|
542
478
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
})()
|
|
546
|
-
])
|
|
479
|
+
// remote closes write
|
|
480
|
+
await remoteStream.sink([])
|
|
547
481
|
|
|
548
|
-
|
|
549
|
-
|
|
482
|
+
// wait to receive FIN_ACK
|
|
483
|
+
await p
|
|
484
|
+
|
|
485
|
+
// close read end of stream
|
|
486
|
+
await stream.closeRead()
|
|
487
|
+
// readable end should finish
|
|
488
|
+
await drain(stream.source)
|
|
550
489
|
|
|
551
490
|
// wait for remote to notice closure
|
|
552
491
|
await pRetry(() => {
|
|
@@ -555,50 +494,70 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
|
555
494
|
}
|
|
556
495
|
})
|
|
557
496
|
|
|
558
|
-
|
|
559
|
-
assertStreamClosed(localStream)
|
|
497
|
+
assertStreamClosed(stream)
|
|
560
498
|
assertStreamClosed(remoteStream)
|
|
561
499
|
})
|
|
500
|
+
})
|
|
562
501
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
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))
|
|
567
514
|
|
|
568
515
|
if (listener == null) {
|
|
569
516
|
return this.skip()
|
|
570
517
|
}
|
|
571
518
|
|
|
572
|
-
|
|
573
|
-
const chunkSize = 1024
|
|
574
|
-
const bytes = chunkSize * 1024 * 10
|
|
519
|
+
await listener.stop()
|
|
575
520
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
'close'
|
|
584
|
-
]
|
|
585
|
-
})
|
|
586
|
-
}
|
|
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()
|
|
587
528
|
}
|
|
529
|
+
})
|
|
588
530
|
|
|
589
|
-
|
|
531
|
+
await listener.start()
|
|
532
|
+
|
|
533
|
+
await raceSignal(transportListeningPromise.promise, AbortSignal.timeout(1000), {
|
|
534
|
+
errorMessage: 'Did not emit listening event'
|
|
590
535
|
})
|
|
536
|
+
})
|
|
591
537
|
|
|
592
|
-
|
|
538
|
+
it('emits close', async function () {
|
|
539
|
+
({ dialer, listener } = await getSetup(common))
|
|
540
|
+
|
|
541
|
+
if (listener == null) {
|
|
542
|
+
return this.skip()
|
|
543
|
+
}
|
|
593
544
|
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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')
|
|
600
555
|
|
|
601
|
-
|
|
556
|
+
await listener.stop()
|
|
557
|
+
|
|
558
|
+
await raceSignal(p, AbortSignal.timeout(1000), {
|
|
559
|
+
errorMessage: 'Did not emit close event'
|
|
560
|
+
})
|
|
602
561
|
})
|
|
603
562
|
})
|
|
604
563
|
}
|
|
@@ -609,4 +568,6 @@ function assertStreamClosed (stream: Stream): void {
|
|
|
609
568
|
expect(stream.writeStatus).to.equal('closed')
|
|
610
569
|
|
|
611
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')
|
|
612
573
|
}
|