@libp2p/interface-compliance-tests 3.0.7-7b5c54dd → 3.0.7-7debe031

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 (50) hide show
  1. package/dist/src/connection/index.d.ts.map +1 -1
  2. package/dist/src/connection/index.js +24 -25
  3. package/dist/src/connection/index.js.map +1 -1
  4. package/dist/src/connection-encryption/utils/index.d.ts.map +1 -1
  5. package/dist/src/connection-encryption/utils/index.js +1 -0
  6. package/dist/src/connection-encryption/utils/index.js.map +1 -1
  7. package/dist/src/mocks/connection-manager.d.ts.map +1 -1
  8. package/dist/src/mocks/connection.d.ts.map +1 -1
  9. package/dist/src/mocks/connection.js +42 -39
  10. package/dist/src/mocks/connection.js.map +1 -1
  11. package/dist/src/mocks/multiaddr-connection.d.ts.map +1 -1
  12. package/dist/src/mocks/multiaddr-connection.js +9 -0
  13. package/dist/src/mocks/multiaddr-connection.js.map +1 -1
  14. package/dist/src/mocks/muxer.d.ts +28 -0
  15. package/dist/src/mocks/muxer.d.ts.map +1 -1
  16. package/dist/src/mocks/muxer.js +85 -213
  17. package/dist/src/mocks/muxer.js.map +1 -1
  18. package/dist/src/stream-muxer/base-test.js +6 -6
  19. package/dist/src/stream-muxer/base-test.js.map +1 -1
  20. package/dist/src/stream-muxer/close-test.d.ts.map +1 -1
  21. package/dist/src/stream-muxer/close-test.js +100 -12
  22. package/dist/src/stream-muxer/close-test.js.map +1 -1
  23. package/dist/src/stream-muxer/fixtures/pb/message.d.ts +13 -0
  24. package/dist/src/stream-muxer/fixtures/pb/message.d.ts.map +1 -0
  25. package/dist/src/stream-muxer/fixtures/pb/message.js +67 -0
  26. package/dist/src/stream-muxer/fixtures/pb/message.js.map +1 -0
  27. package/dist/src/stream-muxer/spawner.d.ts.map +1 -1
  28. package/dist/src/stream-muxer/spawner.js +4 -3
  29. package/dist/src/stream-muxer/spawner.js.map +1 -1
  30. package/dist/src/stream-muxer/stress-test.js +1 -1
  31. package/dist/src/stream-muxer/stress-test.js.map +1 -1
  32. package/dist/src/transport/dial-test.js +1 -1
  33. package/dist/src/transport/dial-test.js.map +1 -1
  34. package/dist/src/transport/listen-test.js +4 -4
  35. package/dist/src/transport/listen-test.js.map +1 -1
  36. package/package.json +15 -11
  37. package/src/connection/index.ts +24 -26
  38. package/src/connection-encryption/utils/index.ts +1 -0
  39. package/src/mocks/connection-manager.ts +2 -2
  40. package/src/mocks/connection.ts +46 -40
  41. package/src/mocks/multiaddr-connection.ts +9 -0
  42. package/src/mocks/muxer.ts +105 -249
  43. package/src/stream-muxer/base-test.ts +6 -6
  44. package/src/stream-muxer/close-test.ts +110 -14
  45. package/src/stream-muxer/fixtures/pb/message.proto +7 -0
  46. package/src/stream-muxer/fixtures/pb/message.ts +87 -0
  47. package/src/stream-muxer/spawner.ts +3 -2
  48. package/src/stream-muxer/stress-test.ts +1 -1
  49. package/src/transport/dial-test.ts +1 -1
  50. package/src/transport/listen-test.ts +4 -4
@@ -6,9 +6,12 @@ import all from 'it-all'
6
6
  import drain from 'it-drain'
7
7
  import { duplexPair } from 'it-pair/duplex'
8
8
  import { pipe } from 'it-pipe'
9
+ import { pbStream } from 'it-protobuf-stream'
10
+ import toBuffer from 'it-to-buffer'
9
11
  import pDefer from 'p-defer'
10
12
  import { Uint8ArrayList } from 'uint8arraylist'
