@libp2p/interface-compliance-tests 6.1.8-32ca76fcb → 6.1.8-432955390

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