@fails-components/webtransport 0.1.7 → 0.2.0

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.
@@ -7,6 +7,7 @@ import { expect } from './fixtures/chai.js'
7
7
  import { readStream } from './fixtures/read-stream.js'
8
8
  import { writeStream } from './fixtures/write-stream.js'
9
9
  import { defer } from '../lib/utils.js'
10
+ import * as ui8 from 'uint8arrays'
10
11
 
11
12
  /**
12
13
  * @template T
@@ -60,6 +61,7 @@ describe('bidirectional streams', function () {
60
61
  // server context - waits for the client to open a bidi stream and pipes it back to them
61
62
  Promise.resolve().then(async () => {
62
63
  const session = await getReaderValue(server.sessionStream(SERVER_PATH))
64
+ if (!session) throw new Error('Got no session')
63
65
  const bidiStream = await getReaderValue(
64
66
  session.incomingBidirectionalStreams
65
67
  )
@@ -87,9 +89,9 @@ describe('bidirectional streams', function () {
87
89
  const stream = await client.createBidirectionalStream()
88
90
  await writeStream(stream.writable, input)
89
91
 
90
- const output = await readStream(stream.readable)
91
- expect(output).to.deep.equal(
92
- input,
92
+ const output = await readStream(stream.readable, ui8.concat(input).length)
93
+ expect(ui8.concat(output)).to.deep.equal(
94
+ ui8.concat(input),
93
95
  'Did not receive the same bytes we sent'
94
96
  )
95
97
  })
@@ -107,12 +109,14 @@ describe('bidirectional streams', function () {
107
109
  // server context - waits for the client to connect, opens a bidi stream, sends some data and reads the response
108
110
  Promise.resolve().then(async () => {
109
111
  const session = await getReaderValue(server.sessionStream(SERVER_PATH))
112
+ if (!session) throw new Error('Got no session')
110
113
  const stream = await session.createBidirectionalStream()
111
114
 
112
115
  await writeStream(stream.writable, input)
113
116
 
114
- const output = await readStream(stream.readable)
117
+ const output = await readStream(stream.readable, ui8.concat(input).length)
115
118
  serverData.resolve(output)
119
+ await stream.readable.cancel() // cancel so that the client can progress
116
120
  })
117
121
 
118
122
  // client context - waits for the server to open a bidi stream then pipes it back to them
@@ -128,11 +132,15 @@ describe('bidirectional streams', function () {
128
132
 
129
133
  const bidiStream = await getReaderValue(client.incomingBidirectionalStreams)
130
134
  // redirect input to output
131
- await bidiStream.readable.pipeTo(bidiStream.writable)
135
+ try {
136
+ await bidiStream.readable.pipeTo(bidiStream.writable)
137
+ } catch (error) {
138
+ console.log('Pipe to error (ignore)', error) // Actually all you can get is, that the fin is catched
139
+ }
132
140
 
133
141
  const received = await serverData.promise
134
- expect(received).to.deep.equal(
135
- input,
142
+ expect(ui8.concat(received)).to.deep.equal(
143
+ ui8.concat(input),
136
144
  'Did not receive the same bytes we sent'
137
145
  )
138
146
  })
@@ -6,7 +6,8 @@ import { WebTransport } from '../lib/index.js'
6
6
  import { expect } from './fixtures/chai.js'
7
7
  import { readStream } from './fixtures/read-stream.js'
8
8
  import { writeStream } from './fixtures/write-stream.js'
9
- import { defer } from '../lib/utils.js'
9
+ import * as ui8 from 'uint8arrays'
10
+ import { pTimeout } from './fixtures/p-timeout.js'
10
11
 
11
12
  /**
12
13
  * @template T
@@ -80,7 +81,10 @@ describe('datagrams', function () {
80
81
 
81
82
  await writeStream(client.datagrams.writable, input)
82
83
 
83
- const output = await readStream(client.datagrams.readable, input.length)
84
+ const output = await readStream(
85
+ client.datagrams.readable,
86
+ ui8.concat(input).length
87
+ )
84
88
  expect(output).to.deep.equal(
85
89
  input,
86
90
  'Did not receive the same bytes we sent'
@@ -89,25 +93,29 @@ describe('datagrams', function () {
89
93
 
90
94
  it('receives datagrams from the server', async () => {
91
95
  this.timeout(200)
92
- /** @type {Deferred<Uint8Array[]>} */
93
- const serverData = defer()
94
- const input = [
95
- Uint8Array.from([0, 1, 2, 3, 4]),
96
- Uint8Array.from([5, 6, 7, 8, 9]),
97
- Uint8Array.from([10, 11, 12, 13, 14])
98
- ]
99
96
 