11
13
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
14
+ import { Message } from './fixtures/pb/message.js'
12
15
  import type { TestSetup } from '../index.js'
13
16
  import type { StreamMuxerFactory } from '@libp2p/interface/stream-muxer'
14
17
 
@@ -61,9 +64,9 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
61
64
 
62
65
  expect(dialer.streams).to.have.lengthOf(expectedStreams)
63
66
 
64
- // Pause, and then send some data and close the dialer
67
+ // Pause, and then close the dialer
65
68
  await delay(50)
66
- await pipe([randomBuffer()], dialer, drain)
69
+ await pipe([], dialer, drain)
67
70
 
68
71
  expect(openedStreams).to.have.equal(expectedStreams)
69
72
  expect(dialer.streams).to.have.lengthOf(0)
@@ -106,7 +109,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
106
109
  // Pause, and then close the dialer
107
110
  await delay(50)
108
111
 
109
- dialer.close()
112
+ await dialer.close()
110
113
 
111
114
  expect(openedStreams, 'listener - number of opened streams should match number of calls to newStream').to.have.equal(expectedStreams)
112
115
  expect(dialer.streams, 'all tracked streams should be deleted after the muxer has called close').to.have.lengthOf(0)
@@ -148,7 +151,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
148
151
  await delay(50)
149
152
 
150
153
  // close _with an error_
151
- dialer.close(new Error())
154
+ dialer.abort(new Error('Oh no!'))
152
155
 
153
156
  const timeoutError = new Error('timeout')
