// META: global=window,worker // META: script=/common/get-host-info.sub.js // META: script=resources/webtransport-test-helpers.sub.js promise_test(async t => { // Establish a WebTransport session. const wt = new WebTransport(webtransport_url('echo.py')); await wt.ready; // Create a bidirectional stream. const bidi_stream = await wt.createBidirectionalStream(); // Write a message to the writable end, and close it. const writer = bidi_stream.writable.getWriter(); const encoder = new TextEncoder(); await writer.write(encoder.encode('Hello World')); await writer.close(); // Read the data on the readable end. const reply = await read_stream_as_string(bidi_stream.readable); // Check that the message from the readable end matches the writable end. assert_equals(reply, 'Hello World'); }, 'WebTransport client should be able to create and handle a bidirectional stream'); promise_test(async t => { // Establish a WebTransport session. const wt = new WebTransport(webtransport_url('echo.py')); // Create a bidirectional stream. const bidi_stream = await wt.createBidirectionalStream(); // Write a message to the writable end, and close it. const writer = bidi_stream.writable.getWriter(); const encoder = new TextEncoder(); await writer.write(encoder.encode('Hello World')); await writer.close(); // Read the data on the readable end. const reply = await read_stream_as_string(bidi_stream.readable); // Check that the message from the readable end matches the writable end. assert_equals(reply, 'Hello World'); }, 'WebTransport client should be able to create and handle a bidirectional stream without waiting for ready'); promise_test(async t => { // Establish a WebTransport session. const wt = new WebTransport(webtransport_url('echo.py')); await wt.ready; // The echo handler creates a bidirectional stream when a WebTransport session // is established. Accept the bidirectional stream. const stream_reader = wt.incomingBidirectionalStreams.getReader(); const { value: bidi_stream } = await stream_reader.read(); stream_reader.releaseLock(); // Write a message to the writable end, and close it. const encoder = new TextEncoderStream(); encoder.readable.pipeTo(bidi_stream.writable); const writer = encoder.writable.getWriter(); await writer.write('Hello World'); await writer.close(); // Read the data on the readable end. const reply = await read_stream_as_string(bidi_stream.readable); // Check that the message from the readable end matches the writable end. assert_equals(reply, 'Hello World'); }, 'WebTransport server should be able to accept and handle a bidirectional stream'); promise_test(async t => { // Establish a WebTransport session. const wt = new WebTransport(webtransport_url('echo.py')); await wt.ready; // Create a unidirectional stream. const writable = await wt.createUnidirectionalStream(); // Write a message to the writable end, and close it. const encoder = new TextEncoderStream(); encoder.readable.pipeTo(writable); const writer = encoder.writable.getWriter(); await writer.write('Hello World'); await writer.close(); // The echo handler creates a new unidirectional stream to echo back data from // the server to client. Accept the unidirectional stream. const readable = wt.incomingUnidirectionalStreams; const stream_reader = readable.getReader(); const { value: recv_stream } = await stream_reader.read(); stream_reader.releaseLock(); // Read the data on the readable end. const reply = await read_stream_as_string(recv_stream); // Make sure the message on the writable and readable ends of the streams // match. assert_equals(reply, 'Hello World'); }, 'WebTransport client should be able to create, accept, and handle a unidirectional stream'); promise_test(async t => { // Establish a WebTransport session. const wt = new WebTransport(webtransport_url('echo.py')); // Create a unidirectional stream. const writable = await wt.createUnidirectionalStream(); // Write a message to the writable end, and close it. const encoder = new TextEncoderStream(); encoder.readable.pipeTo(writable); const writer = encoder.writable.getWriter(); await writer.write('Hello World'); await writer.close(); // The echo handler creates a new unidirectional stream to echo back data from // the server to client. Accept the unidirectional stream. const readable = wt.incomingUnidirectionalStreams; const stream_reader = readable.getReader(); const { value: recv_stream } = await stream_reader.read(); stream_reader.releaseLock(); // Read the data on the readable end. const reply = await read_stream_as_string(recv_stream); // Make sure the message on the writable and readable ends of the streams // match. assert_equals(reply, 'Hello World'); }, 'WebTransport client should be able to create, accept, and handle a unidirectional stream without waiting for ready'); promise_test(async t => { // Establish a WebTransport session. const wt = new WebTransport(webtransport_url('echo.py')); await wt.ready; // The echo handler creates a bidirectional stream when a WebTransport session // is established. Accept the bidirectional stream. const stream_reader = wt.incomingBidirectionalStreams.getReader(); const {value: bidi_stream} = await stream_reader.read(); stream_reader.releaseLock(); // Write data to the writable end, and close it. const buffer_size = 256; const data = new Uint8Array(buffer_size); for (let i = 0; i < data.byteLength; ++i) { data[i] = i; } const writer = bidi_stream.writable.getWriter(); writer.write(data); await writer.close(); // Read the data on the readable end and check if it matches the writable end. const reader = bidi_stream.readable.getReader({mode: 'byob'}); assert_true(reader instanceof ReadableStreamBYOBReader); const half_buffer_size = buffer_size / 2; for (let i = 0; i < 2; i++) { let buffer = new ArrayBuffer(half_buffer_size); buffer = await readInto(reader, buffer); assert_array_equals( new Uint8Array(buffer), data.subarray(half_buffer_size * i, half_buffer_size * (i + 1))) } reader.releaseLock(); }, 'Can read data from a bidirectional stream with BYOB reader'); promise_test(async t => { // Establish a WebTransport session. const wt = new WebTransport(webtransport_url('echo.py')); await wt.ready; // Create a unidirectional stream. const writable = await wt.createUnidirectionalStream(); // Write data to the writable end, and close it. const buffer_size = 256; const data = new Uint8Array(buffer_size); for (let i = 0; i < data.byteLength; ++i) { data[i] = i; } const writer = writable.getWriter(); writer.write(data); await writer.close(); // The echo handler creates a new unidirectional stream to echo back data from // the server to client. Accept the unidirectional stream. const readable = wt.incomingUnidirectionalStreams; const stream_reader = readable.getReader(); const {value: recv_stream} = await stream_reader.read(); stream_reader.releaseLock(); // Read the data on the readable end and check if it matches the writable end. const reader = recv_stream.getReader({mode: 'byob'}); assert_true(reader instanceof ReadableStreamBYOBReader); const half_buffer_size = buffer_size / 2; let buffer = new ArrayBuffer(half_buffer_size); for (let i = 0; i < 2; i++) { buffer = await readInto(reader, buffer); assert_array_equals( new Uint8Array(buffer), data.subarray(half_buffer_size * i, half_buffer_size * (i + 1))) } reader.releaseLock(); }, 'Can read data from a unidirectional stream with BYOB reader'); promise_test(async t => { // Establish a WebTransport session. const wt = new WebTransport(webtransport_url('echo.py')); await wt.ready; // Create a bidirectional stream. const bidi_stream = await wt.createBidirectionalStream(); // Write a message to the writable end, and close it. const writer = bidi_stream.writable.getWriter(); const bytes = new Uint8Array(16384); const [reply] = await Promise.all([ read_stream(bidi_stream.readable), writer.write(bytes), writer.write(bytes), writer.write(bytes), writer.close() ]); let len = 0; for (chunk of reply) { len += chunk.length; } // Check that the message from the readable end matches the writable end. assert_equals(len, 3*bytes.length); }, 'Transfer large chunks of data on a bidirectional stream'); promise_test(async t => { // Establish a WebTransport session. const wt = new WebTransport(webtransport_url('echo.py')); await wt.ready; // Create a unidirectional stream. const uni_stream = await wt.createUnidirectionalStream(); // Write a message to the writable end, and close it. const writer = uni_stream.getWriter(); const bytes = new Uint8Array(16384); await Promise.all([ writer.write(bytes), writer.write(bytes), writer.write(bytes), writer.close() ]); // XXX Update once chrome fixes https://crbug.com/929585 // The echo handler creates a new unidirectional stream to echo back data from // the server to client. Accept the unidirectional stream. const readable = wt.incomingUnidirectionalStreams; const stream_reader = readable.getReader(); const { value: recv_stream } = await stream_reader.read(); stream_reader.releaseLock(); // Read the data on the readable end. const reply = await read_stream(recv_stream); let len = 0; for (chunk of reply) { len += chunk.length; } // Check that the message from the readable end matches the writable end. assert_equals(len, 3*bytes.length); }, 'Transfer large chunks of data on a unidirectional stream'); promise_test(async t => { // Establish a WebTransport session. const wt = new WebTransport(webtransport_url('echo.py')); await wt.ready; // Create a bidirectional stream. const bidi_stream = await wt.createBidirectionalStream(); // Close the writable end with no data at all. const writer = bidi_stream.writable.getWriter(); writer.close(); // Read the data on the readable end. const chunks = await read_stream(bidi_stream.readable); assert_equals(chunks.length, 0); await bidi_stream.readable.closed; }, 'Closing the stream with no data still resolves the read request');