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