154
157
  for (const pipe of streamPipes) {
@@ -173,7 +176,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
173
176
  const dialerFactory = await common.setup()
174
177
  const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' })
175
178
 
176
- dialer.close()
179
+ await dialer.close()
177
180
 
178
181
  try {
179
182
  await dialer.newStream()
@@ -246,7 +249,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
246
249
  onIncomingStream: (stream) => {
247
250
  void Promise.resolve().then(async () => {
248
251
  // Immediate close for write
249
- stream.closeWrite()
252
+ await stream.closeWrite()
250
253
 
251
254
  const results = await pipe(stream, async (source) => {
252
255
  const data = []
@@ -275,16 +278,16 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
275
278
  await stream.sink(data)
276
279
 
277
280
  const err = await deferred.promise
278
- expect(err).to.have.property('message').that.matches(/stream closed for writing/)
281
+ expect(err).to.have.property('code', 'ERR_SINK_INVALID_STATE')
279
282
  })
280
283
 
281
284
  it('can close a stream for reading', async () => {
282
- const deferred = pDefer<any>()
283
-
285
+ const deferred = pDefer<Uint8ArrayList[]>()
284
286
  const p = duplexPair<Uint8Array>()
285
287
  const dialerFactory = await common.setup()
286
288
  const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' })
287
289
  const data = [randomBuffer(), randomBuffer()].map(d => new Uint8ArrayList(d))
290
+ const expected = toBuffer(data.map(d => d.subarray()))
288
291
 
289
292
  const listenerFactory = await common.setup()
290
293
  const listener = listenerFactory.createStreamMuxer({
@@ -298,7 +301,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
298
301
  void pipe(p[1], listener, p[1])
299
302
 
300
303
  const stream = await dialer.newStream()
301
- stream.closeRead()
304
+ await stream.closeRead()
302
305
 
303
306
  // Source should be done
304
307
  void Promise.resolve().then(async () => {
@@ -307,7 +310,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
307
310
  })
308
311
 
309
312
  const results = await deferred.promise
310
- expect(results).to.eql(data)
313
+ expect(toBuffer(results.map(b => b.subarray()))).to.equalBytes(expected)
311
314
  })
312
315
 
313
316
  it('calls onStreamEnd for closed streams not previously written', async () => {
@@ -322,7 +325,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
322
325
 
323
326
  const stream = await dialer.newStream()
324
327
 
325
- stream.close()
328
+ await stream.close()
326
329
  await deferred.promise
327
330
  })
328
331
 
@@ -338,9 +341,102 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
338
341
 
339
342
  const stream = await dialer.newStream()
340
343
 
341
- stream.closeWrite()
342
- stream.closeRead()
344
+ await stream.closeWrite()
345
+ await stream.closeRead()
346
+ await deferred.promise
347
+ })
348
+
349
+ it('should wait for all data to be sent when closing streams', async () => {
350
+ const deferred = pDefer<Message>()
351
+
352
+ const p = duplexPair<Uint8Array>()
353
+ const dialerFactory = await common.setup()
354
+ const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' })
355
+
356
+ const listenerFactory = await common.setup()
357
+ const listener = listenerFactory.createStreamMuxer({
358
+ direction: 'inbound',
359
+ onIncomingStream: (stream) => {
360
+ const pb = pbStream(stream)
361
+
362
+ void pb.read(Message)
363
+ .then(async message => {
364
+ deferred.resolve(message)
365
+ await pb.unwrap().close()
366
+ })
367
+ .catch(err => {
368
+ deferred.reject(err)
369
+ })
370
+ }
371
+ })
372
+
373
+ void pipe(p[0], dialer, p[0])
374
+ void pipe(p[1], listener, p[1])
375
+
376
+ const message = {
377
+ message: 'hello world',
378
+ value: 5,
379
+ flag: true
380
+ }
381
+
382
+ const stream = await dialer.newStream()
383
+
384
+ const pb = pbStream(stream)
385
+ await pb.write(message, Message)
386
+ await pb.unwrap().close()
387
+
388
+ await expect(deferred.promise).to.eventually.deep.equal(message)
389
+ })
390
+ /*
391
+ it('should abort closing a stream with outstanding data to read', async () => {
392
+ const deferred = pDefer<Message>()
393
+
394
+ const p = duplexPair<Uint8Array>()
395
+ const dialerFactory = await common.setup()
396
+ const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' })
397
+
398
+ const listenerFactory = await common.setup()
399
+ const listener = listenerFactory.createStreamMuxer({
400
+ direction: 'inbound',
401
+ onIncomingStream: (stream) => {
402
+ const pb = pbStream(stream)
403
+
404
+ void pb.read(Message)
405
+ .then(async message => {
406
+ await pb.write(message, Message)
407
+ await pb.unwrap().close()
408
+ deferred.resolve(message)
409
+ })
410
+ .catch(err => {
411
+ deferred.reject(err)
412
+ })
413
+ }
414
+ })
415
+
416
+ void pipe(p[0], dialer, p[0])
417
+ void pipe(p[1], listener, p[1])
418
+
419
+ const message = {
420
+ message: 'hello world',
421
+ value: 5,
422
+ flag: true
423
+ }
424
+
425
+ const stream = await dialer.newStream()
426
+
427
+ const pb = pbStream(stream)
428
+ await pb.write(message, Message)
429
+
430
+ console.info('await write back')
343
431
  await deferred.promise
432
+
433
+ // let message arrive
434
+ await delay(100)
435
+
436
+ // close should time out as message is never read
437
+ await expect(pb.unwrap().close()).to.eventually.be.rejected
438
+ .with.property('code', 'ERR_CLOSE_READ_ABORTED')
344
439
  })
440
+ */
345
441
  })
346
442
  }
@@ -0,0 +1,7 @@
1
+ syntax = "proto3";
2
+
3
+ message Message {
4
+ string message = 1;
5
+ uint32 value = 2;
6
+ bool flag = 3;
7
+ }
@@ -0,0 +1,87 @@
1
+ /* eslint-disable import/export */
2
+ /* eslint-disable complexity */
3
+ /* eslint-disable @typescript-eslint/no-namespace */
4
+ /* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
5
+ /* eslint-disable @typescript-eslint/no-empty-interface */
6
+
7
+ import { encodeMessage, decodeMessage, message } from 'protons-runtime'
8
+ import type { Codec } from 'protons-runtime'
9
+ import type { Uint8ArrayList } from 'uint8arraylist'
10
+
11
+ export interface Message {
12
+ message: string
13
+ value: number
14
+ flag: boolean
15
+ }
16
+
17
+ export namespace Message {
18
+ let _codec: Codec<Message>
19
+
20
+ export const codec = (): Codec<Message> => {
21
+ if (_codec == null) {
22
+ _codec = message<Message>((obj, w, opts = {}) => {
23
+ if (opts.lengthDelimited !== false) {
24
+ w.fork()
25
+ }
26
+
27
+ if ((obj.message != null && obj.message !== '')) {
28
+ w.uint32(10)
29
+ w.string(obj.message)
30
+ }
31
+
32
+ if ((obj.value != null && obj.value !== 0)) {
33
+ w.uint32(16)
34
+ w.uint32(obj.value)
35
+ }
36
+
37
+ if ((obj.flag != null && obj.flag !== false)) {
38
+ w.uint32(24)
39
+ w.bool(obj.flag)
40
+ }
41
+
42
+ if (opts.lengthDelimited !== false) {
43
+ w.ldelim()
44
+ }
45
+ }, (reader, length) => {
46
+ const obj: any = {
47
+ message: '',
48
+ value: 0,
49
+ flag: false
50
+ }
51
+
52
+ const end = length == null ? reader.len : reader.pos + length
53
+
54
+ while (reader.pos < end) {
55
+ const tag = reader.uint32()
56
+
57
+ switch (tag >>> 3) {
58
+ case 1:
59
+ obj.message = reader.string()
60
+ break
61
+ case 2:
62
+ obj.value = reader.uint32()
63
+ break
64
+ case 3:
65
+ obj.flag = reader.bool()
66
+ break
67
+ default:
68
+ reader.skipType(tag & 7)
69
+ break
70
+ }
71
+ }
72
+
73
+ return obj
74
+ })
75
+ }
76
+
77
+ return _codec
78
+ }
79
+
80
+ export const encode = (obj: Partial<Message>): Uint8Array => {
81
+ return encodeMessage(obj, Message.codec())
82
+ }
83
+
84
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Message => {
85
+ return decodeMessage(buf, Message.codec())
86
+ }
87
+ }
@@ -19,9 +19,10 @@ export default async (createMuxer: (init?: StreamMuxerInit) => Promise<StreamMux
19
19
  void pipe(
20
20
  stream,
21
21
  drain
22
- ).then(() => {
23
- stream.close()
22
+ ).then(async () => {
23
+ await stream.close()
24
24
  })
25
+ .catch(err => { stream.abort(err) })
25
26
  }
26
27
  })
27
28
  const dialer = await createMuxer({ direction: 'outbound' })
@@ -9,7 +9,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
9
9
  }
