Index: third_party/WebKit/LayoutTests/http/tests/streams/readable-streams/cancel.js |
diff --git a/third_party/WebKit/LayoutTests/http/tests/streams/readable-streams/cancel.js b/third_party/WebKit/LayoutTests/http/tests/streams/readable-streams/cancel.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..edb16dd73c7ffdb859ba4154ecbaee19aec93476 |
--- /dev/null |
+++ b/third_party/WebKit/LayoutTests/http/tests/streams/readable-streams/cancel.js |
@@ -0,0 +1,262 @@ |
+'use strict'; |
+ |
+if (self.importScripts) { |
+ self.importScripts('../resources/rs-utils.js'); |
+ self.importScripts('/resources/testharness.js'); |
+} |
+ |
+var test1 = async_test('ReadableStream cancellation: integration test on an infinite stream derived from a random push source'); |
+test1.step(function() { |
+ var randomSource = new RandomPushSource(); |
+ |
+ var cancellationFinished = false; |
+ var rs = new ReadableStream({ |
+ start: function(c) { |
+ randomSource.ondata = c.enqueue.bind(c); |
+ randomSource.onend = c.close.bind(c); |
+ randomSource.onerror = c.error.bind(c); |
+ }, |
+ |
+ pull: function() { |
+ randomSource.readStart(); |
+ }, |
+ |
+ cancel: function() { |
+ randomSource.readStop(); |
+ randomSource.onend(); |
+ |
+ return new Promise(test1.step_func(function(resolve) { |
+ setTimeout(test1.step_func(function() { |
+ cancellationFinished = true; |
+ resolve(); |
+ }), 500); |
+ })); |
+ } |
+ }); |
+ var reader = rs.getReader(); |
+ |
+ readableStreamToArray(rs, reader).then(test1.step_func(function(chunks) { |
+ assert_equals(cancellationFinished, false, 'it did not wait for the cancellation process to finish before closing'); |
+ assert_greater_than(chunks.length, 0, 'at least one chunk should be read'); |
+ for (var i = 0; i < chunks.length; i++) { |
+ assert_equals(chunks[i].length, 128, 'chunk ' + i + ' should have 128 bytes'); |
+ } |
+ }), test1.step_func(function(e) { assert_unreached(e); })); |
+ |
+ setTimeout(test1.step_func(function() { |
+ reader.cancel().then(test1.step_func(function() { |
+ assert_equals(cancellationFinished, true, 'it returns a promise that is fulfilled when the cancellation finishes'); |
+ test1.done(); |
+ })).catch(test1.step_func(function(e) { assert_unreached(e); })); |
+ }), 1000); |
+}); |
+ |
+test(function() { |
+ var recordedReason; |
+ var rs = new ReadableStream({ |
+ cancel: function(reason) { |
+ recordedReason = reason; |
+ } |
+ }); |
+ |
+ var passedReason = new Error('Sorry, it just wasn\'t meant to be.'); |
+ rs.cancel(passedReason); |
+ |
+ assert_equals(recordedReason, passedReason, |
+ 'the error passed to the underlying source\'s cancel method should equal the one passed to the stream\'s cancel'); |
+}, 'ReadableStream cancellation: cancel(reason) should pass through the given reason to the underlying source'); |
+ |
+var test2 = async_test('ReadableStream cancellation: cancel() on a locked stream should fail and not call the underlying source cancel'); |
+test2.step(function() { |
+ var rs = new ReadableStream({ |
+ start: function(c) { |
+ c.enqueue('a'); |
+ c.close(); |
+ }, |
+ cancel: function() { |
+ assert_unreached('underlying source cancel() should not have been called'); |
+ } |
+ }); |
+ |
+ var reader = rs.getReader(); |
+ |
+ rs.cancel().catch(test2.step_func(function(e) { |
+ assert_throws(new TypeError(), e, 'cancel() should be rejected with a TypeError') |
+ })); |
+ |
+ reader.read().then(test2.step_func(function(result) { |
+ assert_object_equals(result, { value: 'a', done: false }, 'read() should still work after the attempted cancel'); |
+ })); |
+ |
+ reader.closed.then(test2.step_func(function() { |
+ test2.done('closed should fulfill without underlying source cancel ever being called'); |
+ })); |
+}); |
+ |
+var test3 = async_test('ReadableStream cancellation: should fulfill promise when cancel callback went fine'); |
+test3.step(function() |
+{ |
+ var cancelReceived = false; |
+ var cancelReason = new Error('I am tired of this stream, I prefer to cancel it'); |
+ var rs = new ReadableStream({ |
+ cancel: function(reason) { |
+ cancelReceived = true; |
+ assert_equals(reason, cancelReason, 'cancellation reason given to the underlying source should be equal to the one passed'); |
+ } |
+ }); |
+ |
+ rs.cancel(cancelReason).then( |
+ test3.step_func(function() { |
+ assert_true(cancelReceived); |
+ test3.done('stream was successfully cancelled'); |
+ }), |
+ test3.step_func(function(e) { |
+ assert_unreached("received error " + e) |
+ })); |
+}); |
+ |
+var test4 = async_test('ReadableStream cancellation: returning a value from the underlying source\'s cancel should not affect the fulfillment value of the promise returned by the stream\'s cancel'); |
+test4.step(function() { |
+ var rs = new ReadableStream({ |
+ cancel: function(reason) { |
+ return 'Hello'; |
+ } |
+ }); |
+ |
+ rs.cancel().then(test4.step_func(function(v) { |
+ assert_equals(v, undefined, 'cancel() return value should be fulfilled with undefined'); |
+ test4.done(); |
+ }), test4.step_func(function() { |
+ assert_unreached('cancel() return value should not be rejected'); |
+ })); |
+}); |
+ |
+var test5 = async_test('ReadableStream cancellation: should reject promise when cancel callback raises an exception'); |
+test5.step(function() |
+{ |
+ var thrownError = new Error('test'); |
+ var cancelCalled = false; |
+ |
+ var rs = new ReadableStream({ |
+ cancel: function() { |
+ cancelCalled = true; |
+ throw thrownError; |
+ } |
+ }); |
+ |
+ rs.cancel('test').then( |
+ test5.step_func(function() { assert_unreached('cancel should reject'); }), |
+ test5.step_func(function(e) { |
+ assert_true(cancelCalled); |
+ assert_equals(e, thrownError); |
+ test5.done(); |
+ }) |
+ ); |
+}); |
+ |
+var test6 = async_test('ReadableStream cancellation: if the underlying source\'s cancel method returns a promise, the promise returned by the stream\'s cancel should fulfill when that one does (1)'); |
+test6.step(function() |
+{ |
+ var cancelReason = new Error('test'); |
+ |
+ var rs = new ReadableStream({ |
+ cancel: function(error) { |
+ assert_equals(error, cancelReason); |
+ return new Promise(test6.step_func(function(resolve, reject) { |
+ setTimeout(test6.step_func(function() { |
+ resolve(); |
+ }), 500); |
+ })) |
+ } |
+ }) |
+ |
+ rs.cancel(cancelReason).then( |
+ test6.step_func(function() { |
+ test6.done('stream successfully cancelled'); |
+ }), |
+ test6.step_func(function(e) { |
+ assert_unreached("received error " + e) |
+ })) |
+}); |
+ |
+var test7 = async_test('ReadableStream cancellation: if the underlying source\'s cancel method returns a promise, the promise returned by the stream\'s cancel should fulfill when that one does (2)'); |
+test7.step(function() { |
+ var resolveSourceCancelPromise; |
+ var sourceCancelPromiseHasFulfilled = false; |
+ var rs = new ReadableStream({ |
+ cancel: function() { |
+ var sourceCancelPromise = new Promise(test7.step_func(function(resolve, reject) { |
+ resolveSourceCancelPromise = resolve; |
+ })); |
+ |
+ sourceCancelPromise.then(test7.step_func(function() { |
+ sourceCancelPromiseHasFulfilled = true; |
+ })); |
+ |
+ return sourceCancelPromise; |
+ } |
+ }); |
+ |
+ |
+ rs.cancel().then( |
+ test7.step_func(function(value) { |
+ assert_true(sourceCancelPromiseHasFulfilled, 'cancel() return value should be fulfilled only after the promise returned by the underlying source\'s cancel'); |
+ assert_equals(value, undefined, 'cancel() return value should be fulfilled with undefined'); |
+ test7.done(); |
+ }), |
+ test7.step_func(function() { assert_unreached('cancel() return value should not be rejected'); }) |
+ ); |
+ |
+ setTimeout(test7.step_func(function() { |
+ resolveSourceCancelPromise('Hello'); |
+ }), 500); |
+}); |
+ |
+var test8 = async_test('ReadableStream cancellation: if the underlying source\'s cancel method returns a promise, the promise returned by the stream\'s cancel should reject when that one does'); |
+test8.step(function() { |
+ var rejectSourceCancelPromise; |
+ var sourceCancelPromiseHasRejected = false; |
+ var rs = new ReadableStream({ |
+ cancel: function() { |
+ var sourceCancelPromise = new Promise(test8.step_func(function(resolve, reject) { |
+ rejectSourceCancelPromise = reject; |
+ })); |
+ |
+ sourceCancelPromise.catch(test8.step_func(function() { |
+ sourceCancelPromiseHasRejected = true; |
+ })); |
+ |
+ return sourceCancelPromise; |
+ } |
+ }); |
+ |
+ var errorInCancel = new Error('Sorry, it just wasn\'t meant to be.'); |
+ |
+ rs.cancel().then( |
+ test8.step_func(function() { assert_unreached('cancel() return value should not be rejected'); }), |
+ test8.step_func(function(r) { |
+ assert_true(sourceCancelPromiseHasRejected, 'cancel() return value should be rejected only after the promise returned by the underlying source\'s cancel'); |
+ assert_equals(r, errorInCancel, 'cancel() return value should be rejected with the underlying source\'s rejection reason'); |
+ test8.done(); |
+ }) |
+ ); |
+ |
+ setTimeout(test8.step_func(function() { |
+ rejectSourceCancelPromise(errorInCancel); |
+ }), 500); |
+}); |
+ |
+var test9 = async_test('ReadableStream cancellation: cancelling before start finishes should prevent pull() from being called'); |
+test9.step(function() { |
+ var rs = new ReadableStream({ |
+ pull: function() { |
+ assert_unreached('pull should not have been called'); |
+ } |
+ }); |
+ |
+ Promise.all([rs.cancel(), rs.getReader().closed]).then(test9.step_func(function() { |
+ test9.done('pull should never have been called'); |
+ })).catch(test9.step_func(function(e) { assert_reached(e); } )); |
+}); |
+ |
+done(); |