| <!doctype html> |
| <meta charset=utf-8> |
| <title>RTCQuicStream.https.html</title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="../webrtc/RTCIceTransport-extension-helper.js"></script> |
| <script src="RTCQuicTransport-helper.js"></script> |
| <script src="RTCQuicStream-helper.js"></script> |
| <script> |
| 'use strict'; |
| |
| // These tests are based on the following specification: |
| // https://w3c.github.io/webrtc-quic/ |
| |
| // The following helper functions are called from RTCQuicTransport-helper.js: |
| // makeStandaloneQuicTransport |
| // makeTwoConnectedQuicTransports |
| // The following helper functions are called from RTCQuicStream-helper.js: |
| // closed_stream_test |
| |
| promise_test(async t => { |
| const [ quicTransport, ] = await makeTwoConnectedQuicTransports(t); |
| const quicStream = quicTransport.createStream(); |
| assert_equals(quicStream.transport, quicTransport, |
| 'Expect transport to be set to the creating RTCQuicTransport.'); |
| assert_equals(quicStream.state, 'open', `Expect state to be 'open'.`); |
| assert_equals(quicStream.readBufferedAmount, 0, |
| 'Expect read buffered amount to be 0.'); |
| assert_equals(quicStream.writeBufferedAmount, 0, |
| 'Expect write buffered amount to be 0.'); |
| assert_greater_than(quicStream.maxWriteBufferedAmount, 0, |
| 'Expect max write buffered amount to be greater than 0.'); |
| }, 'createStream() returns an RTCQuicStream with initial properties set.'); |
| |
| promise_test(async t => { |
| const quicTransport = await makeStandaloneQuicTransport(t); |
| assert_throws_dom('InvalidStateError', () => quicTransport.createStream()); |
| }, 'createStream() throws if the transport is not connected.'); |
| |
| promise_test(async t => { |
| const quicTransport = await makeStandaloneQuicTransport(t); |
| quicTransport.stop(); |
| assert_throws_dom('InvalidStateError', () => quicTransport.createStream()); |
| }, 'createStream() throws if the transport is closed.'); |
| |
| promise_test(async t => { |
| const [ quicTransport, ] = await makeTwoConnectedQuicTransports(t); |
| const firstQuicStream = quicTransport.createStream(); |
| const secondQuicStream = quicTransport.createStream(); |
| quicTransport.stop(); |
| assert_equals(firstQuicStream.state, 'closed'); |
| assert_equals(secondQuicStream.state, 'closed'); |
| }, 'RTCQuicTransport.stop() closes all local streams.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| localQuicTransport.createStream().write({ data: new Uint8Array([42]) }); |
| localQuicTransport.createStream().write({ data: new Uint8Array([42]) }); |
| const remoteWatcher = |
| new EventWatcher(t, remoteQuicTransport, [ 'quicstream', 'statechange' ]); |
| const { stream: firstRemoteStream } = |
| await remoteWatcher.wait_for('quicstream'); |
| const { stream: secondRemoteStream } = |
| await remoteWatcher.wait_for('quicstream'); |
| localQuicTransport.stop(); |
| await remoteWatcher.wait_for('statechange'); |
| assert_equals(firstRemoteStream.state, 'closed'); |
| assert_equals(secondRemoteStream.state, 'closed'); |
| }, 'RTCQuicTransport.stop() closes all remote streams.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| assert_equals(localStream.state, 'closing'); |
| }, `write() with a finish changes state to 'closing'.`); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: new Uint8Array(), finish: true }); |
| assert_equals(localStream.state, 'closing'); |
| }, 'write() with a finish and an empty array changes state ' + |
| `to 'closing'.`); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| assert_throws_dom('InvalidStateError', () => { |
| localStream.write({ finish: true }); |
| }); |
| }, `write() with finish twice throws InvalidStateError.`); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.reset(); |
| assert_equals(localStream.state, 'closed'); |
| }, `reset() changes state to 'closed'.`); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| localStream.reset(); |
| assert_equals(localStream.state, 'closed'); |
| }, `reset() following write with finish changes state to 'closed'.`); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.reset(); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| assert_equals(remoteStream.state, 'open'); |
| const remoteStreamWatcher = new EventWatcher(t, remoteStream, 'statechange'); |
| await remoteStreamWatcher.wait_for('statechange'); |
| assert_equals(remoteStream.state, 'closed'); |
| }, 'createStream() followed by reset() fires a quicstream event followed ' + |
| `by a statechange event to 'closed' on the remote side.`); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| assert_equals(remoteStream.state, 'open'); |
| const remoteStreamWatcher = new EventWatcher(t, remoteStream, 'statechange'); |
| await remoteStream.waitForReadable(remoteStream.maxReadBufferedAmount); |
| assert_object_equals( |
| remoteStream.readInto(new Uint8Array(10)), |
| { amount: 0, finished: true } ); |
| assert_equals(remoteStream.state, 'closing'); |
| }, 'waitForReadable() promise resolves with remote finish'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| await remoteStream.waitForReadable(remoteStream.maxReadBufferedAmount); |
| assert_object_equals( |
| remoteStream.readInto(new Uint8Array(10)), |
| { amount: 0, finished: true } ); |
| assert_equals(remoteStream.state, 'closing'); |
| remoteStream.write({ finish: true }); |
| assert_equals(remoteStream.state, 'closed'); |
| }, 'write() with a finish on a stream that has already read out finish ' + |
| `changes state to 'closed'.`); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| remoteStream.write({ finish: true }); |
| assert_equals(localStream.state, 'closing'); |
| await localStream.waitForReadable(localStream.maxReadBufferedAmount); |
| assert_object_equals( |
| localStream.readInto(new Uint8Array(10)), |
| { amount: 0, finished: true } ); |
| assert_equals(localStream.state, 'closed'); |
| }, 'Reading out finish on stream that has already called write() with a ' + |
| `finish state to 'closed'.`); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| await remoteStream.waitForReadable(remoteStream.maxReadBufferedAmount); |
| assert_object_equals( |
| remoteStream.readInto(new Uint8Array(10)), |
| { amount: 0, finished: true } ); |
| assert_equals(remoteStream.state, 'closing'); |
| localStream.reset(); |
| const remoteStreamWatcher = new EventWatcher(t, remoteStream, 'statechange'); |
| await remoteStreamWatcher.wait_for('statechange'); |
| assert_equals(remoteStream.state, 'closed'); |
| }, 'Reading out finish then a getting a remote reset fires a statechange event ' + |
| `to 'closed'.`); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| assert_throws_dom('NotSupportedError', () => |
| localStream.write({ data: new Uint8Array() })); |
| }, 'write() without finish and an empty array throws NotSupportedError.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| assert_throws_dom('NotSupportedError', () => |
| localStream.write({})); |
| }, 'write() without finish and no data throws NotSupportedError.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: new Uint8Array([65]) }); |
| assert_equals(localStream.writeBufferedAmount, 1); |
| localStream.write({ data: new Uint8Array([66, 67]) }); |
| assert_equals(localStream.writeBufferedAmount, 3); |
| localStream.write({ data: new Uint8Array([68, 69, 70]) }); |
| assert_equals(localStream.writeBufferedAmount, 6); |
| }, 'write() adds to writeBufferedAmount each call.'); |
| |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: new Uint8Array([42, 43]), finish: true }); |
| assert_equals(localStream.writeBufferedAmount, 2); |
| }, `write() data with a finish adds to writeBufferedAmount.`); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ |
| data: new Uint8Array(localStream.maxWriteBufferedAmount) |
| }); |
| assert_equals(localStream.writeBufferedAmount, |
| localStream.maxWriteBufferedAmount); |
| }, 'write() can write exactly maxWriteBufferedAmount.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| assert_throws_dom('OperationError', () => localStream.write({ |
| data: new Uint8Array(localStream.maxWriteBufferedAmount + 1) |
| })); |
| assert_equals(localStream.writeBufferedAmount, 0); |
| }, 'write() throws if data longer than maxWriteBufferedAmount.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write( |
| { data: new Uint8Array(10)}); |
| assert_throws_dom('OperationError', () => localStream.write({ |
| data: new Uint8Array(localStream.maxWriteBufferedAmount) |
| })); |
| assert_equals(localStream.writeBufferedAmount, 10); |
| }, 'write() throws if total write buffered amount would be greater than ' + |
| 'maxWriteBufferedAmount.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: new Uint8Array(10) }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| await remoteWatcher.wait_for('quicstream'); |
| }, 'write() causes quicstream event to fire on the remote transport.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true });; |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| await remoteWatcher.wait_for('quicstream'); |
| }, 'write() with a finish causes quicstream event to fire on the ' + |
| 'remote transport.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| assert_throws_dom('InvalidStateError', |
| () => localStream.write({ data: new Uint8Array([65]) })); |
| }, 'write() throws InvalidStateError if write() with finish has been called.'); |
| |
| closed_stream_test(async (t, stream) => { |
| assert_throws_dom('InvalidStateError', |
| () => stream.write({ data: new Uint8Array([65]) })); |
| }, 'write() throws InvalidStateError.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: generateData(10) }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream : remoteStream} = await remoteWatcher.wait_for('quicstream'); |
| await remoteStream.waitForReadable(10); |
| assert_equals(10, remoteStream.readBufferedAmount); |
| remoteStream.reset(); |
| assert_equals(0, remoteStream.readBufferedAmount); |
| }, 'readBufferedAmount set to 0 after local reset().'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: generateData(10) }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream : remoteStream} = await remoteWatcher.wait_for('quicstream'); |
| await remoteStream.waitForReadable(10); |
| assert_equals(10, remoteStream.readBufferedAmount); |
| localStream.reset(); |
| const remoteStreamWatcher = |
| new EventWatcher(t, remoteStream, 'statechange'); |
| await remoteStreamWatcher.wait_for('statechange'); |
| assert_equals(remoteStream.state, 'closed'); |
| assert_equals(0, remoteStream.readBufferedAmount); |
| }, 'readBufferedAmount set to 0 after remote reset().'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: new Uint8Array(10) }); |
| localStream.reset(); |
| assert_equals(localStream.writeBufferedAmount, 0); |
| }, 'writeBufferedAmount set to 0 after local reset().'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| const remoteWatcher = |
| new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| await remoteStream.waitForReadable(10); |
| assert_object_equals( |
| remoteStream.readInto(new Uint8Array(10)), |
| { amount: 0, finished: true }); |
| remoteStream.write({ data: new Uint8Array(10) }); |
| assert_equals(remoteStream.writeBufferedAmount, 10); |
| remoteStream.write({ finish: true }); |
| assert_equals(remoteStream.writeBufferedAmount, 0); |
| }, 'writeBufferedAmount set to 0 after reading remote finish, followed ' + |
| 'by write() with finish.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: new Uint8Array(10) }); |
| localQuicTransport.stop(); |
| assert_equals(localStream.writeBufferedAmount, 0); |
| }, 'writeBufferedAmount set to 0 after local RTCQuicTransport stop().'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: new Uint8Array(10) }); |
| localStream.write({ finish: true }); |
| assert_equals(localStream.writeBufferedAmount, 10); |
| }, 'writeBufferedAmount maintained after write() with finish has been called.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| await localStream.waitForWriteBufferedAmountBelow(0); |
| }, 'waitForWriteBufferedAmountBelow(0) resolves immediately.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| await localStream.waitForWriteBufferedAmountBelow( |
| localStream.maxWriteBufferedAmount); |
| }, 'waitForWriteBufferedAmountBelow(maxWriteBufferedAmount) resolves ' + |
| 'immediately.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ |
| data: new Uint8Array(localStream.maxWriteBufferedAmount) |
| }); |
| const promise1 = localStream.waitForWriteBufferedAmountBelow(0); |
| const promise2 = localStream.waitForWriteBufferedAmountBelow(0); |
| localStream.write({ finish: true }); |
| await Promise.all([ |
| promise_rejects(t, 'InvalidStateError', promise1), |
| promise_rejects(t, 'InvalidStateError', promise2)]); |
| }, 'Pending waitForWriteBufferedAmountBelow() promises rejected after ' + |
| 'write() with finish.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ |
| data: new Uint8Array(localStream.maxWriteBufferedAmount) |
| }); |
| localStream.write({ finish: true }); |
| const promise1 = localStream.waitForWriteBufferedAmountBelow(0); |
| const promise2 = localStream.waitForWriteBufferedAmountBelow(0); |
| await Promise.all([ |
| promise_rejects(t, 'InvalidStateError', promise1), |
| promise_rejects(t, 'InvalidStateError', promise2)]); |
| }, 'waitForWriteBufferedAmountBelow() promises immediately rejected after ' + |
| 'wrote finish.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ |
| data: new Uint8Array(localStream.maxWriteBufferedAmount) |
| }); |
| const promise1 = localStream.waitForWriteBufferedAmountBelow(0); |
| const promise2 = localStream.waitForWriteBufferedAmountBelow(0); |
| localStream.reset(); |
| await Promise.all([ |
| promise_rejects(t, 'InvalidStateError', promise1), |
| promise_rejects(t, 'InvalidStateError', promise2)]); |
| }, 'Pending waitForWriteBufferedAmountBelow() promises rejected after ' + |
| 'reset().'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ |
| data: new Uint8Array(localStream.maxWriteBufferedAmount) |
| }); |
| const promise1 = localStream.waitForWriteBufferedAmountBelow(0); |
| const promise2 = localStream.waitForWriteBufferedAmountBelow(0); |
| localQuicTransport.stop(); |
| await Promise.all([ |
| promise_rejects(t, 'InvalidStateError', promise1), |
| promise_rejects(t, 'InvalidStateError', promise2)]); |
| }, 'Pending waitForWriteBufferedAmountBelow() promises rejected after ' + |
| 'RTCQuicTransport stop().'); |
| |
| closed_stream_test(async (t, stream) => { |
| await promise_rejects(t, 'InvalidStateError', |
| stream.waitForWriteBufferedAmountBelow(0)); |
| }, 'waitForWriteBufferedBelow() rejects with InvalidStateError.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| assert_object_equals( |
| localStream.readInto(new Uint8Array(10)), |
| { amount: 0, finished: false } ); |
| }, 'readInto() on new local stream returns amount 0.'); |
| |
| closed_stream_test(async (t, stream) => { |
| assert_throws_dom('InvalidStateError', () => stream.readInto(new Uint8Array(1))); |
| }, 'readInto() throws InvalidStateError.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: new Uint8Array([ 65 ]) }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| await remoteStream.waitForReadable(1); |
| assert_equals(remoteStream.readBufferedAmount, 1); |
| const readBuffer = new Uint8Array(3); |
| assert_object_equals( |
| remoteStream.readInto(readBuffer), |
| { amount: 1, finished: false } ); |
| assert_array_equals(readBuffer, [ 65, 0, 0 ]); |
| assert_equals(remoteStream.readBufferedAmount, 0); |
| }, 'Read 1 byte.'); |
| |
| // Returns a Uint8Array of length |amount| with generated data. |
| function generateData(amount) { |
| const data = new Uint8Array(amount); |
| for (let i = 0; i < data.length; i++) { |
| data[i] = i % 256; |
| } |
| return data; |
| } |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| const data = generateData(10); |
| localStream.write({ data: data, finish: true }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| await remoteStream.waitForReadable(data.length + 1); |
| const readBuffer = new Uint8Array(5); |
| assert_object_equals( |
| remoteStream.readInto(readBuffer), |
| { amount: 5, finished: false} ); |
| assert_array_equals( |
| readBuffer, data.subarray(0, 5)); |
| const finReadBuffer = new Uint8Array(5); |
| assert_object_equals( |
| remoteStream.readInto(finReadBuffer), |
| { amount: 5, finished: true} ); |
| assert_array_equals( |
| finReadBuffer, data.subarray(5, data.length)); |
| }, 'readInto() reads out finish after reading all data.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| await remoteStream.waitForReadable(remoteStream.maxReadBufferedAmount); |
| assert_object_equals( |
| remoteStream.readInto(new Uint8Array(10)), |
| { amount: 0, finished: true } ); |
| }, 'waitForReadable() resolves with write() with finish.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| const writeData = generateData(10); |
| localStream.write({ data: writeData }); |
| localStream.write({ finish: true }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| await remoteStream.waitForReadable(11); |
| assert_equals(remoteStream.readBufferedAmount, 10); |
| const readBuffer = new Uint8Array(10); |
| assert_object_equals( |
| remoteStream.readInto(readBuffer), { amount: 10, finished: true } ); |
| assert_array_equals(readBuffer, writeData); |
| }, 'waitForReadable() resolves early if remote finish is received.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| await promise_rejects(t, new TypeError(), |
| localStream.waitForReadable(localStream.maxReadBufferedAmount + 1)); |
| }, 'waitForReadable() rejects with TypeError if amount is more than ' + |
| 'maxReadBufferedAmount.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ finish: true }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); |
| await remoteStream.waitForReadable(remoteStream.maxReadBufferedAmount); |
| assert_object_equals( |
| remoteStream.readInto(new Uint8Array(10)), |
| { amount: 0, finished: true } ); |
| |
| const promise1 = remoteStream.waitForReadable(10); |
| const promise2 = remoteStream.waitForReadable(10); |
| await Promise.all([ |
| promise_rejects(t, 'InvalidStateError', promise1), |
| promise_rejects(t, 'InvalidStateError', promise2)]); |
| }, 'waitForReadable() promises immediately rejected with InvalidStateError ' + |
| 'after finish is read out.'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| const promise1 = localStream.waitForReadable(10); |
| const promise2 = localStream.waitForReadable(10); |
| localStream.reset(); |
| await Promise.all([ |
| promise_rejects(t, 'InvalidStateError', promise1), |
| promise_rejects(t, 'InvalidStateError', promise2)]); |
| }, 'Pending waitForReadable() promises rejected after reset().'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: new Uint8Array(1) }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream : remoteStream} = await remoteWatcher.wait_for('quicstream'); |
| const promise1 = remoteStream.waitForReadable(10); |
| const promise2 = remoteStream.waitForReadable(10); |
| localStream.reset(); |
| await Promise.all([ |
| promise_rejects(t, 'InvalidStateError', promise1), |
| promise_rejects(t, 'InvalidStateError', promise2)]); |
| }, 'Pending waitForReadable() promises rejected after remote reset().'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| const promise1 = localStream.waitForReadable(10); |
| const promise2 = localStream.waitForReadable(10); |
| localQuicTransport.stop(); |
| await Promise.all([ |
| promise_rejects(t, 'InvalidStateError', promise1), |
| promise_rejects(t, 'InvalidStateError', promise2)]); |
| }, 'Pending waitForReadable() promises rejected after RTCQuicTransport ' + |
| 'stop().'); |
| |
| promise_test(async t => { |
| const [ localQuicTransport, remoteQuicTransport ] = |
| await makeTwoConnectedQuicTransports(t); |
| const localStream = localQuicTransport.createStream(); |
| localStream.write({ data: new Uint8Array(1) }); |
| const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); |
| const { stream : remoteStream} = await remoteWatcher.wait_for('quicstream'); |
| const promise1 = remoteStream.waitForReadable(10); |
| const promise2 = remoteStream.waitForReadable(10); |
| localQuicTransport.stop(); |
| await Promise.all([ |
| promise_rejects(t, 'InvalidStateError', promise1), |
| promise_rejects(t, 'InvalidStateError', promise2)]); |
| }, 'Pending waitForReadable() promises rejected after remote RTCQuicTransport ' + |
| 'stop().'); |
| |
| closed_stream_test(async (t, stream) => { |
| await promise_rejects(t, 'InvalidStateError', |
| stream.waitForReadable(1)); |
| }, 'waitForReadable() rejects with InvalidStateError.'); |
| |
| </script> |