summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/streams/transform-streams/flush.any.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/streams/transform-streams/flush.any.js')
-rw-r--r--testing/web-platform/tests/streams/transform-streams/flush.any.js146
1 files changed, 146 insertions, 0 deletions
diff --git a/testing/web-platform/tests/streams/transform-streams/flush.any.js b/testing/web-platform/tests/streams/transform-streams/flush.any.js
new file mode 100644
index 0000000000..c95d8ae118
--- /dev/null
+++ b/testing/web-platform/tests/streams/transform-streams/flush.any.js
@@ -0,0 +1,146 @@
+// META: global=window,worker,shadowrealm
+// META: script=../resources/test-utils.js
+'use strict';
+
+promise_test(() => {
+ let flushCalled = false;
+ const ts = new TransformStream({
+ transform() { },
+ flush() {
+ flushCalled = true;
+ }
+ });
+
+ return ts.writable.getWriter().close().then(() => {
+ return assert_true(flushCalled, 'closing the writable triggers the transform flush immediately');
+ });
+}, 'TransformStream flush is called immediately when the writable is closed, if no writes are queued');
+
+promise_test(() => {
+ let flushCalled = false;
+ let resolveTransform;
+ const ts = new TransformStream({
+ transform() {
+ return new Promise(resolve => {
+ resolveTransform = resolve;
+ });
+ },
+ flush() {
+ flushCalled = true;
+ return new Promise(() => {}); // never resolves
+ }
+ }, undefined, { highWaterMark: 1 });
+
+ const writer = ts.writable.getWriter();
+ writer.write('a');
+ writer.close();
+ assert_false(flushCalled, 'closing the writable does not immediately call flush if writes are not finished');
+
+ let rsClosed = false;
+ ts.readable.getReader().closed.then(() => {
+ rsClosed = true;
+ });
+
+ return delay(0).then(() => {
+ assert_false(flushCalled, 'closing the writable does not asynchronously call flush if writes are not finished');
+ resolveTransform();
+ return delay(0);
+ }).then(() => {
+ assert_true(flushCalled, 'flush is eventually called');
+ assert_false(rsClosed, 'if flushPromise does not resolve, the readable does not become closed');
+ });
+}, 'TransformStream flush is called after all queued writes finish, once the writable is closed');
+
+promise_test(() => {
+ let c;
+ const ts = new TransformStream({
+ start(controller) {
+ c = controller;
+ },
+ transform() {
+ },
+ flush() {
+ c.enqueue('x');
+ c.enqueue('y');
+ }
+ });
+
+ const reader = ts.readable.getReader();
+
+ const writer = ts.writable.getWriter();
+ writer.write('a');
+ writer.close();
+ return reader.read().then(result1 => {
+ assert_equals(result1.value, 'x', 'the first chunk read is the first one enqueued in flush');
+ assert_equals(result1.done, false, 'the first chunk read is the first one enqueued in flush');
+
+ return reader.read().then(result2 => {
+ assert_equals(result2.value, 'y', 'the second chunk read is the second one enqueued in flush');
+ assert_equals(result2.done, false, 'the second chunk read is the second one enqueued in flush');
+ });
+ });
+}, 'TransformStream flush gets a chance to enqueue more into the readable');
+
+promise_test(() => {
+ let c;
+ const ts = new TransformStream({
+ start(controller) {
+ c = controller;
+ },
+ transform() {
+ },
+ flush() {
+ c.enqueue('x');
+ c.enqueue('y');
+ return delay(0);
+ }
+ });
+
+ const reader = ts.readable.getReader();
+
+ const writer = ts.writable.getWriter();
+ writer.write('a');
+ writer.close();
+
+ return Promise.all([
+ reader.read().then(result1 => {
+ assert_equals(result1.value, 'x', 'the first chunk read is the first one enqueued in flush');
+ assert_equals(result1.done, false, 'the first chunk read is the first one enqueued in flush');
+
+ return reader.read().then(result2 => {
+ assert_equals(result2.value, 'y', 'the second chunk read is the second one enqueued in flush');
+ assert_equals(result2.done, false, 'the second chunk read is the second one enqueued in flush');
+ });
+ }),
+ reader.closed.then(() => {
+ assert_true(true, 'readable reader becomes closed');
+ })
+ ]);
+}, 'TransformStream flush gets a chance to enqueue more into the readable, and can then async close');
+
+const error1 = new Error('error1');
+error1.name = 'error1';
+
+promise_test(t => {
+ const ts = new TransformStream({
+ flush(controller) {
+ controller.error(error1);
+ }
+ });
+ return promise_rejects_exactly(t, error1, ts.writable.getWriter().close(), 'close() should reject');
+}, 'error() during flush should cause writer.close() to reject');
+
+promise_test(async t => {
+ let flushed = false;
+ const ts = new TransformStream({
+ flush() {
+ flushed = true;
+ },
+ cancel: t.unreached_func('cancel should not be called')
+ });
+ const closePromise = ts.writable.close();
+ await delay(0);
+ const cancelPromise = ts.readable.cancel(error1);
+ await Promise.all([closePromise, cancelPromise]);
+ assert_equals(flushed, true, 'transformer.flush() should be called');
+}, 'closing the writable side should call transformer.flush() and a parallel readable.cancel() should not reject');