100
97
  // server context - waits for the client to connect, sends some datagrams and reads the response
101
98
  Promise.resolve().then(async () => {
102
99
  const session = await getReaderValue(server.sessionStream(SERVER_PATH))
103
100
 
104
- await writeStream(session.datagrams.writable, input)
105
-
106
- const output = await readStream(session.datagrams.readable, input.length)
101
+ let closed = false
102
+ const writer = session.datagrams.writable.getWriter()
103
+ Promise.resolve().then(async () => {
104
+ // eslint-disable-next-line no-unmodified-loop-condition
105
+ while (!closed) {
106
+ try {
107
+ await writer.ready
108
+ await writer.write(Uint8Array.from([0, 1, 2, 3, 4]))
109
+ await new Promise((resolve) => setTimeout(resolve, 1)) // do not flood everything
110
+ } catch {
111
+ // the session can be closed while we are writing
112
+ }
113
+ }
114
+ })
107
115
 
108
116
  // have to close the session to end the client's datagram stream
109
- session.close()
110
- serverData.resolve(output)
117
+ await session.closed
118
+ closed = true
111
119
  })
112
120
 
113
121
  // client context - pipes the server's datagrams back to them
@@ -121,13 +129,15 @@ describe('datagrams', function () {
121
129
  })
122
130
  await client.ready
123
131
 
124
- // redirect input to output
125
- await client.datagrams.readable.pipeTo(client.datagrams.writable)
132
+ // datagram transport is unreliable, at least one message should make it through
133
+ const expected = 1
126
134
 
127
- const received = await serverData.promise
128
- expect(received).to.deep.equal(
129
- input,
130
- 'Did not receive the same bytes we sent'
135
+ const received = await pTimeout(
136
+ readStream(client.datagrams.readable, expected),
137
+ 1000
131
138
  )
139
+ await client.close()
140
+ client = undefined
141
+ expect(received).to.have.lengthOf(expected)
132
142
  })
133
143
  })
