@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
|
@@ -1,102 +1,40 @@
|
|
|
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
|
async function getSetup(common) {
|
|
16
14
|
const setup = await common.setup();
|
|
17
|
-
const dialer = await createPeer(
|
|
18
|
-
logger: prefixLogger('dialer'),
|
|
19
|
-
...setup.dialer
|
|
20
|
-
});
|
|
15
|
+
const dialer = await createPeer(setup.dialer);
|
|
21
16
|
let listener;
|
|
22
17
|
if (setup.listener != null) {
|
|
23
|
-
listener = await createPeer(
|
|
24
|
-
logger: prefixLogger('listener'),
|
|
25
|
-
...setup.listener
|
|
26
|
-
});
|
|
18
|
+
listener = await createPeer(setup.listener);
|
|
27
19
|
}
|
|
28
|
-
|
|
20
|
+
const dialAddrs = listener?.getMultiaddrs() ?? setup.dialAddrs;
|
|
29
21
|
if (dialAddrs == null) {
|
|
30
22
|
throw new Error('Listener config or dial addresses must be specified');
|
|
31
23
|
}
|
|
32
|
-
dialAddrs = dialAddrs.filter(ma => setup.dialMultiaddrMatcher.exactMatch(ma));
|
|
33
|
-
if (dialAddrs.length === 0) {
|
|
34
|
-
throw new Error('Listener was not listening on any addresses that the dialMultiaddrMatcher matched');
|
|
35
|
-
}
|
|
36
24
|
return {
|
|
37
25
|
dialer,
|
|
38
26
|
listener,
|
|
39
|
-
dialAddrs,
|
|
27
|
+
dialAddrs: dialAddrs.filter(ma => setup.dialMultiaddrMatcher.exactMatch(ma)),
|
|
40
28
|
dialMultiaddrMatcher: setup.dialMultiaddrMatcher,
|
|
41
29
|
listenMultiaddrMatcher: setup.listenMultiaddrMatcher
|
|
42
30
|
};
|
|
43
31
|
}
|
|
44
32
|
export default (common) => {
|
|
45
|
-
describe('transport events', () => {
|
|
46
|
-
let dialer;
|
|
47
|
-
let listener;
|
|
48
|
-
let listenMultiaddrMatcher;
|
|
49
|
-
afterEach(async () => {
|
|
50
|
-
await stop(dialer, listener);
|
|
51
|
-
await common.teardown();
|
|
52
|
-
});
|
|
53
|
-
it('emits listening', async function () {
|
|
54
|
-
({ dialer, listener, listenMultiaddrMatcher } = await getSetup(common));
|
|
55
|
-
if (listener == null) {
|
|
56
|
-
return this.skip();
|
|
57
|
-
}
|
|
58
|
-
await listener.stop();
|
|
59
|
-
const transportListeningPromise = Promise.withResolvers();
|
|
60
|
-
listener.addEventListener('transport:listening', (event) => {
|
|
61
|
-
const transportListener = event.detail;
|
|
62
|
-
if (transportListener.getAddrs().some(ma => listenMultiaddrMatcher.exactMatch(ma))) {
|
|
63
|
-
transportListeningPromise.resolve();
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
await listener.start();
|
|
67
|
-
await raceSignal(transportListeningPromise.promise, AbortSignal.timeout(1000), {
|
|
68
|
-
translateError: () => {
|
|
69
|
-
return new TimeoutError('Did not emit listening event');
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
it('emits close', async function () {
|
|
74
|
-
({ dialer, listener } = await getSetup(common));
|
|
75
|
-
if (listener == null) {
|
|
76
|
-
return this.skip();
|
|
77
|
-
}
|
|
78
|
-
const transportManager = getTransportManager(listener);
|
|
79
|
-
const transportListener = transportManager.getListeners()
|
|
80
|
-
.filter(listener => listener.getAddrs().some(ma => listenMultiaddrMatcher.exactMatch(ma)))
|
|
81
|
-
.pop();
|
|
82
|
-
if (transportListener == null) {
|
|
83
|
-
throw new Error('Could not find address listener');
|
|
84
|
-
}
|
|
85
|
-
const p = pEvent(transportListener, 'close');
|
|
86
|
-
await listener.stop();
|
|
87
|
-
await raceSignal(p, AbortSignal.timeout(1000), {
|
|
88
|
-
translateError: () => {
|
|
89
|
-
return new TimeoutError('Did not emit close event');
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
33
|
describe('interface-transport', () => {
|
|
95
34
|
let dialer;
|
|
96
35
|
let listener;
|
|
97
36
|
let dialAddrs;
|
|
98
37
|
let dialMultiaddrMatcher;
|
|
99
|
-
let listenMultiaddrMatcher;
|
|
100
38
|
afterEach(async () => {
|
|
101
39
|
await stop(dialer, listener);
|
|
102
40
|
await common.teardown();
|
|
@@ -107,20 +45,17 @@ export default (common) => {
|
|
|
107
45
|
const output = await dialer.services.echo.echo(dialAddrs[0], input, {
|
|
108
46
|
signal: AbortSignal.timeout(5000)
|
|
109
47
|
});
|
|
110
|
-
expect(output
|
|
48
|
+
expect(output).to.equalBytes(input);
|
|
111
49
|
});
|
|
112
50
|
it('should listen on multiple addresses', async () => {
|
|
113
51
|
({ dialer, listener, dialAddrs } = await getSetup(common));
|
|
114
52
|
const input = Uint8Array.from([0, 1, 2, 3, 4]);
|
|
115
|
-
|
|
53
|
+
await expect(dialer.services.echo.echo(dialAddrs[0], input, {
|
|
116
54
|
signal: AbortSignal.timeout(5000)
|
|
117
|
-
});
|
|
118
|
-
expect(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
force: true
|
|
122
|
-
});
|
|
123
|
-
expect(output2.subarray()).to.equalBytes(input);
|
|
55
|
+
})).to.eventually.deep.equal(input);
|
|
56
|
+
await expect(dialer.services.echo.echo(dialAddrs[1], input, {
|
|
57
|
+
signal: AbortSignal.timeout(5000)
|
|
58
|
+
})).to.eventually.deep.equal(input);
|
|
124
59
|
});
|
|
125
60
|
it('can close connections', async () => {
|
|
126
61
|
({ dialer, listener, dialAddrs } = await getSetup(common));
|
|
@@ -140,15 +75,12 @@ export default (common) => {
|
|
|
140
75
|
.with.property('name', 'AbortError');
|
|
141
76
|
});
|
|
142
77
|
it('should close all streams when the connection closes', async () => {
|
|
143
|
-
({ dialer, listener, dialAddrs
|
|
78
|
+
({ dialer, listener, dialAddrs } = await getSetup(common));
|
|
144
79
|
let incomingConnectionPromise;
|
|
145
80
|
if (listener != null) {
|
|
146
|
-
incomingConnectionPromise =
|
|
81
|
+
incomingConnectionPromise = pDefer();
|
|
147
82
|
listener.addEventListener('connection:open', (event) => {
|
|
148
83
|
const conn = event.detail;
|
|
149
|
-
if (!listenMultiaddrMatcher.matches(conn.remoteAddr)) {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
84
|
if (conn.remotePeer.equals(dialer.peerId)) {
|
|
153
85
|
incomingConnectionPromise?.resolve(conn);
|
|
154
86
|
}
|
|
@@ -164,25 +96,18 @@ export default (common) => {
|
|
|
164
96
|
maxOutboundStreams: 5
|
|
165
97
|
});
|
|
166
98
|
}
|
|
167
|
-
|
|
168
|
-
if (remoteConn != null) {
|
|
169
|
-
await pWaitFor(() => remoteConn.streams.filter(s => s.protocol === '/echo/1.0.0').length === 5, {
|
|
170
|
-
timeout: 5_000,
|
|
171
|
-
interval: 1_000
|
|
172
|
-
});
|
|
173
|
-
}
|
|
99
|
+
const streams = connection.streams;
|
|
174
100
|
// Close the connection and verify all streams have been closed
|
|
175
|
-
await
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
]);
|
|
180
|
-
expect(connection).to.have.property('status', 'closed');
|
|
181
|
-
expect(connection).to.have.property('streams').that.is.empty();
|
|
101
|
+
await connection.close();
|
|
102
|
+
await pWaitFor(() => connection.streams.length === 0, {
|
|
103
|
+
timeout: 5000
|
|
104
|
+
});
|
|
182
105
|
if (remoteConn != null) {
|
|
183
|
-
|
|
184
|
-
|
|
106
|
+
await pWaitFor(() => remoteConn.streams.length === 0, {
|
|
107
|
+
timeout: 5000
|
|
108
|
+
});
|
|
185
109
|
}
|
|
110
|
+
expect(streams.find(stream => stream.status === 'open')).to.be.undefined();
|
|
186
111
|
});
|
|
187
112
|
it('should not handle connection if upgradeInbound rejects', async function () {
|
|
188
113
|
({ dialer, listener, dialAddrs, dialMultiaddrMatcher } = await getSetup(common));
|
|
@@ -223,219 +148,262 @@ export default (common) => {
|
|
|
223
148
|
}
|
|
224
149
|
}
|
|
225
150
|
});
|
|
226
|
-
it('should handle one small write', async function () {
|
|
227
|
-
const timeout = 120_000;
|
|
228
|
-
this.timeout(timeout);
|
|
229
|
-
({ dialer, listener, dialAddrs } = await getSetup(common));
|
|
230
|
-
const connection = await dialer.dial(dialAddrs[0]);
|
|
231
|
-
const input = new Uint8Array(1024).fill(5);
|
|
232
|
-
const output = await dialer.services.echo.echo(connection.remotePeer, input, {
|
|
233
|
-
signal: AbortSignal.timeout(timeout)
|
|
234
|
-
});
|
|
235
|
-
expect(output.subarray()).to.equalBytes(input);
|
|
236
|
-
expect(connection.streams.filter(s => s.protocol === dialer.services.echo.protocol)).to.be.empty();
|
|
237
|
-
});
|
|
238
151
|
it('should handle one big write', async function () {
|
|
239
|
-
const timeout =
|
|
152
|
+
const timeout = 120_000;
|
|
240
153
|
this.timeout(timeout);
|
|
241
154
|
({ dialer, listener, dialAddrs } = await getSetup(common));
|
|
242
|
-
const connection = await dialer.dial(dialAddrs[0]);
|
|
243
155
|
const input = new Uint8Array(1024 * 1024 * 10).fill(5);
|
|
244
|
-
const output = await dialer.services.echo.echo(
|
|
156
|
+
const output = await dialer.services.echo.echo(dialAddrs[0], input, {
|
|
245
157
|
signal: AbortSignal.timeout(timeout)
|
|
246
158
|
});
|
|
247
|
-
expect(output
|
|
248
|
-
expect(connection.streams.filter(s => s.protocol === dialer.services.echo.protocol)).to.be.empty();
|
|
159
|
+
expect(output).to.equalBytes(input);
|
|
249
160
|
});
|
|
250
161
|
it('should handle many small writes', async function () {
|
|
251
162
|
const timeout = 360_000;
|
|
252
163
|
this.timeout(timeout);
|
|
253
164
|
({ dialer, listener, dialAddrs } = await getSetup(common));
|
|
254
|
-
|
|
255
|
-
const echoProtocol = dialer.services.echo.protocol;
|
|
256
|
-
for (let i = 0; i < 2_000; i++) {
|
|
165
|
+
for (let i = 0; i < 2000; i++) {
|
|
257
166
|
const input = new Uint8Array(1024).fill(5);
|
|
258
|
-
const output = await dialer.services.echo.echo(
|
|
167
|
+
const output = await dialer.services.echo.echo(dialAddrs[0], input, {
|
|
259
168
|
signal: AbortSignal.timeout(timeout)
|
|
260
169
|
});
|
|
261
|
-
expect(output
|
|
262
|
-
|
|
170
|
+
expect(output).to.equalBytes(input);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
it('can close a stream for reading but send a large amount of data', async function () {
|
|
174
|
+
const timeout = 120_000;
|
|
175
|
+
this.timeout(timeout);
|
|
176
|
+
({ dialer, listener, dialAddrs } = await getSetup(common));
|
|
177
|
+
if (listener == null) {
|
|
178
|
+
return this.skip();
|
|
179
|
+
}
|
|
180
|
+
const protocol = '/send-data/1.0.0';
|
|
181
|
+
const chunkSize = 1024;
|
|
182
|
+
const bytes = chunkSize * 1024 * 10;
|
|
183
|
+
const deferred = pDefer();
|
|
184
|
+
await listener.handle(protocol, ({ stream }) => {
|
|
185
|
+
Promise.resolve().then(async () => {
|
|
186
|
+
let read = 0;
|
|
187
|
+
for await (const buf of stream.source) {
|
|
188
|
+
read += buf.byteLength;
|
|
189
|
+
if (read === bytes) {
|
|
190
|
+
deferred.resolve();
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
.catch(err => {
|
|
196
|
+
deferred.reject(err);
|
|
197
|
+
stream.abort(err);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
const stream = await dialer.dialProtocol(dialAddrs[0], protocol);
|
|
201
|
+
await stream.closeRead();
|
|
202
|
+
await stream.sink((async function* () {
|
|
203
|
+
for (let i = 0; i < bytes; i += chunkSize) {
|
|
204
|
+
yield new Uint8Array(chunkSize);
|
|
205
|
+
}
|
|
206
|
+
})());
|
|
207
|
+
await stream.close();
|
|
208
|
+
await deferred.promise;
|
|
209
|
+
});
|
|
210
|
+
it('can close a stream for writing but receive a large amount of data', async function () {
|
|
211
|
+
const timeout = 120_000;
|
|
212
|
+
this.timeout(timeout);
|
|
213
|
+
({ dialer, listener, dialAddrs } = await getSetup(common));
|
|
214
|
+
if (listener == null) {
|
|
215
|
+
return this.skip();
|
|
216
|
+
}
|
|
217
|
+
const protocol = '/receive-data/1.0.0';
|
|
218
|
+
const chunkSize = 1024;
|
|
219
|
+
const bytes = chunkSize * 1024 * 10;
|
|
220
|
+
const deferred = pDefer();
|
|
221
|
+
await listener.handle(protocol, ({ stream }) => {
|
|
222
|
+
Promise.resolve().then(async () => {
|
|
223
|
+
await stream.sink((async function* () {
|
|
224
|
+
for (let i = 0; i < bytes; i += chunkSize) {
|
|
225
|
+
yield new Uint8Array(chunkSize);
|
|
226
|
+
}
|
|
227
|
+
})());
|
|
228
|
+
await stream.close();
|
|
229
|
+
})
|
|
230
|
+
.catch(err => {
|
|
231
|
+
deferred.reject(err);
|
|
232
|
+
stream.abort(err);
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
const stream = await dialer.dialProtocol(dialAddrs[0], protocol);
|
|
236
|
+
await stream.closeWrite();
|
|
237
|
+
let read = 0;
|
|
238
|
+
for await (const buf of stream.source) {
|
|
239
|
+
read += buf.byteLength;
|
|
263
240
|
}
|
|
241
|
+
expect(read).to.equal(bytes);
|
|
264
242
|
});
|
|
265
|
-
it('can close local stream while a remote stream is writing', async function () {
|
|
243
|
+
it('can close local stream for writing and reading while a remote stream is writing', async function () {
|
|
266
244
|
({ dialer, listener, dialAddrs } = await getSetup(common));
|
|
267
245
|
if (listener == null) {
|
|
268
246
|
return this.skip();
|
|
269
247
|
}
|
|
270
|
-
// 1. remote stream close read
|
|
271
|
-
// 2. local stream close write
|
|
272
|
-
// 3. remote stream close write
|
|
273
248
|
/**
|
|
274
249
|
* NodeA NodeB
|
|
275
250
|
* | <--- STOP_SENDING |
|
|
276
251
|
* | FIN ---> |
|
|
277
|
-
* | <--- DATA |
|
|
278
252
|
* | <--- FIN |
|
|
279
253
|
* | FIN_ACK ---> |
|
|
280
254
|
* | <--- FIN_ACK |
|
|
281
255
|
*/
|
|
282
|
-
const getRemoteStream =
|
|
256
|
+
const getRemoteStream = pDefer();
|
|
283
257
|
const protocol = '/close-local-while-remote-writes/1.0.0';
|
|
284
|
-
const streamHandler = (stream) => {
|
|
285
|
-
|
|
258
|
+
const streamHandler = ({ stream }) => {
|
|
259
|
+
void Promise.resolve().then(async () => {
|
|
260
|
+
getRemoteStream.resolve(stream);
|
|
261
|
+
});
|
|
286
262
|
};
|
|
287
|
-
await listener.handle(protocol,
|
|
263
|
+
await listener.handle(protocol, (info) => {
|
|
264
|
+
streamHandler(info);
|
|
265
|
+
}, {
|
|
288
266
|
runOnLimitedConnection: true
|
|
289
267
|
});
|
|
290
268
|
const connection = await dialer.dial(dialAddrs[0]);
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
//
|
|
299
|
-
void drain(localStream);
|
|
300
|
-
// close the remote readable end
|
|
269
|
+
// open a stream on the echo protocol
|
|
270
|
+
const stream = await connection.newStream(protocol, {
|
|
271
|
+
runOnLimitedConnection: true
|
|
272
|
+
});
|
|
273
|
+
// close the write end immediately
|
|
274
|
+
const p = stream.closeWrite();
|
|
275
|
+
const remoteStream = await getRemoteStream.promise;
|
|
276
|
+
// close the readable end of the remote stream
|
|
301
277
|
await remoteStream.closeRead();
|
|
302
|
-
//
|
|
278
|
+
// keep the remote write end open, this should delay the FIN_ACK reply to the local stream
|
|
303
279
|
const remoteInputStream = pushable();
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
rejectionEvents: [
|
|
310
|
-
'close'
|
|
311
|
-
]
|
|
312
|
-
});
|
|
313
|
-
}
|
|
280
|
+
void remoteStream.sink(remoteInputStream);
|
|
281
|
+
// wait for remote to receive local close-write
|
|
282
|
+
await pRetry(() => {
|
|
283
|
+
if (remoteStream.readStatus !== 'closed') {
|
|
284
|
+
throw new Error('Remote stream read status ' + remoteStream.readStatus);
|
|
314
285
|
}
|
|
315
|
-
|
|
316
|
-
|
|
286
|
+
}, {
|
|
287
|
+
minTimeout: 100
|
|
317
288
|
});
|
|
318
|
-
|
|
319
|
-
// wait for remote to receive local FIN
|
|
320
|
-
pEvent(remoteStream, 'remoteCloseWrite'),
|
|
321
|
-
// wait to receive FIN_ACK
|
|
322
|
-
localStream.close()
|
|
323
|
-
]);
|
|
324
|
-
// stop sending remote -> local
|
|
289
|
+
// remote closes write
|
|
325
290
|
remoteInputStream.end();
|
|
291
|
+
// wait to receive FIN_ACK
|
|
292
|
+
await p;
|
|
326
293
|
// wait for remote to notice closure
|
|
327
294
|
await pRetry(() => {
|
|
328
295
|
if (remoteStream.status !== 'closed') {
|
|
329
296
|
throw new Error('Remote stream not closed');
|
|
330
297
|
}
|
|
331
298
|
});
|
|
332
|
-
|
|
333
|
-
assertStreamClosed(localStream);
|
|
299
|
+
assertStreamClosed(stream);
|
|
334
300
|
assertStreamClosed(remoteStream);
|
|
335
301
|
});
|
|
336
|
-
it('can close local stream for writing while a remote stream is
|
|
302
|
+
it('can close local stream for writing and reading while a remote stream is writing using source/sink', async function () {
|
|
337
303
|
({ dialer, listener, dialAddrs } = await getSetup(common));
|
|
338
304
|
if (listener == null) {
|
|
339
305
|
return this.skip();
|
|
340
306
|
}
|
|
341
307
|
/**
|
|
342
308
|
* NodeA NodeB
|
|
343
|
-
* | DATA ---> |
|
|
344
309
|
* | FIN ---> |
|
|
345
310
|
* | <--- FIN |
|
|
346
311
|
* | FIN_ACK ---> |
|
|
347
312
|
* | <--- FIN_ACK |
|
|
348
313
|
*/
|
|
349
|
-
const getRemoteStream =
|
|
314
|
+
const getRemoteStream = pDefer();
|
|
350
315
|
const protocol = '/close-local-while-remote-reads/1.0.0';
|
|
351
|
-
const streamHandler = (stream) => {
|
|
352
|
-
|
|
316
|
+
const streamHandler = ({ stream }) => {
|
|
317
|
+
void Promise.resolve().then(async () => {
|
|
318
|
+
getRemoteStream.resolve(stream);
|
|
319
|
+
});
|
|
353
320
|
};
|
|
354
|
-
await listener.handle(protocol,
|
|
321
|
+
await listener.handle(protocol, (info) => {
|
|
322
|
+
streamHandler(info);
|
|
323
|
+
}, {
|
|
355
324
|
runOnLimitedConnection: true
|
|
356
325
|
});
|
|
357
326
|
const connection = await dialer.dial(dialAddrs[0]);
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
runOnLimitedConnection: true
|
|
362
|
-
}),
|
|
363
|
-
getRemoteStream.promise
|
|
364
|
-
]);
|
|
365
|
-
// ignore incoming data
|
|
366
|
-
void drain(remoteStream);
|
|
367
|
-
// close the remote stream writable end when the local sends a FIN
|
|
368
|
-
remoteStream.addEventListener('remoteCloseWrite', () => {
|
|
369
|
-
remoteStream.close()
|
|
370
|
-
.catch(err => {
|
|
371
|
-
remoteStream.abort(err);
|
|
372
|
-
});
|
|
327
|
+
// open a stream on the echo protocol
|
|
328
|
+
const stream = await connection.newStream(protocol, {
|
|
329
|
+
runOnLimitedConnection: true
|
|
373
330
|
});
|
|
374
|
-
//
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
]);
|
|
398
|
-
expect(remoteCloseEvent).to.not.have.property('error', 'remote stream did not close cleanly');
|
|
399
|
-
expect(localCloseEvent).to.not.have.property('error', 'local stream did not close cleanly');
|
|
331
|
+
// keep the remote write end open, this should delay the FIN_ACK reply to the local stream
|
|
332
|
+
const p = stream.sink([]);
|
|
333
|
+
const remoteStream = await getRemoteStream.promise;
|
|
334
|
+
// close the readable end of the remote stream
|
|
335
|
+
await remoteStream.closeRead();
|
|
336
|
+
// readable end should finish
|
|
337
|
+
await drain(remoteStream.source);
|
|
338
|
+
// wait for remote to receive local close-write
|
|
339
|
+
await pRetry(() => {
|
|
340
|
+
if (remoteStream.readStatus !== 'closed') {
|
|
341
|
+
throw new Error('Remote stream read status ' + remoteStream.readStatus);
|
|
342
|
+
}
|
|
343
|
+
}, {
|
|
344
|
+
minTimeout: 100
|
|
345
|
+
});
|
|
346
|
+
// remote closes write
|
|
347
|
+
await remoteStream.sink([]);
|
|
348
|
+
// wait to receive FIN_ACK
|
|
349
|
+
await p;
|
|
350
|
+
// close read end of stream
|
|
351
|
+
await stream.closeRead();
|
|
352
|
+
// readable end should finish
|
|
353
|
+
await drain(stream.source);
|
|
400
354
|
// wait for remote to notice closure
|
|
401
355
|
await pRetry(() => {
|
|
402
356
|
if (remoteStream.status !== 'closed') {
|
|
403
357
|
throw new Error('Remote stream not closed');
|
|
404
358
|
}
|
|
405
359
|
});
|
|
406
|
-
|
|
407
|
-
assertStreamClosed(localStream);
|
|
360
|
+
assertStreamClosed(stream);
|
|
408
361
|
assertStreamClosed(remoteStream);
|
|
409
362
|
});
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
363
|
+
});
|
|
364
|
+
describe('events', () => {
|
|
365
|
+
let dialer;
|
|
366
|
+
let listener;
|
|
367
|
+
let listenMultiaddrMatcher;
|
|
368
|
+
afterEach(async () => {
|
|
369
|
+
await stop(dialer, listener);
|
|
370
|
+
await common.teardown();
|
|
371
|
+
});
|
|
372
|
+
it('emits listening', async function () {
|
|
373
|
+
({ dialer, listener, listenMultiaddrMatcher } = await getSetup(common));
|
|
414
374
|
if (listener == null) {
|
|
415
375
|
return this.skip();
|
|
416
376
|
}
|
|
417
|
-
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
if (!sendMore) {
|
|
424
|
-
await pEvent(stream, 'drain', {
|
|
425
|
-
rejectionEvents: [
|
|
426
|
-
'close'
|
|
427
|
-
]
|
|
428
|
-
});
|
|
429
|
-
}
|
|
377
|
+
await listener.stop();
|
|
378
|
+
const transportListeningPromise = pDefer();
|
|
379
|
+
listener.addEventListener('transport:listening', (event) => {
|
|
380
|
+
const transportListener = event.detail;
|
|
381
|
+
if (transportListener.getAddrs().some(ma => listenMultiaddrMatcher.exactMatch(ma))) {
|
|
382
|
+
transportListeningPromise.resolve();
|
|
430
383
|
}
|
|
431
|
-
await stream.close();
|
|
432
384
|
});
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
385
|
+
await listener.start();
|
|
386
|
+
await raceSignal(transportListeningPromise.promise, AbortSignal.timeout(1000), {
|
|
387
|
+
errorMessage: 'Did not emit listening event'
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
it('emits close', async function () {
|
|
391
|
+
({ dialer, listener } = await getSetup(common));
|
|
392
|
+
if (listener == null) {
|
|
393
|
+
return this.skip();
|
|
394
|
+
}
|
|
395
|
+
const transportManager = getTransportManager(listener);
|
|
396
|
+
const transportListener = transportManager.getListeners()
|
|
397
|
+
.filter(listener => listener.getAddrs().some(ma => listenMultiaddrMatcher.exactMatch(ma)))
|
|
398
|
+
.pop();
|
|
399
|
+
if (transportListener == null) {
|
|
400
|
+
throw new Error('Could not find address listener');
|
|
401
|
+
}
|
|
402
|
+
const p = pEvent(transportListener, 'close');
|
|
403
|
+
await listener.stop();
|
|
404
|
+
await raceSignal(p, AbortSignal.timeout(1000), {
|
|
405
|
+
errorMessage: 'Did not emit close event'
|
|
406
|
+
});
|
|
439
407
|
});
|
|
440
408
|
});
|
|
441
409
|
};
|
|
@@ -444,5 +412,7 @@ function assertStreamClosed(stream) {
|
|
|
444
412
|
expect(stream.readStatus).to.equal('closed');
|
|
445
413
|
expect(stream.writeStatus).to.equal('closed');
|
|
446
414
|
expect(stream.timeline.close).to.be.a('number');
|
|
415
|
+
expect(stream.timeline.closeRead).to.be.a('number');
|
|
416
|
+
expect(stream.timeline.closeWrite).to.be.a('number');
|
|
447
417
|
}
|
|
448
418
|
//# sourceMappingURL=index.js.map
|