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