@@ -0,0 +1,33 @@
1
+ class TimeoutError extends Error {
2
+ /**
3
+ * @param {string} message
4
+ */
5
+ constructor(message) {
6
+ super(message)
7
+
8
+ this.name = this[Symbol.toStringTag] = 'TimeoutError'
9
+ }
10
+ }
11
+
12
+ /**
13
+ * @template T
14
+ * @param {Promise<T>} promise
15
+ * @param {number} timeout
16
+ * @returns {Promise<T>}
17
+ */
18
+ export async function pTimeout(promise, timeout) {
19
+ let ref
20
+
21
+ const value = await Promise.race([
22
+ promise,
23
+ new Promise((resolve, reject) => {
24
+ ref = setTimeout(() => {
25
+ reject(new TimeoutError('timeout'))
26
+ }, timeout)
27
+ })
28
+ ])
29
+
30
+ clearTimeout(ref)
31
+
32
+ return value
33
+ }
@@ -12,6 +12,7 @@ export async function readStream(readable, expected) {
12
12
  try {
13
13
  /** @type {T[]} */
14
14
  const output = []
15
+ let outputlength = 0
15
16
 
16
17
  while (true) {
17
18
  const { done, value } = await reader.read()
@@ -21,10 +22,12 @@ export async function readStream(readable, expected) {
21
22
  }
22
23
 
23
24
  if (value != null) {
25
+ // @ts-ignore
26
+ outputlength += value.length
24
27
  output.push(value)
25
28
  }
26
29
 
27
- if (expected != null && output.length === expected) {
30
+ if (expected != null && outputlength >= expected) {
28
31
  break
29
32
  }
30
33
  }
@@ -7,6 +7,7 @@ import { expect } from 'chai'
7
7
  import { readStream } from './fixtures/read-stream.js'
8
8
  import { writeStream } from './fixtures/write-stream.js'
9
9
  import { defer } from '../lib/utils.js'
10
+ import * as ui8 from 'uint8arrays'
10
11
 
11
12
  /**
12
13
  * @template T
@@ -56,13 +57,21 @@ describe('unidirectional streams', function () {
56
57
  /** @type {Deferred<Uint8Array[]>} */
57
58
  const serverData = defer()
58
59
 
60
+ const input = [
61
+ Uint8Array.from([0, 1, 2, 3, 4]),
62
+ Uint8Array.from([5, 6, 7, 8, 9]),
63
+ Uint8Array.from([10, 11, 12, 13, 14])
64
+ ]
65
+
59
66
  // server context - waits for the client to open a bidi stream and pipes it back to them
60
67
  Promise.resolve().then(async () => {
61
68
  const session = await getReaderValue(server.sessionStream(SERVER_PATH))
69
+ if (!session) throw new Error('no session')
62
70
  const stream = await getReaderValue(session.incomingUnidirectionalStreams)
63
71
 
64
- const output = await readStream(stream)
72
+ const output = await readStream(stream, ui8.concat(input).length)
65
73
  serverData.resolve(output)
74
+ await stream.cancel() // cancel so that the client can progress
66
75
  })
67
76
 
68
77
  // client context - connects to the server, opens a bidi stream, sends some data and reads the response
@@ -76,18 +85,12 @@ describe('unidirectional streams', function () {
76
85
  })
77
86
  await client.ready
78
87
 
79
- const input = [
80
- Uint8Array.from([0, 1, 2, 3, 4]),
81
- Uint8Array.from([5, 6, 7, 8, 9]),
82
- Uint8Array.from([10, 11, 12, 13, 14])
83
- ]
84
-
85
88
  const stream = await client.createUnidirectionalStream()
86
89
  await writeStream(stream, input)
87
90
 
88
91
  const received = await serverData.promise
89
- expect(received).to.deep.equal(
90
- input,
92
+ expect(ui8.concat(received)).to.deep.equal(
93
+ ui8.concat(input),
91
94
  'Server did not receive the same bytes we sent'
92
95
  )
93
96
  })
@@ -103,6 +106,7 @@ describe('unidirectional streams', function () {
103
106
  // server context - waits for the client to connect, opens a bidi stream, sends some data and reads the response
104
107
  Promise.resolve().then(async () => {
105
108
  const session = await getReaderValue(server.sessionStream(SERVER_PATH))
109
+ if (!session) throw new Error('no session')
106
110
  const stream = await session.createUnidirectionalStream()
107
111
 
108
112
  await writeStream(stream, input)
@@ -120,9 +124,9 @@ describe('unidirectional streams', function () {
120
124
  await client.ready
121
125
 
122
126
  const stream = await getReaderValue(client.incomingUnidirectionalStreams)
123
- const received = await readStream(stream)
124
- expect(received).to.deep.equal(
125
- input,
127
+ const received = await readStream(stream, ui8.concat(input).length)
128
+ expect(ui8.concat(received)).to.deep.equal(
129
+ ui8.concat(input),
126
130
  'Did not receive the same bytes we sent'
127
131
  )
128
132
  })
@@ -135,6 +139,7 @@ describe('unidirectional streams', function () {
135
139
 
136
140
  Promise.resolve().then(async () => {
137
141
  const session = await getReaderValue(server.sessionStream(SERVER_PATH))
142
+ if (!session) throw new Error('Got no session')
138
143
  const stream = await getReaderValue(session.incomingUnidirectionalStreams)
139
144
 
140
145
  serverStream.resolve(stream)
@@ -172,9 +177,12 @@ describe('unidirectional streams', function () {
172
177
 
173
178
  await new Promise((resolve) => setTimeout(resolve, 1000))
174
179
 
175
- const received = await readStream(await serverStream.promise)
176
- expect(received).to.deep.equal(
177
- input,
180
+ const received = await readStream(
181
+ await serverStream.promise,
182
+ ui8.concat(input).length
183
+ )
184
+ expect(ui8.concat(received)).to.deep.equal(
185
+ ui8.concat(input),
178
186
  'Did not receive the same bytes we sent'
179
187
  )
180
188
  })