@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
|
@@ -1,392 +1,341 @@
|
|
|
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
|
-
// Listener is echo server :)
|
|
29
|
+
dialer = dialerFactory.createStreamMuxer(outboundConnection);
|
|
65
30
|
const listenerFactory = await common.setup();
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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);
|
|
72
43
|
});
|
|
73
|
-
const
|
|
74
|
-
void pipe(p[0], dialer, p[0]);
|
|
75
|
-
void pipe(p[1], listener, p[1]);
|
|
76
|
-
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()));
|
|
77
45
|
void Promise.all(streams.map(async (stream) => {
|
|
78
|
-
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
|
+
}
|
|
79
59
|
}));
|
|
80
60
|
expect(dialer.streams).to.have.lengthOf(expectedStreams);
|
|
81
61
|
// Pause, and then close the dialer
|
|
82
62
|
await delay(50);
|
|
83
|
-
await
|
|
63
|
+
await inboundConnection.close();
|
|
64
|
+
await outboundConnection.close();
|
|
65
|
+
await delay(50);
|
|
84
66
|
expect(openedStreams).to.have.equal(expectedStreams);
|
|
85
67
|
expect(dialer.streams).to.have.lengthOf(0);
|
|
86
68
|
});
|
|
87
69
|
it('calling close closes streams', async () => {
|
|
88
70
|
let openedStreams = 0;
|
|
89
71
|
const expectedStreams = 5;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const listenerFactory = await common.setup();
|
|
94
|
-
const listener = listenerFactory.createStreamMuxer({
|
|
95
|
-
direction: 'inbound',
|
|
96
|
-
onIncomingStream: (stream) => {
|
|
97
|
-
openedStreams++;
|
|
98
|
-
void pipe(stream, stream).catch(() => { });
|
|
99
|
-
}
|
|
72
|
+
listener.addEventListener('stream', (evt) => {
|
|
73
|
+
openedStreams++;
|
|
74
|
+
echo(evt.detail);
|
|
100
75
|
});
|
|
101
|
-
const
|
|
102
|
-
void pipe(p[0], dialer, p[0]);
|
|
103
|
-
void pipe(p[1], listener, p[1]);
|
|
104
|
-
const streams = await Promise.all(Array(expectedStreams).fill(0).map(async () => dialer.newStream()));
|
|
76
|
+
const streams = await Promise.all(Array(expectedStreams).fill(0).map(async () => dialer.createStream()));
|
|
105
77
|
void Promise.all(streams.map(async (stream) => {
|
|
106
|
-
await
|
|
107
|
-
|
|
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
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}))
|
|
92
|
+
.catch(() => {
|
|
93
|
+
// calling .send on a closed stream will throw so swallow any errors
|
|
94
|
+
});
|
|
108
95
|
expect(dialer.streams, 'dialer - number of opened streams should match number of calls to newStream').to.have.lengthOf(expectedStreams);
|
|
109
96
|
// Pause, and then close the dialer
|
|
110
97
|
await delay(50);
|
|
111
98
|
await dialer.close();
|
|
99
|
+
await delay(50);
|
|
112
100
|
expect(openedStreams, 'listener - number of opened streams should match number of calls to newStream').to.have.equal(expectedStreams);
|
|
113
101
|
expect(dialer.streams, 'all tracked streams should be deleted after the muxer has called close').to.have.lengthOf(0);
|
|
114
102
|
});
|
|
115
|
-
it('calling
|
|
103
|
+
it('calling abort aborts streams', async () => {
|
|
116
104
|
let openedStreams = 0;
|
|
117
105
|
const expectedStreams = 5;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const listenerFactory = await common.setup();
|
|
122
|
-
const listener = listenerFactory.createStreamMuxer({
|
|
123
|
-
direction: 'inbound',
|
|
124
|
-
onIncomingStream: (stream) => {
|
|
125
|
-
openedStreams++;
|
|
126
|
-
void pipe(stream, stream).catch(() => { });
|
|
127
|
-
}
|
|
106
|
+
listener.addEventListener('stream', (evt) => {
|
|
107
|
+
openedStreams++;
|
|
108
|
+
echo(evt.detail);
|
|
128
109
|
});
|
|
129
|
-
const
|
|
130
|
-
void pipe(p[0], dialer, p[0]);
|
|
131
|
-
void pipe(p[1], listener, p[1]);
|
|
132
|
-
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()));
|
|
133
111
|
const streamPipes = streams.map(async (stream) => {
|
|
134
|
-
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
|
+
}
|
|
135
123
|
});
|
|
136
|
-
expect(dialer.streams, 'dialer - number of opened streams should match number of calls to
|
|
137
|
-
// Pause, and then close the dialer
|
|
138
|
-
await delay(50);
|
|
139
|
-
// close _with an error_
|
|
140
|
-
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');
|
|
141
125
|
const timeoutError = new Error('timeout');
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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');
|
|
153
143
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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');
|
|
158
153
|
});
|
|
159
154
|
it('calling newStream after close throws an error', async () => {
|
|
160
|
-
const dialerFactory = await common.setup();
|
|
161
|
-
const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' });
|
|
162
155
|
await dialer.close();
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
expect.fail('newStream should throw if called after close');
|
|
166
|
-
}
|
|
167
|
-
catch (e) {
|
|
168
|
-
expect(dialer.streams, 'closed muxer should have no streams').to.have.lengthOf(0);
|
|
169
|
-
}
|
|
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');
|
|
170
158
|
});
|
|
171
159
|
it('closing one of the muxed streams doesn\'t close others', async () => {
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
direction: 'inbound',
|
|
179
|
-
onIncomingStream: (stream) => {
|
|
180
|
-
void pipe(stream, stream).catch(() => { });
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
void pipe(p[0], dialer, p[0]);
|
|
184
|
-
void pipe(p[1], listener, p[1]);
|
|
185
|
-
const stream = await dialer.newStream();
|
|
186
|
-
const streams = await Promise.all(Array.from(Array(5), async () => dialer.newStream()));
|
|
187
|
-
let closed = false;
|
|
188
|
-
const controllers = [];
|
|
189
|
-
const streamResults = streams.map(async (stream) => {
|
|
190
|
-
const controller = new AbortController();
|
|
191
|
-
controllers.push(controller);
|
|
192
|
-
try {
|
|
193
|
-
const abortableRand = abortableSource(infiniteRandom(), controller.signal, {
|
|
194
|
-
abortName: 'TestAbortError'
|
|
195
|
-
});
|
|
196
|
-
await pipe(abortableRand, stream, drain);
|
|
197
|
-
}
|
|
198
|
-
catch (err) {
|
|
199
|
-
if (err.name !== 'TestAbortError') {
|
|
200
|
-
throw err;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
if (!closed) {
|
|
204
|
-
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();
|
|
205
166
|
}
|
|
206
167
|
});
|
|
207
|
-
|
|
208
|
-
await
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
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'));
|
|
216
185
|
});
|
|
217
186
|
it('can close a stream for writing', async () => {
|
|
218
|
-
const deferred =
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const listenerFactory = await common.setup();
|
|
224
|
-
const listener = listenerFactory.createStreamMuxer({
|
|
225
|
-
direction: 'inbound',
|
|
226
|
-
onIncomingStream: (stream) => {
|
|
227
|
-
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 {
|
|
228
192
|
// Immediate close for write
|
|
229
|
-
await
|
|
230
|
-
|
|
231
|
-
const data = [];
|
|
232
|
-
for await (const chunk of source) {
|
|
233
|
-
data.push(chunk.slice());
|
|
234
|
-
}
|
|
235
|
-
return data;
|
|
193
|
+
await evt.detail.close({
|
|
194
|
+
signal: AbortSignal.timeout(1_000)
|
|
236
195
|
});
|
|
237
|
-
|
|
196
|
+
const results = await all(map(evt.detail, (buf) => {
|
|
197
|
+
return buf.subarray();
|
|
198
|
+
}));
|
|
199
|
+
expect(results).to.deep.equal(data);
|
|
238
200
|
try {
|
|
239
|
-
|
|
201
|
+
evt.detail.send(randomBuffer());
|
|
240
202
|
}
|
|
241
203
|
catch (err) {
|
|
242
204
|
deferred.resolve(err);
|
|
243
205
|
}
|
|
244
|
-
|
|
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
|
+
]
|
|
245
220
|
});
|
|
246
221
|
}
|
|
222
|
+
}
|
|
223
|
+
await stream.close({
|
|
224
|
+
signal: AbortSignal.timeout(1_000)
|
|
247
225
|
});
|
|
248
|
-
void pipe(p[0], dialer, p[0]);
|
|
249
|
-
void pipe(p[1], listener, p[1]);
|
|
250
|
-
const stream = await dialer.newStream();
|
|
251
|
-
await stream.sink(data);
|
|
252
226
|
const err = await deferred.promise;
|
|
253
227
|
expect(err).to.have.property('name', 'StreamStateError');
|
|
254
228
|
});
|
|
255
|
-
it('
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const dialerFactory = await common.setup();
|
|
259
|
-
const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' });
|
|
260
|
-
const data = [randomBuffer(), randomBuffer()].map(d => new Uint8ArrayList(d));
|
|
261
|
-
const expected = toBuffer(data.map(d => d.subarray()));
|
|
262
|
-
const listenerFactory = await common.setup();
|
|
263
|
-
const listener = listenerFactory.createStreamMuxer({
|
|
264
|
-
direction: 'inbound',
|
|
265
|
-
onIncomingStream: (stream) => {
|
|
266
|
-
void all(stream.source).then(deferred.resolve, deferred.reject);
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
void pipe(p[0], dialer, p[0]);
|
|
270
|
-
void pipe(p[1], listener, p[1]);
|
|
271
|
-
const stream = await dialer.newStream();
|
|
272
|
-
await stream.closeRead();
|
|
273
|
-
// Source should be done
|
|
274
|
-
void Promise.resolve().then(async () => {
|
|
275
|
-
expect(await stream.source.next()).to.have.property('done', true);
|
|
276
|
-
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();
|
|
277
232
|
});
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const deferred = pDefer();
|
|
283
|
-
const onStreamEnd = () => { deferred.resolve(); };
|
|
284
|
-
const dialerFactory = await common.setup();
|
|
285
|
-
const dialer = dialerFactory.createStreamMuxer({
|
|
286
|
-
direction: 'outbound',
|
|
287
|
-
onStreamEnd
|
|
233
|
+
const deferred = Promise.withResolvers();
|
|
234
|
+
const stream = await dialer.createStream();
|
|
235
|
+
stream.addEventListener('close', () => {
|
|
236
|
+
deferred.resolve();
|
|
288
237
|
});
|
|
289
|
-
const stream = await dialer.newStream();
|
|
290
238
|
await stream.close();
|
|
291
239
|
await deferred.promise;
|
|
292
240
|
});
|
|
293
|
-
it('
|
|
294
|
-
const deferred =
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
direction: 'outbound',
|
|
299
|
-
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();
|
|
300
246
|
});
|
|
301
|
-
|
|
302
|
-
await stream.closeWrite();
|
|
303
|
-
await stream.closeRead();
|
|
247
|
+
stream.abort(new Error('Urk!'));
|
|
304
248
|
await deferred.promise;
|
|
305
249
|
});
|
|
306
250
|
it('should wait for all data to be sent when closing streams', async () => {
|
|
307
|
-
const deferred =
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
deferred.resolve(message);
|
|
319
|
-
await pb.unwrap().close();
|
|
320
|
-
})
|
|
321
|
-
.catch(err => {
|
|
322
|
-
deferred.reject(err);
|
|
323
|
-
});
|
|
324
|
-
}
|
|
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
|
+
});
|
|
325
262
|
});
|
|
326
|
-
void pipe(p[0], dialer, p[0]);
|
|
327
|
-
void pipe(p[1], listener, p[1]);
|
|
328
263
|
const message = {
|
|
329
264
|
message: 'hello world',
|
|
330
265
|
value: 5,
|
|
331
266
|
flag: true
|
|
332
267
|
};
|
|
333
|
-
const stream = await dialer.
|
|
268
|
+
const stream = await dialer.createStream();
|
|
334
269
|
const pb = pbStream(stream);
|
|
335
270
|
await pb.write(message, Message);
|
|
336
|
-
await
|
|
271
|
+
await stream.close();
|
|
337
272
|
await expect(deferred.promise).to.eventually.deep.equal(message);
|
|
338
273
|
});
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
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
|
-
|
|
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
|
+
dialerStream.abort(new Error('Urk!'))
|
|
284
|
+
]);
|
|
285
|
+
expect(dialer.streams).to.not.include(dialerStream, 'dialer did not remove outbound stream close');
|
|
286
|
+
expect(listener.streams).to.not.include(listenerStream, 'listener did not remove inbound stream after close');
|
|
287
|
+
});
|
|
288
|
+
it('should remove a stream in the streams list after closing', async () => {
|
|
289
|
+
const [listenerStream, dialerStream] = await Promise.all([
|
|
290
|
+
pEvent(listener, 'stream').then(evt => evt.detail),
|
|
291
|
+
dialer.createStream()
|
|
292
|
+
]);
|
|
293
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer did not store outbound stream');
|
|
294
|
+
expect(listener.streams).to.include(listenerStream, 'listener did not store inbound stream');
|
|
295
|
+
await Promise.all([
|
|
296
|
+
dialerStream.close(),
|
|
297
|
+
listenerStream.close()
|
|
298
|
+
]);
|
|
299
|
+
await delay(10);
|
|
300
|
+
expect(dialer.streams).to.not.include(dialerStream, 'dialer did not remove outbound stream close');
|
|
301
|
+
expect(listener.streams).to.not.include(listenerStream, 'listener did not remove inbound stream after close');
|
|
302
|
+
});
|
|
303
|
+
it('should not remove a half-closed outbound stream', async () => {
|
|
304
|
+
const [listenerStream, dialerStream] = await Promise.all([
|
|
305
|
+
pEvent(listener, 'stream').then(evt => evt.detail),
|
|
306
|
+
dialer.createStream()
|
|
307
|
+
]);
|
|
308
|
+
await dialerStream.close();
|
|
309
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer did not store outbound stream');
|
|
310
|
+
expect(listener.streams).to.include(listenerStream, 'listener did not store inbound stream');
|
|
311
|
+
});
|
|
312
|
+
it('should not remove a half-closed inbound stream', async () => {
|
|
313
|
+
const [listenerStream, dialerStream] = await Promise.all([
|
|
314
|
+
pEvent(listener, 'stream').then(evt => evt.detail),
|
|
315
|
+
dialer.createStream()
|
|
316
|
+
]);
|
|
317
|
+
await listenerStream.close();
|
|
318
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer did not store outbound stream');
|
|
319
|
+
expect(listener.streams).to.include(listenerStream, 'listener did not store inbound stream');
|
|
320
|
+
});
|
|
321
|
+
it('should remove a stream half closed from both ends', async () => {
|
|
322
|
+
const [listenerStream, dialerStream] = await Promise.all([
|
|
323
|
+
pEvent(listener, 'stream').then(evt => evt.detail),
|
|
324
|
+
dialer.createStream()
|
|
325
|
+
]);
|
|
326
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer did not store outbound stream');
|
|
327
|
+
expect(listener.streams).to.include(listenerStream, 'listener did not store inbound stream');
|
|
328
|
+
await listenerStream.close();
|
|
329
|
+
expect(dialer.streams).to.include(dialerStream, 'dialer removed outbound stream before fully closing');
|
|
330
|
+
expect(listener.streams).to.include(listenerStream, 'listener removed inbound stream before fully closing');
|
|
331
|
+
await Promise.all([
|
|
332
|
+
pEvent(listenerStream, 'close'),
|
|
333
|
+
dialerStream.close()
|
|
334
|
+
]);
|
|
335
|
+
await delay(10);
|
|
336
|
+
expect(dialer.streams).to.not.include(dialerStream, 'dialer did not remove outbound stream close');
|
|
337
|
+
expect(listener.streams).to.not.include(listenerStream, 'listener did not remove inbound stream after close');
|
|
338
|
+
});
|
|
390
339
|
});
|
|
391
340
|
};
|
|
392
341
|
//# sourceMappingURL=close-test.js.map
|