summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/streams/transform-streams/flush.any.js
blob: 9287f6f5eb78eb759447f722e943e1aa42a57d7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// META: global=window,worker
// 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');