[Streams API] Import the web-platform-tests directly from the spec
[WebKit-https.git] / LayoutTests / streams / reference-implementation / readable-stream-templated.html
1 <!DOCTYPE html>
2 <script src='../../resources/testharness.js'></script>
3 <script src='../../resources/testharnessreport.js'></script>
4 <script src='resources/streams-utils.js'></script>
5 <script>
6 // This is updated till https://github.com/whatwg/streams/commit/ec5ffa036308d9f6350d2946560d48cdbf090939
7
8 function templatedRSClosed(label, factory) {
9     test(function() {
10     }, 'Running templatedRSClosed with ' + label);
11
12     var test2 = async_test('piping to a WritableStream in the writable state should close the writable stream');
13     test2.step(function() {
14         var closeCalled = false;
15
16         var rs = factory();
17
18         var startPromise = Promise.resolve();
19         var ws = new WritableStream({
20             start: function() {
21                 return startPromise;
22             },
23             write: function() {
24                 assert_unreached('Unexpected write call');
25             },
26             close: function() {
27                 closeCalled = true;
28             },
29             abort: function() {
30                 assert_unreached('Unexpected abort call');
31             }
32         });
33
34         startPromise.then(test2.step_func(function() {
35             assert_equals(ws.state, 'writable', 'writable stream should start in writable state');
36
37             return rs.pipeTo(ws).then(test2.step_func(function() {
38                 assert_true(closeCalled);
39                 assert_equals(ws.state, 'closed', 'writable stream should become closed');
40                 test2.done('underlying source close should be called');
41             }));
42         })).catch(test2.step_func(function(e) { assert_unreached(e); }));
43     });
44
45     var test3 = async_test('piping to a WritableStream in the writable state with { preventClose: true } should do nothing');
46     test3.step(function() {
47         var rs = factory();
48
49         var startPromise = Promise.resolve();
50         var ws = new WritableStream({
51             start: function() {
52                 return startPromise;
53             },
54             write: function() {
55                 assert_unreached('Unexpected write call');
56             },
57             close: function() {
58                 assert_unreached('Unexpected close call');
59             },
60             abort: function() {
61                 assert_unreached('Unexpected abort call');
62             }
63         });
64
65         startPromise.then(test3.step_func(function() {
66             assert_equals(ws.state, 'writable', 'writable stream should start in writable state');
67
68             return rs.pipeTo(ws, { preventClose: true }).then(test3.step_func(function() {
69                 assert_equals(ws.state, 'writable', 'writable stream should still be writable');
70                 test3.done('pipeTo promise should be fulfilled');
71             }));
72         })).catch(test3.step_func(function(e) { assert_unreached(e); }));
73     });
74 };
75
76 function templatedRSErrored(label, factory, error) {
77     test(function() {
78     }, 'Running templatedRSErrored with ' + label);
79
80     var test1 = async_test('piping to a WritableStream in the writable state should abort the writable stream');
81     test1.step(function() {
82         var rs = factory();
83
84         var startPromise = Promise.resolve();
85         var ws = new WritableStream({
86             start: function() {
87                 return startPromise;
88             },
89             write: function() {
90                 assert_unreached('Unexpected write call');
91             },
92             close: function() {
93                 assert_reached('Unexpected close call');
94             },
95             abort: function(reason) {
96                 assert_equals(reason, error);
97             }
98         });
99
100         startPromise.then(test1.step_func(function() {
101             assert_equals(ws.state, 'writable');
102
103             rs.pipeTo(ws).then(
104                 test1.step_func(function() { assert_unreached('pipeTo promise should not be fulfilled'); }),
105                 test1.step_func(function(e) {
106                     assert_equals(e, error, 'pipeTo promise should be rejected with the passed error');
107                     assert_equals(ws.state, 'errored', 'writable stream should become errored');
108                     test1.done();
109                 })
110             );
111         }));
112     });
113 };
114
115 function templatedRSErroredAsyncOnly(label, factory, error) {
116     test(function() {
117     }, 'Running templatedRSErroredAsyncOnly with ' + label);
118
119     var test1 = async_test('piping with no options');
120     test1.step(function() {
121         var closeCalled = false;
122
123         var rs = factory();
124
125         var ws = new WritableStream({
126             abort: function(r) {
127                 assert_equals(r, error, 'reason passed to abort should equal the source error');
128             }
129         });
130
131         rs.pipeTo(ws).catch(test1.step_func(function(e) {
132             assert_equals(ws.state, 'errored', 'destination should be errored');
133             assert_equals(e, error, 'rejection reason of pipeToPromise should be the source error');
134             assert_true(closeCalled);
135             test1.done();
136         }));
137
138         ws.closed.catch(test1.step_func(function(e) {
139             assert_equals(e, error, 'rejection reason of dest closed should be the source error');
140             closeCalled = true;
141         }))
142     });
143
144     var test2 = async_test('piping with { preventAbort: false }');
145     test2.step(function() {
146         var abortCalled = false;
147         var closeRejected = false;
148
149         var rs = factory();
150
151         var ws = new WritableStream({
152             abort: function(r) {
153                 assert_equals(r, error, 'reason passed to abort should equal the source error');
154                 abortCalled = true;
155             }
156         });
157
158         rs.pipeTo(ws, { preventAbort: false }).catch(test2.step_func(function(e) {
159             assert_equals(ws.state, 'errored', 'destination should be errored');
160             assert_equals(e, error, 'rejection reason of pipeToPromise should be the source error');
161             assert_true(abortCalled);
162             assert_true(closeRejected);
163             test2.done();
164         }));
165
166         ws.closed.catch(test2.step_func(function(e) {
167             assert_equals(e, error, 'rejection reason of dest closed should be the source error');
168             closeRejected = true;
169         }));
170     });
171
172     var test3 = async_test('piping with { preventAbort: true }');
173     test3.step(function() {
174         var rs = factory();
175
176         var ws = new WritableStream({
177             abort: function() {
178                 assert_unreached('underlying sink abort should not be called');
179             }
180         });
181
182         rs.pipeTo(ws, { preventAbort: true }).catch(test3.step_func(function(e) {
183             assert_equals(ws.state, 'writable', 'destination should remain writable');
184             assert_equals(e, error, 'rejection reason of pipeToPromise should be the source error');
185             test3.done();
186         }));
187    });
188 };
189
190 function templatedRSTwoChunksClosed(label, factory, error) {
191     test(function() {
192     }, 'Running templatedRSTwoChunksClosed with ' + label);
193
194     var test1 = async_test('piping with no options and no destination errors');
195     test1.step(function() {
196         var rs = factory();
197
198         var chunksWritten = [];
199         var ws = new WritableStream({
200             abort: function() {
201                 assert_unreached('unexpected abort call');
202             },
203             write: function(chunk) {
204                 chunksWritten.push(chunk);
205             }
206         });
207
208         rs.pipeTo(ws).then(test1.step_func(function() {
209             assert_equals(ws.state, 'closed', 'destination should be closed');
210             assert_array_equals(chunksWritten, chunks);
211             test1.done();
212         }));
213     });
214
215     var test2 = async_test('piping with { preventClose: false } and no destination errors');
216     test2.step(function() {
217         var rs = factory();
218
219         var chunksWritten = [];
220         var ws = new WritableStream({
221             abort: function() {
222                 assert_unreached('unexpected abort call');
223             },
224             write: function(chunk) {
225                 chunksWritten.push(chunk);
226             }
227         });
228
229         rs.pipeTo(ws).then(test2.step_func(function() {
230             assert_equals(ws.state, 'closed', 'destination should be closed');
231             assert_array_equals(chunksWritten, chunks);
232             test2.done();
233         }));
234     });
235
236     var test3 = async_test('piping with { preventClose: true } and no destination errors');
237     test3.step(function() {
238         var rs = factory();
239
240         var chunksWritten = [];
241         var ws = new WritableStream({
242             close: function() {
243                 assert_unreached('unexpected close call');
244             },
245             abort: function() {
246                 assert_unreached('unexpected abort call');
247             },
248             write: function(chunk) {
249                 chunksWritten.push(chunk);
250             }
251         });
252
253         rs.pipeTo(ws, { preventClose: true }).then(test3.step_func(function() {
254             assert_equals(ws.state, 'writable', 'destination should be writable');
255             assert_array_equals(chunksWritten, chunks);
256             test3.done();
257         }));
258     });
259
260     var test4 = async_test('piping with { preventClose: false } and a destination with that errors synchronously');
261     test4.step(function() {
262         var rs = factory();
263
264         var theError = new Error('!!!');
265         var ws = new WritableStream({
266             close: function() {
267                 assert_unreached('unexpected close call');
268             },
269             abort: function() {
270                 assert_unreached('unexpected abort call');
271             },
272             write: function() {
273                 throw theError;
274             }
275         });
276
277         rs.pipeTo(ws, { preventClose: false }).then(
278             test4.step_func(function() { assert_unreached('pipeTo promise should not fulfill'); }),
279             test4.step_func(function(e) {
280                 assert_equals(e, theError, 'pipeTo promise should reject with the write error');
281                 test4.done();
282             })
283         );
284     });
285
286     var test5 = async_test('piping with { preventClose: true } and a destination with that errors synchronously');
287     test5.step(function() {
288         var rs = factory();
289
290         var theError = new Error('!!!');
291         var ws = new WritableStream({
292             close: function() {
293                 assert_unreached('unexpected close call');
294             },
295             abort: function() {
296                 assert_unreached('unexpected abort call');
297             },
298             write: function() {
299                 throw theError;
300             }
301         });
302
303         rs.pipeTo(ws, { preventClose: true }).then(
304             test5.step_func(function() { assert_unreached('pipeTo promise should not fulfill'); }),
305             test5.step_func(function(e) {
306                 assert_equals(e, theError, 'pipeTo promise should reject with the write error');
307                 test5.done();
308             })
309         );
310     });
311
312     var test6 = async_test('piping with { preventClose: true } and a destination that errors on the last chunk');
313     test6.step(function() {
314         var rs = factory();
315
316         var theError = new Error('!!!');
317         var chunkCounter = 0;
318         var ws = new WritableStream(
319             {
320                 close: function() {
321                     assert_unreached('unexpected close call');
322                 },
323                 abort: function() {
324                     assert_unreached('unexpected abort call');
325                 },
326                 write: function() {
327                     if (++chunkCounter === 2) {
328                         return new Promise(test6.step_func(function(r, reject) { setTimeout(test6.step_func(function() { reject(theError); }), 200); }));
329                     }
330                 }
331             },
332             {
333                 highWaterMark: Infinity,
334                 size: function() { return 1; }
335             }
336         );
337
338         rs.pipeTo(ws, { preventClose: true }).then(
339             test6.step_func(function() { assert_unreached('pipeTo promise should not fulfill'); }),
340             test6.step_func(function(e) {
341                 assert_equals(e, theError, 'pipeTo promise should reject with the write error');
342                 test6.done();
343             })
344         );
345     });
346 };
347
348 templatedRSClosed('ReadableStream (closed via call in start)', function() {
349     return new ReadableStream({
350         start: function(c) {
351             c.close();
352         }
353     });
354 });
355
356 templatedRSClosed('ReadableStream (closed via cancel)', function() {
357     var stream = new ReadableStream();
358     stream.cancel();
359     return stream;
360 });
361 var theError = new Error('boo!');
362
363 templatedRSErrored('ReadableStream (errored via call in start)', function() {
364     return new ReadableStream({
365         start: function(c) {
366             c.error(theError);
367         }
368     })},
369     theError
370 );
371
372 templatedRSErrored('ReadableStream (errored via returning a rejected promise in start)', function() {
373     return new ReadableStream({
374         start: function() {
375             return Promise.reject(theError);
376         }
377     })},
378     theError
379 );
380
381 templatedRSErroredAsyncOnly('ReadableStream (errored via returning a rejected promise in start) reader', function() {
382     return new ReadableStream({
383         start: function() { return Promise.reject(theError); }
384     })},
385     theError
386 );
387
388 var chunks = ['a', 'b'];
389
390 templatedRSTwoChunksClosed('ReadableStream (two chunks enqueued, then closed)', function() {
391     return new ReadableStream({
392         start: function(c) {
393             c.enqueue(chunks[0]);
394             c.enqueue(chunks[1]);
395             c.close();
396         }
397     })},
398     chunks
399 );
400
401 templatedRSTwoChunksClosed('ReadableStream (two chunks enqueued async, then closed)', function() {
402     return new ReadableStream({
403         start: function(c) {
404             setTimeout(function() { c.enqueue(chunks[0]); }, 100);
405             setTimeout(function() { c.enqueue(chunks[1]); }, 200);
406             setTimeout(function() { c.close(); }, 300);
407         }
408     })},
409     chunks
410 );
411
412 templatedRSTwoChunksClosed('ReadableStream (two chunks enqueued via pull, then closed)', function() {
413     var pullCall = 0;
414
415     return new ReadableStream({
416         pull:function(c) {
417             if (pullCall >= chunks.length) {
418                 c.close();
419             } else {
420                 c.enqueue(chunks[pullCall++]);
421             }
422         }
423     });
424 },
425 chunks
426 );
427 </script>