OLD | NEW |
| (Empty) |
1 'use strict'; | |
2 | |
3 // These tests can be run against any readable stream produced by the web platfo
rm that meets the given descriptions. | |
4 // For readable stream tests, the factory should return the stream. For reader t
ests, the factory should return a | |
5 // { stream, reader } object. (You can use this to vary the time at which you ac
quire a reader.) | |
6 | |
7 self.templatedRSEmpty = (label, factory) => { | |
8 test(() => {}, 'Running templatedRSEmpty with ' + label); | |
9 | |
10 test(() => { | |
11 | |
12 const rs = factory(); | |
13 | |
14 assert_equals(typeof rs.locked, 'boolean', 'has a boolean locked getter'); | |
15 assert_equals(typeof rs.cancel, 'function', 'has a cancel method'); | |
16 assert_equals(typeof rs.getReader, 'function', 'has a getReader method'); | |
17 assert_equals(typeof rs.tee, 'function', 'has a tee method'); | |
18 | |
19 }, 'instances have the correct methods and properties'); | |
20 | |
21 test(() => { | |
22 const rs = factory(); | |
23 | |
24 assert_throws(new RangeError(), () => rs.getReader({ mode: '' }), 'empty str
ing mode should throw'); | |
25 assert_throws(new RangeError(), () => rs.getReader({ mode: null }), 'null mo
de should throw'); | |
26 assert_throws(new RangeError(), () => rs.getReader({ mode: 'asdf' }), 'asdf
mode should throw'); | |
27 assert_throws(new TypeError(), () => rs.getReader(null), 'null should throw'
); | |
28 | |
29 }, 'calling getReader with invalid arguments should throw appropriate errors')
; | |
30 }; | |
31 | |
32 self.templatedRSClosed = (label, factory) => { | |
33 test(() => {}, 'Running templatedRSClosed with ' + label); | |
34 | |
35 promise_test(() => { | |
36 | |
37 const rs = factory(); | |
38 const cancelPromise1 = rs.cancel(); | |
39 const cancelPromise2 = rs.cancel(); | |
40 | |
41 assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should ret
urn distinct promises'); | |
42 | |
43 return Promise.all([ | |
44 cancelPromise1.then(v => assert_equals(v, undefined, 'first cancel() call
should fulfill with undefined')), | |
45 cancelPromise2.then(v => assert_equals(v, undefined, 'second cancel() call
should fulfill with undefined')) | |
46 ]); | |
47 | |
48 }, 'cancel() should return a distinct fulfilled promise each time'); | |
49 | |
50 test(() => { | |
51 | |
52 const rs = factory(); | |
53 assert_false(rs.locked, 'locked getter should return false'); | |
54 | |
55 }, 'locked should be false'); | |
56 | |
57 test(() => { | |
58 | |
59 const rs = factory(); | |
60 rs.getReader(); // getReader() should not throw. | |
61 | |
62 }, 'getReader() should be OK'); | |
63 | |
64 test(() => { | |
65 | |
66 const rs = factory(); | |
67 | |
68 const reader = rs.getReader(); | |
69 reader.releaseLock(); | |
70 | |
71 const reader2 = rs.getReader(); // Getting a second reader should not throw. | |
72 reader2.releaseLock(); | |
73 | |
74 rs.getReader(); // Getting a third reader should not throw. | |
75 | |
76 }, 'should be able to acquire multiple readers if they are released in success
ion'); | |
77 | |
78 test(() => { | |
79 | |
80 const rs = factory(); | |
81 | |
82 rs.getReader(); | |
83 | |
84 assert_throws(new TypeError(), () => rs.getReader(), 'getting a second reade
r should throw'); | |
85 assert_throws(new TypeError(), () => rs.getReader(), 'getting a third reader
should throw'); | |
86 | |
87 }, 'should not be able to acquire a second reader if we don\'t release the fir
st one'); | |
88 }; | |
89 | |
90 self.templatedRSErrored = (label, factory, error) => { | |
91 test(() => {}, 'Running templatedRSErrored with ' + label); | |
92 | |
93 promise_test(t => { | |
94 | |
95 const rs = factory(); | |
96 const reader = rs.getReader(); | |
97 | |
98 return Promise.all([ | |
99 promise_rejects(t, error, reader.closed), | |
100 promise_rejects(t, error, reader.read()) | |
101 ]); | |
102 | |
103 }, 'getReader() should return a reader that acts errored'); | |
104 | |
105 promise_test(t => { | |
106 | |
107 const rs = factory(); | |
108 const reader = rs.getReader(); | |
109 | |
110 return Promise.all([ | |
111 promise_rejects(t, error, reader.read()), | |
112 promise_rejects(t, error, reader.read()), | |
113 promise_rejects(t, error, reader.closed) | |
114 ]); | |
115 | |
116 }, 'read() twice should give the error each time'); | |
117 | |
118 test(() => { | |
119 const rs = factory(); | |
120 | |
121 assert_false(rs.locked, 'locked getter should return false'); | |
122 }, 'locked should be false'); | |
123 }; | |
124 | |
125 self.templatedRSErroredSyncOnly = (label, factory, error) => { | |
126 test(() => {}, 'Running templatedRSErroredSyncOnly with ' + label); | |
127 | |
128 promise_test(t => { | |
129 | |
130 const rs = factory(); | |
131 rs.getReader().releaseLock(); | |
132 const reader = rs.getReader(); // Calling getReader() twice does not throw (
the stream is not locked). | |
133 | |
134 return promise_rejects(t, error, reader.closed); | |
135 | |
136 }, 'should be able to obtain a second reader, with the correct closed promise'
); | |
137 | |
138 test(() => { | |
139 | |
140 const rs = factory(); | |
141 rs.getReader(); | |
142 | |
143 assert_throws(new TypeError(), () => rs.getReader(), 'getting a second reade
r should throw a TypeError'); | |
144 assert_throws(new TypeError(), () => rs.getReader(), 'getting a third reader
should throw a TypeError'); | |
145 | |
146 }, 'should not be able to obtain additional readers if we don\'t release the f
irst lock'); | |
147 | |
148 promise_test(t => { | |
149 | |
150 const rs = factory(); | |
151 const cancelPromise1 = rs.cancel(); | |
152 const cancelPromise2 = rs.cancel(); | |
153 | |
154 assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should ret
urn distinct promises'); | |
155 | |
156 return Promise.all([ | |
157 promise_rejects(t, error, cancelPromise1), | |
158 promise_rejects(t, error, cancelPromise2) | |
159 ]); | |
160 | |
161 }, 'cancel() should return a distinct rejected promise each time'); | |
162 | |
163 promise_test(t => { | |
164 | |
165 const rs = factory(); | |
166 const reader = rs.getReader(); | |
167 const cancelPromise1 = reader.cancel(); | |
168 const cancelPromise2 = reader.cancel(); | |
169 | |
170 assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should ret
urn distinct promises'); | |
171 | |
172 return Promise.all([ | |
173 promise_rejects(t, error, cancelPromise1), | |
174 promise_rejects(t, error, cancelPromise2) | |
175 ]); | |
176 | |
177 }, 'reader cancel() should return a distinct rejected promise each time'); | |
178 }; | |
179 | |
180 self.templatedRSEmptyReader = (label, factory) => { | |
181 test(() => {}, 'Running templatedRSEmptyReader with ' + label); | |
182 | |
183 test(() => { | |
184 | |
185 const reader = factory().reader; | |
186 | |
187 assert_true('closed' in reader, 'has a closed property'); | |
188 assert_equals(typeof reader.closed.then, 'function', 'closed property is the
nable'); | |
189 | |
190 assert_equals(typeof reader.cancel, 'function', 'has a cancel method'); | |
191 assert_equals(typeof reader.read, 'function', 'has a read method'); | |
192 assert_equals(typeof reader.releaseLock, 'function', 'has a releaseLock meth
od'); | |
193 | |
194 }, 'instances have the correct methods and properties'); | |
195 | |
196 test(() => { | |
197 | |
198 const stream = factory().stream; | |
199 | |
200 assert_true(stream.locked, 'locked getter should return true'); | |
201 | |
202 }, 'locked should be true'); | |
203 | |
204 promise_test(t => { | |
205 | |
206 const reader = factory().reader; | |
207 | |
208 reader.read().then( | |
209 t.unreached_func('read() should not fulfill'), | |
210 t.unreached_func('read() should not reject') | |
211 ); | |
212 | |
213 return delay(500); | |
214 | |
215 }, 'read() should never settle'); | |
216 | |
217 promise_test(t => { | |
218 | |
219 const reader = factory().reader; | |
220 | |
221 reader.read().then( | |
222 t.unreached_func('read() should not fulfill'), | |
223 t.unreached_func('read() should not reject') | |
224 ); | |
225 | |
226 reader.read().then( | |
227 t.unreached_func('read() should not fulfill'), | |
228 t.unreached_func('read() should not reject') | |
229 ); | |
230 | |
231 return delay(500); | |
232 | |
233 }, 'two read()s should both never settle'); | |
234 | |
235 test(() => { | |
236 | |
237 const reader = factory().reader; | |
238 assert_not_equals(reader.read(), reader.read(), 'the promises returned shoul
d be distinct'); | |
239 | |
240 }, 'read() should return distinct promises each time'); | |
241 | |
242 test(() => { | |
243 | |
244 const stream = factory().stream; | |
245 assert_throws(new TypeError(), () => stream.getReader(), 'stream.getReader()
should throw a TypeError'); | |
246 | |
247 }, 'getReader() again on the stream should fail'); | |
248 | |
249 promise_test(t => { | |
250 | |
251 const streamAndReader = factory(); | |
252 const stream = streamAndReader.stream; | |
253 const reader = streamAndReader.reader; | |
254 | |
255 reader.read().then( | |
256 t.unreached_func('first read() should not fulfill'), | |
257 t.unreached_func('first read() should not reject') | |
258 ); | |
259 | |
260 reader.read().then( | |
261 t.unreached_func('second read() should not fulfill'), | |
262 t.unreached_func('second read() should not reject') | |
263 ); | |
264 | |
265 reader.closed.then( | |
266 t.unreached_func('closed should not fulfill'), | |
267 t.unreached_func('closed should not reject') | |
268 ); | |
269 | |
270 assert_throws(new TypeError(), () => reader.releaseLock(), 'releaseLock shou
ld throw a TypeError'); | |
271 | |
272 assert_true(stream.locked, 'the stream should still be locked'); | |
273 | |
274 return delay(500); | |
275 | |
276 }, 'releasing the lock with pending read requests should throw but the read re
quests should stay pending'); | |
277 | |
278 promise_test(t => { | |
279 | |
280 const reader = factory().reader; | |
281 reader.releaseLock(); | |
282 | |
283 return Promise.all([ | |
284 promise_rejects(t, new TypeError(), reader.read()), | |
285 promise_rejects(t, new TypeError(), reader.read()) | |
286 ]); | |
287 | |
288 }, 'releasing the lock should cause further read() calls to reject with a Type
Error'); | |
289 | |
290 promise_test(t => { | |
291 | |
292 const reader = factory().reader; | |
293 | |
294 const closedBefore = reader.closed; | |
295 reader.releaseLock(); | |
296 const closedAfter = reader.closed; | |
297 | |
298 assert_equals(closedBefore, closedAfter, 'the closed promise should not chan
ge identity'); | |
299 | |
300 return promise_rejects(t, new TypeError(), closedBefore); | |
301 | |
302 }, 'releasing the lock should cause closed calls to reject with a TypeError'); | |
303 | |
304 test(() => { | |
305 | |
306 const streamAndReader = factory(); | |
307 const stream = streamAndReader.stream; | |
308 const reader = streamAndReader.reader; | |
309 | |
310 reader.releaseLock(); | |
311 assert_false(stream.locked, 'locked getter should return false'); | |
312 | |
313 }, 'releasing the lock should cause locked to become false'); | |
314 | |
315 promise_test(() => { | |
316 | |
317 const reader = factory().reader; | |
318 reader.cancel(); | |
319 | |
320 return reader.read().then(r => { | |
321 assert_object_equals(r, { value: undefined, done: true }, 'read()ing from
the reader should give a done result'); | |
322 }); | |
323 | |
324 }, 'canceling via the reader should cause the reader to act closed'); | |
325 | |
326 promise_test(t => { | |
327 | |
328 const stream = factory().stream; | |
329 return promise_rejects(t, new TypeError(), stream.cancel()); | |
330 | |
331 }, 'canceling via the stream should fail'); | |
332 }; | |
333 | |
334 self.templatedRSClosedReader = (label, factory) => { | |
335 test(() => {}, 'Running templatedRSClosedReader with ' + label); | |
336 | |
337 promise_test(() => { | |
338 | |
339 const reader = factory().reader; | |
340 | |
341 return reader.read().then(v => { | |
342 assert_object_equals(v, { value: undefined, done: true }, 'read() should f
ulfill correctly'); | |
343 }); | |
344 | |
345 }, 'read() should fulfill with { value: undefined, done: true }'); | |
346 | |
347 promise_test(() => { | |
348 | |
349 const reader = factory().reader; | |
350 | |
351 return Promise.all([ | |
352 reader.read().then(v => { | |
353 assert_object_equals(v, { value: undefined, done: true }, 'read() should
fulfill correctly'); | |
354 }), | |
355 reader.read().then(v => { | |
356 assert_object_equals(v, { value: undefined, done: true }, 'read() should
fulfill correctly'); | |
357 }) | |
358 ]); | |
359 | |
360 }, 'read() multiple times should fulfill with { value: undefined, done: true }
'); | |
361 | |
362 promise_test(() => { | |
363 | |
364 const reader = factory().reader; | |
365 | |
366 return reader.read().then(() => reader.read()).then(v => { | |
367 assert_object_equals(v, { value: undefined, done: true }, 'read() should f
ulfill correctly'); | |
368 }); | |
369 | |
370 }, 'read() should work when used within another read() fulfill callback'); | |
371 | |
372 promise_test(() => { | |
373 | |
374 const reader = factory().reader; | |
375 | |
376 return reader.closed.then(v => assert_equals(v, undefined, 'reader closed sh
ould fulfill with undefined')); | |
377 | |
378 }, 'closed should fulfill with undefined'); | |
379 | |
380 promise_test(t => { | |
381 | |
382 const reader = factory().reader; | |
383 | |
384 const closedBefore = reader.closed; | |
385 reader.releaseLock(); | |
386 const closedAfter = reader.closed; | |
387 | |
388 assert_not_equals(closedBefore, closedAfter, 'the closed promise should chan
ge identity'); | |
389 | |
390 return Promise.all([ | |
391 closedBefore.then(v => assert_equals(v, undefined, 'reader.closed acquired
before release should fulfill')), | |
392 promise_rejects(t, new TypeError(), closedAfter) | |
393 ]); | |
394 | |
395 }, 'releasing the lock should cause closed to reject and change identity'); | |
396 | |
397 promise_test(() => { | |
398 | |
399 const reader = factory().reader; | |
400 const cancelPromise1 = reader.cancel(); | |
401 const cancelPromise2 = reader.cancel(); | |
402 const closedReaderPromise = reader.closed; | |
403 | |
404 assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should ret
urn distinct promises'); | |
405 assert_not_equals(cancelPromise1, closedReaderPromise, 'cancel() promise 1 s
hould be distinct from reader.closed'); | |
406 assert_not_equals(cancelPromise2, closedReaderPromise, 'cancel() promise 2 s
hould be distinct from reader.closed'); | |
407 | |
408 return Promise.all([ | |
409 cancelPromise1.then(v => assert_equals(v, undefined, 'first cancel() shoul
d fulfill with undefined')), | |
410 cancelPromise2.then(v => assert_equals(v, undefined, 'second cancel() shou
ld fulfill with undefined')) | |
411 ]); | |
412 | |
413 }, 'cancel() should return a distinct fulfilled promise each time'); | |
414 }; | |
415 | |
416 self.templatedRSErroredReader = (label, factory, error) => { | |
417 test(() => {}, 'Running templatedRSErroredReader with ' + label); | |
418 | |
419 promise_test(t => { | |
420 | |
421 const reader = factory().reader; | |
422 return promise_rejects(t, error, reader.closed); | |
423 | |
424 }, 'closed should reject with the error'); | |
425 | |
426 promise_test(t => { | |
427 | |
428 const reader = factory().reader; | |
429 const closedBefore = reader.closed; | |
430 | |
431 return promise_rejects(t, error, closedBefore).then(() => { | |
432 reader.releaseLock(); | |
433 | |
434 const closedAfter = reader.closed; | |
435 assert_not_equals(closedBefore, closedAfter, 'the closed promise should ch
ange identity'); | |
436 | |
437 return promise_rejects(t, new TypeError(), closedAfter); | |
438 }); | |
439 | |
440 }, 'releasing the lock should cause closed to reject and change identity'); | |
441 | |
442 promise_test(t => { | |
443 | |
444 const reader = factory().reader; | |
445 return promise_rejects(t, error, reader.read()); | |
446 | |
447 }, 'read() should reject with the error'); | |
448 }; | |
449 | |
450 self.templatedRSTwoChunksOpenReader = (label, factory, chunks) => { | |
451 test(() => {}, 'Running templatedRSTwoChunksOpenReader with ' + label); | |
452 | |
453 promise_test(() => { | |
454 | |
455 const reader = factory().reader; | |
456 | |
457 return Promise.all([ | |
458 reader.read().then(r => { | |
459 assert_object_equals(r, { value: chunks[0], done: false }, 'first result
should be correct'); | |
460 }), | |
461 reader.read().then(r => { | |
462 assert_object_equals(r, { value: chunks[1], done: false }, 'second resul
t should be correct'); | |
463 }) | |
464 ]); | |
465 | |
466 }, 'calling read() twice without waiting will eventually give both chunks (seq
uential)'); | |
467 | |
468 promise_test(() => { | |
469 | |
470 const reader = factory().reader; | |
471 | |
472 return reader.read().then(r => { | |
473 assert_object_equals(r, { value: chunks[0], done: false }, 'first result s
hould be correct'); | |
474 | |
475 return reader.read().then(r2 => { | |
476 assert_object_equals(r2, { value: chunks[1], done: false }, 'second resu
lt should be correct'); | |
477 }); | |
478 }); | |
479 | |
480 }, 'calling read() twice without waiting will eventually give both chunks (nes
ted)'); | |
481 | |
482 test(() => { | |
483 | |
484 const reader = factory().reader; | |
485 assert_not_equals(reader.read(), reader.read(), 'the promises returned shoul
d be distinct'); | |
486 | |
487 }, 'read() should return distinct promises each time'); | |
488 | |
489 promise_test(() => { | |
490 | |
491 const reader = factory().reader; | |
492 | |
493 const promise1 = reader.closed.then(v => { | |
494 assert_equals(v, undefined, 'reader closed should fulfill with undefined')
; | |
495 }); | |
496 | |
497 const promise2 = reader.read().then(r => { | |
498 assert_object_equals(r, { value: chunks[0], done: false }, | |
499 'promise returned before cancellation should fulfill
with a chunk'); | |
500 }); | |
501 | |
502 reader.cancel(); | |
503 | |
504 const promise3 = reader.read().then(r => { | |
505 assert_object_equals(r, { value: undefined, done: true }, | |
506 'promise returned after cancellation should fulfill w
ith an end-of-stream signal'); | |
507 }); | |
508 | |
509 return Promise.all([promise1, promise2, promise3]); | |
510 | |
511 }, 'cancel() after a read() should still give that single read result'); | |
512 }; | |
513 | |
514 self.templatedRSTwoChunksClosedReader = function (label, factory, chunks) { | |
515 test(() => {}, 'Running templatedRSTwoChunksClosedReader with ' + label); | |
516 | |
517 promise_test(() => { | |
518 | |
519 const reader = factory().reader; | |
520 | |
521 return Promise.all([ | |
522 reader.read().then(r => { | |
523 assert_object_equals(r, { value: chunks[0], done: false }, 'first result
should be correct'); | |
524 }), | |
525 reader.read().then(r => { | |
526 assert_object_equals(r, { value: chunks[1], done: false }, 'second resul
t should be correct'); | |
527 }), | |
528 reader.read().then(r => { | |
529 assert_object_equals(r, { value: undefined, done: true }, 'third result
should be correct'); | |
530 }) | |
531 ]); | |
532 | |
533 }, 'third read(), without waiting, should give { value: undefined, done: true
} (sequential)'); | |
534 | |
535 promise_test(() => { | |
536 | |
537 const reader = factory().reader; | |
538 | |
539 return reader.read().then(r => { | |
540 assert_object_equals(r, { value: chunks[0], done: false }, 'first result s
hould be correct'); | |
541 | |
542 return reader.read().then(r2 => { | |
543 assert_object_equals(r2, { value: chunks[1], done: false }, 'second resu
lt should be correct'); | |
544 | |
545 return reader.read().then(r3 => { | |
546 assert_object_equals(r3, { value: undefined, done: true }, 'third resu
lt should be correct'); | |
547 }); | |
548 }); | |
549 }); | |
550 | |
551 }, 'third read(), without waiting, should give { value: undefined, done: true
} (nested)'); | |
552 | |
553 promise_test(() => { | |
554 | |
555 const streamAndReader = factory(); | |
556 const stream = streamAndReader.stream; | |
557 const reader = streamAndReader.reader; | |
558 | |
559 assert_true(stream.locked, 'stream should start locked'); | |
560 | |
561 const promise = reader.closed.then(v => { | |
562 assert_equals(v, undefined, 'reader closed should fulfill with undefined')
; | |
563 assert_true(stream.locked, 'stream should remain locked'); | |
564 }); | |
565 | |
566 reader.read(); | |
567 reader.read(); | |
568 | |
569 return promise; | |
570 | |
571 }, 'draining the stream via read() should cause the reader closed promise to f
ulfill, but locked stays true'); | |
572 | |
573 promise_test(() => { | |
574 | |
575 const streamAndReader = factory(); | |
576 const stream = streamAndReader.stream; | |
577 const reader = streamAndReader.reader; | |
578 | |
579 const promise = reader.closed.then(() => { | |
580 assert_true(stream.locked, 'the stream should start locked'); | |
581 reader.releaseLock(); // Releasing the lock after reader closed should not
throw. | |
582 assert_false(stream.locked, 'the stream should end unlocked'); | |
583 }); | |
584 | |
585 reader.read(); | |
586 reader.read(); | |
587 | |
588 return promise; | |
589 | |
590 }, 'releasing the lock after the stream is closed should cause locked to becom
e false'); | |
591 | |
592 promise_test(t => { | |
593 | |
594 const reader = factory().reader; | |
595 | |
596 reader.releaseLock(); | |
597 | |
598 return Promise.all([ | |
599 promise_rejects(t, new TypeError(), reader.read()), | |
600 promise_rejects(t, new TypeError(), reader.read()), | |
601 promise_rejects(t, new TypeError(), reader.read()) | |
602 ]); | |
603 | |
604 }, 'releasing the lock should cause further read() calls to reject with a Type
Error'); | |
605 | |
606 promise_test(() => { | |
607 | |
608 const streamAndReader = factory(); | |
609 const stream = streamAndReader.stream; | |
610 const reader = streamAndReader.reader; | |
611 | |
612 const readerClosed = reader.closed; | |
613 | |
614 assert_equals(reader.closed, readerClosed, 'accessing reader.closed twice in
succession gives the same value'); | |
615 | |
616 const promise = reader.read().then(() => { | |
617 assert_equals(reader.closed, readerClosed, 'reader.closed is the same afte
r read() fulfills'); | |
618 | |
619 reader.releaseLock(); | |
620 | |
621 assert_equals(reader.closed, readerClosed, 'reader.closed is the same afte
r releasing the lock'); | |
622 | |
623 const newReader = stream.getReader(); | |
624 return newReader.read(); | |
625 }); | |
626 | |
627 assert_equals(reader.closed, readerClosed, 'reader.closed is the same after
calling read()'); | |
628 | |
629 return promise; | |
630 | |
631 }, 'reader\'s closed property always returns the same promise'); | |
632 }; | |
OLD | NEW |