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