252 lines
8.5 KiB
JavaScript
252 lines
8.5 KiB
JavaScript
// META: global=window,worker
|
|
// META: script=/common/get-host-info.sub.js
|
|
// META: script=/common/utils.js
|
|
// META: script=resources/webtransport-test-helpers.sub.js
|
|
|
|
// Note: There is no aioquic event for STOP_SENDING yet, so the server does
|
|
// not support checking this yet. Hence, tests checking from the STOP_SENDING
|
|
// signal cannot be tested yet.
|
|
|
|
promise_test(async t => {
|
|
const id = token();
|
|
const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
|
|
add_completion_callback(() => wt.close());
|
|
await wt.ready;
|
|
|
|
const bidi_stream = await wt.createBidirectionalStream();
|
|
|
|
const writable = bidi_stream.writable;
|
|
writable.close();
|
|
|
|
await wait(10);
|
|
const data = await query(id);
|
|
|
|
assert_own_property(data, 'stream-close-info');
|
|
const info = data['stream-close-info'];
|
|
|
|
assert_equals(info.source, 'FIN', 'source');
|
|
}, 'Close outgoing stream / bidi-1');
|
|
|
|
promise_test(async t => {
|
|
const id = token();
|
|
const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
|
|
add_completion_callback(() => wt.close());
|
|
await wt.ready;
|
|
|
|
const streams_reader = wt.incomingBidirectionalStreams.getReader();
|
|
const {value: bidi} = await streams_reader.read();
|
|
|
|
const writable = bidi.writable;
|
|
writable.close();
|
|
|
|
await wait(10);
|
|
const data = await query(id);
|
|
|
|
assert_own_property(data, 'stream-close-info');
|
|
const info = data['stream-close-info'];
|
|
|
|
assert_equals(info.source, 'FIN', 'source');
|
|
}, 'Close outgoing stream / bidi-2');
|
|
|
|
promise_test(async t => {
|
|
const id = token();
|
|
const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
|
|
add_completion_callback(() => wt.close());
|
|
await wt.ready;
|
|
|
|
const writable = await wt.createUnidirectionalStream();
|
|
writable.close();
|
|
|
|
await wait(10);
|
|
const data = await query(id);
|
|
|
|
assert_own_property(data, 'stream-close-info');
|
|
const info = data['stream-close-info'];
|
|
|
|
assert_equals(info.source, 'FIN', 'source');
|
|
}, 'Close outgoing stream / uni');
|
|
|
|
promise_test(async t => {
|
|
const id = token();
|
|
const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
|
|
add_completion_callback(() => wt.close());
|
|
await wt.ready;
|
|
|
|
const bidi_stream = await wt.createBidirectionalStream();
|
|
|
|
const writable = bidi_stream.writable;
|
|
|
|
const WT_CODE = 139;
|
|
const HTTP_CODE = webtransport_code_to_http_code(WT_CODE);
|
|
await writable.abort(
|
|
new WebTransportError({streamErrorCode: WT_CODE}));
|
|
|
|
await wait(10);
|
|
const data = await query(id);
|
|
|
|
// Check that stream is aborted with RESET_STREAM with the code and reason
|
|
assert_own_property(data, 'stream-close-info');
|
|
const info = data['stream-close-info'];
|
|
|
|
assert_equals(info.source, 'reset', 'reset stream');
|
|
assert_equals(info.code, HTTP_CODE, 'code');
|
|
}, 'Abort client-created bidirectional stream');
|
|
|
|
promise_test(async t => {
|
|
const id = token();
|
|
const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
|
|
add_completion_callback(() => wt.close());
|
|
await wt.ready;
|
|
|
|
const stream_reader = wt.incomingBidirectionalStreams.getReader();
|
|
const { value: bidi_stream } = await stream_reader.read();
|
|
stream_reader.releaseLock();
|
|
|
|
const writer = bidi_stream.writable.getWriter();
|
|
|
|
const WT_CODE = 52;
|
|
const HTTP_CODE = webtransport_code_to_http_code(WT_CODE);
|
|
await writer.abort(
|
|
new WebTransportError({streamErrorCode: WT_CODE}));
|
|
|
|
await wait(10);
|
|
const data = await query(id);
|
|
|
|
// Check that stream is aborted with RESET_STREAM with the code and reason
|
|
assert_own_property(data, 'stream-close-info');
|
|
const info = data['stream-close-info'];
|
|
|
|
assert_equals(info.source, 'reset', 'reset_stream');
|
|
assert_equals(info.code, HTTP_CODE, 'code');
|
|
}, 'Abort server-initiated bidirectional stream');
|
|
|
|
promise_test(async t => {
|
|
const id = token();
|
|
const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
|
|
add_completion_callback(() => wt.close());
|
|
await wt.ready;
|
|
|
|
const writable = await wt.createUnidirectionalStream();
|
|
|
|
const WT_CODE = 95;
|
|
const HTTP_CODE = webtransport_code_to_http_code(WT_CODE);
|
|
await writable.abort(
|
|
new WebTransportError({streamErrorCode: WT_CODE}));
|
|
|
|
await wait(10);
|
|
const data = await query(id);
|
|
|
|
// Check that stream is aborted with RESET_STREAM with the code and reason
|
|
assert_own_property(data, 'stream-close-info');
|
|
const info = data['stream-close-info'];
|
|
|
|
assert_equals(info.source, 'reset', 'reset_stream');
|
|
assert_equals(info.code, HTTP_CODE, 'code');
|
|
}, 'Abort unidirectional stream with WebTransportError');
|
|
|
|
promise_test(async t => {
|
|
const id = token();
|
|
const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
|
|
add_completion_callback(() => wt.close());
|
|
await wt.ready;
|
|
|
|
const writable = await wt.createUnidirectionalStream();
|
|
const writer = writable.getWriter();
|
|
|
|
const WT_CODE = 134;
|
|
const HTTP_CODE = webtransport_code_to_http_code(WT_CODE);
|
|
|
|
// We use a large chunk so that sending the FIN signal takes time.
|
|
const chunk = new Uint8Array(64 * 1024);
|
|
const e = new WebTransportError({streamErrorCode: WT_CODE});
|
|
// Write a chunk, close the stream, and then abort the stream immediately to
|
|
// abort the closing operation.
|
|
// TODO: Check that the abort promise is correctly rejected/resolved based on
|
|
// the spec discussion at https://github.com/whatwg/streams/issues/1203.
|
|
await writer.write(chunk);
|
|
const close_promise = writer.close();
|
|
const abort_promise = writer.abort(e);
|
|
|
|
await promise_rejects_exactly(t, e, close_promise, 'close_promise');
|
|
await promise_rejects_exactly(t, e, writer.closed, '.closed');
|
|
await promise_rejects_exactly(t, e, abort_promise, 'abort_promise');
|
|
writer.releaseLock();
|
|
|
|
await wait(10);
|
|
const data = await query(id);
|
|
|
|
// Check that stream is aborted with RESET_STREAM with the code and reason
|
|
assert_own_property(data, 'stream-close-info');
|
|
const info = data['stream-close-info'];
|
|
|
|
assert_equals(info.source, 'reset', 'reset_stream');
|
|
assert_equals(info.code, HTTP_CODE, 'code');
|
|
}, 'Close and abort unidirectional stream');
|
|
|
|
promise_test(async t => {
|
|
const id = token();
|
|
const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
|
|
add_completion_callback(() => wt.close());
|
|
await wt.ready;
|
|
|
|
const writable = await wt.createUnidirectionalStream();
|
|
await writable.abort();
|
|
|
|
await wait(10);
|
|
const data = await query(id);
|
|
|
|
// Check that stream is aborted with RESET_STREAM with the code and reason
|
|
assert_own_property(data, 'stream-close-info');
|
|
const info = data['stream-close-info'];
|
|
|
|
assert_equals(info.source, 'reset', 'reset_stream');
|
|
assert_equals(info.code, webtransport_code_to_http_code(0), 'code');
|
|
}, 'Abort unidirectional stream with default error code');
|
|
|
|
promise_test(async t => {
|
|
const WT_CODE = 0;
|
|
const HTTP_CODE = webtransport_code_to_http_code(WT_CODE);
|
|
const wt = new WebTransport(
|
|
webtransport_url(`abort-stream-from-server.py?code=${HTTP_CODE}`));
|
|
add_completion_callback(() => wt.close());
|
|
await wt.ready;
|
|
|
|
const writable = await wt.createUnidirectionalStream();
|
|
const writer = writable.getWriter();
|
|
|
|
// Write something, to make the stream visible to the server side.
|
|
await writer.write(new Uint8Array([64]));
|
|
|
|
// Sadly we cannot use promise_rejects_dom as the error constructor is
|
|
// WebTransportError rather than DOMException. Ditto below.
|
|
// We get a possible error, and then make sure wt.closed is rejected with it.
|
|
const e = await writer.closed.catch(e => e);
|
|
await promise_rejects_exactly(
|
|
t, e, writer.closed, 'closed promise should be rejected');
|
|
assert_true(e instanceof WebTransportError);
|
|
assert_equals(e.source, 'stream', 'source');
|
|
assert_equals(e.streamErrorCode, WT_CODE, 'streamErrorCode');
|
|
}, 'STOP_SENDING coming from server');
|
|
|
|
promise_test(async t => {
|
|
const WT_CODE = 0xffffffff;
|
|
const HTTP_CODE = webtransport_code_to_http_code(WT_CODE);
|
|
const wt = new WebTransport(
|
|
webtransport_url(`abort-stream-from-server.py?code=${HTTP_CODE}`));
|
|
add_completion_callback(() => wt.close());
|
|
await wt.ready;
|
|
|
|
const bidi = await wt.createBidirectionalStream();
|
|
const writer = bidi.writable.getWriter();
|
|
|
|
// Write something, to make the stream visible to the server side.
|
|
await writer.write(new Uint8Array([64]));
|
|
|
|
const reader = bidi.readable.getReader();
|
|
const e = await reader.closed.catch(e => e);
|
|
await promise_rejects_exactly(
|
|
t, e, reader.closed, 'closed promise should be rejected');
|
|
assert_true(e instanceof WebTransportError);
|
|
assert_equals(e.source, 'stream', 'source');
|
|
assert_equals(e.streamErrorCode, WT_CODE, 'streamErrorCode');
|
|
}, 'RESET_STREAM coming from server');
|