10
10
 
11
11
  describe('stress test', function () {
12
- this.timeout(800000)
12
+ this.timeout(1600000)
13
13
 
14
14
  it('1 stream with 1 msg', async () => { await spawn(createMuxer, 1, 1) })
15
15
  it('1 stream with 10 msg', async () => { await spawn(createMuxer, 1, 10) })
@@ -85,7 +85,7 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
85
85
  expect(upgradeSpy.callCount).to.equal(1)
86
86
  await expect(upgradeSpy.getCall(0).returnValue).to.eventually.equal(conn)
87
87
  await conn.close()
88
- expect(isValidTick(conn.stat.timeline.close)).to.equal(true)
88
+ expect(isValidTick(conn.timeline.close)).to.equal(true)
89
89
  })
90
90
 
91
91
  it('to non existent listener', async () => {
@@ -93,12 +93,12 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
93
93
  listener.close()
94
94
  ])
95
95
 
96
- stream1.close()
96
+ await stream1.close()
97
97
  await conn1.close()
98
98
 
99
- expect(isValidTick(conn1.stat.timeline.close)).to.equal(true)
99
+ expect(isValidTick(conn1.timeline.close)).to.equal(true)
100
100
  listenerConns.forEach(conn => {
101
- expect(isValidTick(conn.stat.timeline.close)).to.equal(true)
101
+ expect(isValidTick(conn.timeline.close)).to.equal(true)
102
102
  })
103
103
 
104
104
  // 2 dials = 2 connections upgraded
@@ -120,7 +120,7 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
120
120
  upgrader
121
121
  })
122
122
 
123
- await pWaitFor(() => typeof conn.stat.timeline.close === 'number')
123
+ await pWaitFor(() => typeof conn.timeline.close === 'number')
124
124
  await listener.close()
125
125
  })
126
126