@libp2p/interface-compliance-tests 6.5.0 → 7.0.0-049bfa0fa
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 -345
- 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 -320
- 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 +290 -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 +235 -205
- 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 +3 -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 -413
- package/src/stream-muxer/close-test.ts +305 -343
- package/src/stream-muxer/index.ts +2 -2
- package/src/stream-muxer/stream-test.ts +381 -0
- package/src/stream-muxer/stress-test.ts +92 -18
- package/src/transport/index.ts +281 -241
- package/src/transport/utils.ts +3 -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 -236
- 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 -39
- 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 -309
- 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 -57
|
@@ -1,408 +1,342 @@
|
|
|
1
1
|
/* eslint max-nested-callbacks: ["error", 8] */
|
|
2
|
-
import {
|
|
2
|
+
import { multiaddrConnectionPair, echo, pbStream } from '@libp2p/utils';
|
|
3
3
|
import { expect } from 'aegir/chai';
|
|
4
4
|
import delay from 'delay';
|
|
5
5
|
import all from 'it-all';
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import { pipe } from 'it-pipe';
|
|
9
|
-
import { pbStream } from 'it-protobuf-stream';
|
|
10
|
-
import toBuffer from 'it-to-buffer';
|
|
11
|
-
import pDefer from 'p-defer';
|
|
6
|
+
import map from 'it-map';
|
|
7
|
+
import { pEvent } from 'p-event';
|
|
12
8
|
import { Uint8ArrayList } from 'uint8arraylist';
|
|
13
9
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
|
|
14
10
|
import { Message } from './fixtures/pb/message.js';
|
|
15
11
|
function randomBuffer() {
|
|
16
12
|
return uint8ArrayFromString(Math.random().toString());
|
|
17
13
|
}
|
|
18
|
-
function infiniteRandom() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
},
|
|
24
|
-
async next() {
|
|
25
|
-
await delay(10);
|
|
26
|
-
if (done instanceof Error) {
|
|
27
|
-
throw done;
|
|
28
|
-
}
|
|
29
|
-
if (done) {
|
|
30
|
-
return {
|
|
31
|
-
done: true,
|
|
32
|
-
value: undefined
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
return {
|
|
36
|
-
done: false,
|
|
37
|
-
value: new Uint8ArrayList(randomBuffer())
|
|
38
|
-
};
|
|
39
|
-
},
|
|
40
|
-
async return() {
|
|
41
|
-
done = true;
|
|
42
|
-
return {
|
|
43
|
-
done: true,
|
|
44
|
-
value: undefined
|
|
45
|
-
};
|
|
46
|
-
},
|
|
47
|
-
async throw(err) {
|
|
48
|
-
done = err;
|
|
49
|
-
return {
|
|
50
|
-
done: true,
|
|
51
|
-
value: undefined
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
return generator;
|
|
14
|
+
async function* infiniteRandom() {
|
|
15
|
+
while (true) {
|
|
16
|
+
await delay(10);
|
|
17
|
+
yield new Uint8ArrayList(randomBuffer());
|
|
18
|
+
}
|
|
56
19
|
}
|
|
57
20
|
export default (common) => {
|
|
58
21
|
describe('close', () => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
22
|
+
let outboundConnection;
|
|
23
|
+
let inboundConnection;
|
|
24
|
+
let dialer;
|
|
25
|
+
let listener;
|
|
26
|
+
beforeEach(async () => {
|
|
27
|
+
[outboundConnection, inboundConnection] = multiaddrConnectionPair();
|
|
62
28
|
const dialerFactory = await common.setup();
|
|
63
|
-
|
|
64
|
-
direction: 'outbound'
|
|
65
|
-
});
|
|
66
|
-
// Listener is echo server :)
|
|
29
|
+
dialer = dialerFactory.createStreamMuxer(outboundConnection);
|
|
67
30
|
const listenerFactory = await common.setup();
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
31
|
+
listener = listenerFactory.createStreamMuxer(inboundConnection);
|
|
32
|
+
});
|
|
33
|
+
afterEach(async () => {
|
|
34
|
+
await dialer?.close();
|
|
35
|
+
await listener?.close();
|
|
36
|
+
});
|
|
37
|
+
it('closing underlying MultiaddrConnection closes streams', async () => {
|
|
38
|
+
let openedStreams = 0;
|
|
39
|
+
const expectedStreams = 5;
|
|
40
|
+
listener.addEventListener('stream', (evt) => {
|
|
41
|
+
openedStreams++;
|
|
42
|
+
echo(evt.detail);
|
|
74
43
|
});
|
|
75
|
-
const
|
|
76
|
-
void pipe(p[0], dialer, p[0]);
|
|
77
|
-
void pipe(p[1], listener, p[1]);
|
|
78
|
-
const streams = await Promise.all(Array(expectedStreams).fill(0).map(async () => dialer.newStream()));
|
|
44
|
+
const streams = await Promise.all(Array(expectedStreams).fill(0).map(async () => dialer.createStream()));
|
|
79
45
|
void Promise.all(streams.map(async (stream) => {
|
|
80
|
-
await
|
|
46
|
+
for await (const buf of infiniteRandom()) {
|
|
47
|
+
if (stream.status !== 'open') {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const sendMore = stream.send(buf);
|
|
51
|
+
if (!sendMore) {
|
|
52
|
+
await pEvent(stream, 'drain', {
|
|
53
|
+
rejectionEvents: [
|
|
54
|
+
'close'
|
|
55
|
+
]
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
81
59
|
}));
|
|
82
60
|
expect(dialer.streams).to.have.lengthOf(expectedStreams);
|
|
83
61
|
// Pause, and then close the dialer
|
|
84
62
|
await delay(50);
|
|
85
|
-
await
|
|
63
|
+
await inboundConnection.close();
|
|
64
|
+
await outboundConnection.close();
|
|
65
|
+
await delay(50);
|
|
86
66
|
expect(openedStreams).to.have.equal(expectedStreams);
|
|
87
67
|
expect(dialer.streams).to.have.lengthOf(0);
|
|
88
68
|
});
|
|
89
69
|
it('calling close closes streams', async () => {
|
|
90
70
|
let openedStreams = 0;
|
|
91
71
|
const expectedStreams = 5;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
72
|
+
listener.addEventListener('stream', (evt) => {
|
|
73
|
+
openedStreams++;
|
|
74
|
+
echo(evt.detail);
|
|
95
75
|
});
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
76
|
+
const streams = await Promise.all(Array(expectedStreams).fill(0).map(async () => dialer.createStream()));
|
|
77
|
+
void Promise.all(streams.map(async (stream) => {
|
|
78
|
+
for await (const buf of infiniteRandom()) {
|
|
79
|
+
if (stream.status !== 'open') {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const sendMore = stream.send(buf);
|
|
83
|
+
if (!sendMore) {
|
|
84
|
+
await pEvent(stream, 'drain', {
|
|
85
|
+
rejectionEvents: [
|
|
86
|
+
'close'
|
|
87
|
+
]
|
|
88
|
+
});
|
|
89
|
+
}
|
|
103
90
|
}
|
|
91
|
+
}))
|
|
92
|
+
.catch(() => {
|
|
93
|
+
// calling .send on a closed stream will throw so swallow any errors
|
|
104
94
|
});
|
|
105
|
-
const p = duplexPair();
|
|
106
|
-
void pipe(p[0], dialer, p[0]);
|
|
107
|
-
void pipe(p[1], listener, p[1]);
|
|
108
|
-
const streams = await Promise.all(Array(expectedStreams).fill(0).map(async () => dialer.newStream()));
|
|
109
|
-
void Promise.all(streams.map(async (stream) => {
|
|
110
|
-
await pipe(infiniteRandom(), stream, drain);
|
|
111
|
-
}));
|
|
112
95
|
expect(dialer.streams, 'dialer - number of opened streams should match number of calls to newStream').to.have.lengthOf(expectedStreams);
|
|
113
96
|
// Pause, and then close the dialer
|
|
114
97
|
await delay(50);
|
|
115
98
|
await dialer.close();
|
|
99
|
+
await delay(50);
|
|
116
100
|
expect(openedStreams, 'listener - number of opened streams should match number of calls to newStream').to.have.equal(expectedStreams);
|
|
117
101
|
expect(dialer.streams, 'all tracked streams should be deleted after the muxer has called close').to.have.lengthOf(0);
|
|
118
102
|
});
|
|
119
|
-
it('calling
|
|
103
|
+
it('calling abort aborts streams', async () => {
|
|
120
104
|
let openedStreams = 0;
|
|
121
105
|
const expectedStreams = 5;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
});
|
|
126
|
-
// Listener is echo server :)
|
|
127
|
-
const listenerFactory = await common.setup();
|
|
128
|
-
const listener = listenerFactory.createStreamMuxer({
|
|
129
|
-
direction: 'inbound',
|
|
130
|
-
onIncomingStream: (stream) => {
|
|
131
|
-
openedStreams++;
|
|
132
|
-
void pipe(stream, stream).catch(() => { });
|
|
133
|
-
}
|
|
106
|
+
listener.addEventListener('stream', (evt) => {
|
|
107
|
+
openedStreams++;
|
|
108
|
+
echo(evt.detail);
|
|
134
109
|
});
|
|
135
|
-
const
|
|
136
|
-
void pipe(p[0], dialer, p[0]);
|
|
137
|
-
void pipe(p[1], listener, p[1]);
|
|
138
|
-
const streams = await Promise.all(Array(expectedStreams).fill(0).map(async () => dialer.newStream()));
|
|
110
|
+
const streams = await Promise.all(Array(expectedStreams).fill(0).map(async () => dialer.createStream()));
|
|
139
111
|
const streamPipes = streams.map(async (stream) => {
|
|
140
|
-
await
|
|
112
|
+
for await (const buf of infiniteRandom()) {
|
|
113
|
+
if (stream.writeStatus !== 'writable') {
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
const sendMore = stream.send(buf);
|
|
117
|
+
if (!sendMore) {
|
|
118
|
+
await pEvent(stream, 'drain', {
|
|
119
|
+
rejectionEvents: ['close']
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
141
123
|
});
|
|
142
|
-
expect(dialer.streams, 'dialer - number of opened streams should match number of calls to
|
|
143
|
-
// Pause, and then close the dialer
|
|
144
|
-
await delay(50);
|
|
145
|
-
// close _with an error_
|
|
146
|
-
dialer.abort(new Error('Oh no!'));
|
|
124
|
+
expect(dialer.streams).to.have.lengthOf(expectedStreams, 'dialer - number of opened streams should match number of calls to createStream');
|
|
147
125
|
const timeoutError = new Error('timeout');
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
126
|
+
await Promise.all([
|
|
127
|
+
// Pause, and then close the dialer
|
|
128
|
+
delay(50).then(() => {
|
|
129
|
+
// close _with an error_
|
|
130
|
+
dialer.abort(new Error('Oh no!'));
|
|
131
|
+
}),
|
|
132
|
+
...streamPipes.map(async (pipe) => {
|
|
133
|
+
try {
|
|
134
|
+
await Promise.race([
|
|
135
|
+
pipe,
|
|
136
|
+
new Promise((resolve, reject) => {
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
reject(timeoutError);
|
|
139
|
+
}, 70);
|
|
140
|
+
})
|
|
141
|
+
]);
|
|
142
|
+
expect.fail('stream pipe with infinite source should never return');
|
|
159
143
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
144
|
+
catch (e) {
|
|
145
|
+
if (e === timeoutError) {
|
|
146
|
+
expect.fail('expected stream pipe to throw an error after muxer closed with error');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
]);
|
|
151
|
+
expect(openedStreams).to.equal(expectedStreams, 'listener - number of opened streams should match number of calls to createStream');
|
|
152
|
+
expect(dialer.streams).to.have.lengthOf(0, 'all tracked streams should be deleted after the muxer has called close');
|
|
164
153
|
});
|
|
165
154
|
it('calling newStream after close throws an error', async () => {
|
|
166
|
-
const dialerFactory = await common.setup();
|
|
167
|
-
const dialer = dialerFactory.createStreamMuxer({
|
|
168
|
-
direction: 'outbound'
|
|
169
|
-
});
|
|
170
155
|
await dialer.close();
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
expect.fail('newStream should throw if called after close');
|
|
174
|
-
}
|
|
175
|
-
catch (e) {
|
|
176
|
-
expect(dialer.streams, 'closed muxer should have no streams').to.have.lengthOf(0);
|
|
177
|
-
}
|
|
156
|
+
await expect(dialer.createStream()).to.eventually.rejected.with.property('name', 'MuxerClosedError');
|
|
157
|
+
expect(dialer.streams).to.have.lengthOf(0, 'closed muxer should have no streams');
|
|
178
158
|
});
|
|
179
159
|
it('closing one of the muxed streams doesn\'t close others', async () => {
|
|
180
|
-
const
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const listenerFactory = await common.setup();
|
|
187
|
-
const listener = listenerFactory.createStreamMuxer({
|
|
188
|
-
direction: 'inbound',
|
|
189
|
-
onIncomingStream: (stream) => {
|
|
190
|
-
void pipe(stream, stream).catch(() => { });
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
void pipe(p[0], dialer, p[0]);
|
|
194
|
-
void pipe(p[1], listener, p[1]);
|
|
195
|
-
const stream = await dialer.newStream();
|
|
196
|
-
const streams = await Promise.all(Array.from(Array(5), async () => dialer.newStream()));
|
|
197
|
-
let closed = false;
|
|
198
|
-
const controllers = [];
|
|
199
|
-
const streamResults = streams.map(async (stream) => {
|
|
200
|
-
const controller = new AbortController();
|
|
201
|
-
controllers.push(controller);
|
|
202
|
-
try {
|
|
203
|
-
const abortableRand = abortableSource(infiniteRandom(), controller.signal, {
|
|
204
|
-
abortName: 'TestAbortError'
|
|
205
|
-
});
|
|
206
|
-
await pipe(abortableRand, stream, drain);
|
|
207
|
-
}
|
|
208
|
-
catch (err) {
|
|
209
|
-
if (err.name !== 'TestAbortError') {
|
|
210
|
-
throw err;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
if (!closed) {
|
|
214
|
-
throw new Error('stream should not have ended yet!');
|
|
160
|
+
const streamCount = 5;
|
|
161
|
+
const allStreamsOpen = Promise.withResolvers();
|
|
162
|
+
listener.addEventListener('stream', (evt) => {
|
|
163
|
+
echo(evt.detail).catch(() => { });
|
|
164
|
+
if (listener.streams.length === streamCount) {
|
|
165
|
+
allStreamsOpen.resolve();
|
|
215
166
|
}
|
|
216
167
|
});
|
|
217
|
-
|
|
218
|
-
await
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
await Promise.all(
|
|
168
|
+
const streams = await Promise.all(Array.from(Array(streamCount), async () => dialer.createStream()));
|
|
169
|
+
await allStreamsOpen.promise;
|
|
170
|
+
expect(dialer.streams).to.have.lengthOf(streamCount);
|
|
171
|
+
expect(listener.streams).to.have.lengthOf(streamCount);
|
|
172
|
+
expect(dialer.streams.map(s => s.status)).to.deep.equal(new Array(streamCount).fill('open'));
|
|
173
|
+
expect(listener.streams.map(s => s.status)).to.deep.equal(new Array(streamCount).fill('open'));
|
|
174
|
+
const localStream = streams[0];
|
|
175
|
+
const remoteStream = listener.streams[0];
|
|
176
|
+
await Promise.all([
|
|
177
|
+
pEvent(remoteStream, 'close'),
|
|
178
|
+
pEvent(localStream, 'close'),
|
|
179
|
+
localStream.close()
|
|
180
|
+
]);
|
|
181
|
+
expect(dialer.streams).to.have.lengthOf(streamCount - 1);
|
|
182
|
+
expect(listener.streams).to.have.lengthOf(streamCount - 1);
|
|
183
|
+
expect(dialer.streams.map(s => s.status)).to.deep.equal(new Array(streamCount - 1).fill('open'));
|
|
184
|
+
expect(listener.streams.map(s => s.status)).to.deep.equal(new Array(streamCount - 1).fill('open'));
|
|
226
185
|
});
|
|
227
186
|
it('can close a stream for writing', async () => {
|
|
228
|
-
const deferred =
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
});
|
|
234
|
-
const data = [randomBuffer(), randomBuffer()];
|
|
235
|
-
const listenerFactory = await common.setup();
|
|
236
|
-
const listener = listenerFactory.createStreamMuxer({
|
|
237
|
-
direction: 'inbound',
|
|
238
|
-
onIncomingStream: (stream) => {
|
|
239
|
-
void Promise.resolve().then(async () => {
|
|
187
|
+
const deferred = Promise.withResolvers();
|
|
188
|
+
const data = [Uint8Array.from([0, 1, 2, 3, 4]), Uint8Array.from([5, 6, 7, 8, 9])];
|
|
189
|
+
listener.addEventListener('stream', (evt) => {
|
|
190
|
+
void Promise.resolve().then(async () => {
|
|
191
|
+
try {
|
|
240
192
|
// Immediate close for write
|
|
241
|
-
await
|
|
242
|
-
|
|
243
|
-
const data = [];
|
|
244
|
-
for await (const chunk of source) {
|
|
245
|
-
data.push(chunk.slice());
|
|
246
|
-
}
|
|
247
|
-
return data;
|
|
193
|
+
await evt.detail.close({
|
|
194
|
+
signal: AbortSignal.timeout(1_000)
|
|
248
195
|
});
|
|
249
|
-
|
|
196
|
+
const results = await all(map(evt.detail, (buf) => {
|
|
197
|
+
return buf.subarray();
|
|
198
|
+
}));
|
|
199
|
+
expect(results).to.deep.equal(data);
|
|
250
200
|
try {
|
|
251
|
-
|
|
201
|
+
evt.detail.send(randomBuffer());
|
|
252
202
|
}
|
|
253
203
|
catch (err) {
|
|
254
204
|
deferred.resolve(err);
|
|
255
205
|
}
|
|
256
|
-
|
|
206
|
+
throw new Error('should not support writing to closed writer');
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
deferred.reject(err);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
const stream = await dialer.createStream();
|
|
214
|
+
for (const buf of data) {
|
|
215
|
+
if (!stream.send(buf)) {
|
|
216
|
+
await pEvent(stream, 'drain', {
|
|
217
|
+
rejectionEvents: [
|
|
218
|
+
'close'
|
|
219
|
+
]
|
|
257
220
|
});
|
|
258
221
|
}
|
|
222
|
+
}
|
|
223
|
+
await stream.close({
|
|
224
|
+
signal: AbortSignal.timeout(1_000)
|
|
259
225
|
});
|
|
260
|
-
void pipe(p[0], dialer, p[0]);
|
|
261
|
-
void pipe(p[1], listener, p[1]);
|
|
262
|
-
const stream = await dialer.newStream();
|
|
263
|
-
await stream.sink(data);
|
|
264
226
|
const err = await deferred.promise;
|
|
265
227
|
expect(err).to.have.property('name', 'StreamStateError');
|
|
266
228
|
});
|
|
267
|
-
it('
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const dialerFactory = await common.setup();
|
|
271
|
-
const dialer = dialerFactory.createStreamMuxer({
|
|
272
|
-
direction: 'outbound'
|
|
273
|
-
});
|
|
274
|
-
const data = [randomBuffer(), randomBuffer()].map(d => new Uint8ArrayList(d));
|
|
275
|
-
const expected = toBuffer(data.map(d => d.subarray()));
|
|
276
|
-
const listenerFactory = await common.setup();
|
|
277
|
-
const listener = listenerFactory.createStreamMuxer({
|
|
278
|
-
direction: 'inbound',
|
|
279
|
-
onIncomingStream: (stream) => {
|
|
280
|
-
void all(stream.source).then(deferred.resolve, deferred.reject);
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
void pipe(p[0], dialer, p[0]);
|
|
284
|
-
void pipe(p[1], listener, p[1]);
|
|
285
|
-
const stream = await dialer.newStream();
|
|
286
|
-
await stream.closeRead();
|
|
287
|
-
// Source should be done
|
|
288
|
-
void Promise.resolve().then(async () => {
|
|
289
|
-
expect(await stream.source.next()).to.have.property('done', true);
|
|
290
|
-
await stream.sink(data);
|
|
229
|
+
it('should emit a close event for closed streams not previously written', async () => {
|
|
230
|
+
listener.addEventListener('stream', async (evt) => {
|
|
231
|
+
void evt.detail.close();
|
|
291
232
|
});
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const deferred = pDefer();
|
|
297
|
-
const onStreamEnd = () => { deferred.resolve(); };
|
|
298
|
-
const dialerFactory = await common.setup();
|
|
299
|
-
const dialer = dialerFactory.createStreamMuxer({
|
|
300
|
-
direction: 'outbound',
|
|
301
|
-
onStreamEnd
|
|
233
|
+
const deferred = Promise.withResolvers();
|
|
234
|
+
const stream = await dialer.createStream();
|
|
235
|
+
stream.addEventListener('close', () => {
|
|
236
|
+
deferred.resolve();
|
|
302
237
|
});
|
|
303
|
-
const stream = await dialer.newStream();
|
|
304
238
|
await stream.close();
|
|
305
239
|
await deferred.promise;
|
|
306
240
|
});
|
|
307
|
-
it('
|
|
308
|
-
const deferred =
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
direction: 'outbound',
|
|
313
|
-
onStreamEnd
|
|
241
|
+
it('should emit a close event for aborted streams not previously written', async () => {
|
|
242
|
+
const deferred = Promise.withResolvers();
|
|
243
|
+
const stream = await dialer.createStream();
|
|
244
|
+
stream.addEventListener('close', () => {
|
|
245
|
+
deferred.resolve();
|
|
314
246
|
});
|
|
315
|
-
|
|
316
|
-
await stream.closeWrite();
|
|
317
|
-
await stream.closeRead();
|
|
247
|
+
stream.abort(new Error('Urk!'));
|
|
318
248
|
await deferred.promise;
|
|
319
249
|
});
|
|
320
250
|
it('should wait for all data to be sent when closing streams', async () => {
|
|
321
|
-
const deferred =
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
void pb.read(Message)
|
|
333
|
-
.then(async (message) => {
|
|
334
|
-
deferred.resolve(message);
|
|
335
|
-
await pb.unwrap().close();
|
|
336
|
-
})
|
|
337
|
-
.catch(err => {
|
|
338
|
-
deferred.reject(err);
|
|
339
|
-
});
|
|
340
|
-
}
|
|
251
|
+
const deferred = Promise.withResolvers();
|
|
252
|
+
listener.addEventListener('stream', (evt) => {
|
|
253
|
+
const pb = pbStream(evt.detail);
|
|
254
|
+
void pb.read(Message)
|
|
255
|
+
.then(async (message) => {
|
|
256
|
+
deferred.resolve(message);
|
|
257
|
+
await evt.detail.close();
|
|
258
|
+
})
|
|
259
|
+
.catch(err => {
|
|
260
|
+
deferred.reject(err);
|
|
261
|
+
});
|
|
341
262
|
});
|
|
342
|
-
void pipe(p[0], dialer, p[0]);
|
|
343
|
-
void pipe(p[1], listener, p[1]);
|
|
344
263
|
const message = {
|
|
345
264
|
message: 'hello world',
|
|
346
265
|
value: 5,
|
|
347
266
|
flag: true
|
|
348
267
|
};
|
|
349
|
-
const stream = await dialer.
|
|
268
|
+
const stream = await dialer.createStream();
|
|
350
269
|
const pb = pbStream(stream);
|
|
351
270
|
await pb.write(message, Message);
|
|
352
|
-
await
|
|
271
|
+
await stream.close();
|
|
353
272
|
await expect(deferred.promise).to.eventually.deep.equal(message);
|
|
354
273
|
});
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
274
|
+
it('should remove a stream in the streams list after aborting', async () => {
|
|
275
|
+
const [listenerStream, dialerStream] = await Promise.all([
|
|
276
|
+
pEvent(listener, 'stream').then(evt => evt.detail),
|
|
277
|
+
dialer.createStream()
|
|
278
|
+
]);
|
|
279
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer did not store outbound stream');
|
|
280
|
+
expect(listener.streams).to.include(listenerStream, 'listener did not store inbound stream');
|
|
281
|
+
await Promise.all([
|
|
282
|
+
pEvent(listenerStream, 'close'),
|
|
283
|
+
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
284
|
+
dialerStream.abort(new Error('Urk!'))
|
|
285
|
+
]);
|
|
286
|
+
expect(dialer.streams).to.not.include(dialerStream, 'dialer did not remove outbound stream close');
|
|
287
|
+
expect(listener.streams).to.not.include(listenerStream, 'listener did not remove inbound stream after close');
|
|
288
|
+
});
|
|
289
|
+
it('should remove a stream in the streams list after closing', async () => {
|
|
290
|
+
const [listenerStream, dialerStream] = await Promise.all([
|
|
291
|
+
pEvent(listener, 'stream').then(evt => evt.detail),
|
|
292
|
+
dialer.createStream()
|
|
293
|
+
]);
|
|
294
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer did not store outbound stream');
|
|
295
|
+
expect(listener.streams).to.include(listenerStream, 'listener did not store inbound stream');
|
|
296
|
+
await Promise.all([
|
|
297
|
+
dialerStream.close(),
|
|
298
|
+
listenerStream.close()
|
|
299
|
+
]);
|
|
300
|
+
await delay(10);
|
|
301
|
+
expect(dialer.streams).to.not.include(dialerStream, 'dialer did not remove outbound stream close');
|
|
302
|
+
expect(listener.streams).to.not.include(listenerStream, 'listener did not remove inbound stream after close');
|
|
303
|
+
});
|
|
304
|
+
it('should not remove a half-closed outbound stream', async () => {
|
|
305
|
+
const [listenerStream, dialerStream] = await Promise.all([
|
|
306
|
+
pEvent(listener, 'stream').then(evt => evt.detail),
|
|
307
|
+
dialer.createStream()
|
|
308
|
+
]);
|
|
309
|
+
await dialerStream.close();
|
|
310
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer did not store outbound stream');
|
|
311
|
+
expect(listener.streams).to.include(listenerStream, 'listener did not store inbound stream');
|
|
312
|
+
});
|
|
313
|
+
it('should not remove a half-closed inbound stream', async () => {
|
|
314
|
+
const [listenerStream, dialerStream] = await Promise.all([
|
|
315
|
+
pEvent(listener, 'stream').then(evt => evt.detail),
|
|
316
|
+
dialer.createStream()
|
|
317
|
+
]);
|
|
318
|
+
await listenerStream.close();
|
|
319
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer did not store outbound stream');
|
|
320
|
+
expect(listener.streams).to.include(listenerStream, 'listener did not store inbound stream');
|
|
321
|
+
});
|
|
322
|
+
it('should remove a stream half closed from both ends', async () => {
|
|
323
|
+
const [listenerStream, dialerStream] = await Promise.all([
|
|
324
|
+
pEvent(listener, 'stream').then(evt => evt.detail),
|
|
325
|
+
dialer.createStream()
|
|
326
|
+
]);
|
|
327
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer did not store outbound stream');
|
|
328
|
+
expect(listener.streams).to.include(listenerStream, 'listener did not store inbound stream');
|
|
329
|
+
await listenerStream.close();
|
|
330
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer removed outbound stream before fully closing');
|
|
331
|
+
expect(listener.streams).to.include(listenerStream, 'listener removed inbound stream before fully closing');
|
|
332
|
+
await Promise.all([
|
|
333
|
+
pEvent(listenerStream, 'close'),
|
|
334
|
+
dialerStream.close()
|
|
335
|
+
]);
|
|
336
|
+
await delay(10);
|
|
337
|
+
expect(dialer.streams).to.not.include(dialerStream, 'dialer did not remove outbound stream close');
|
|
338
|
+
expect(listener.streams).to.not.include(listenerStream, 'listener did not remove inbound stream after close');
|
|
339
|
+
});
|
|
406
340
|
});
|
|
407
341
|
};
|
|
408
342
|
//# sourceMappingURL=close-test.js.map
|