blob: efc28c56de0dd55edaf923d883fc3894d8693f87 [file] [log] [blame]
<!DOCTYPE html>
<script src='../resources/testharness.js'></script>
<script src='../resources/testharnessreport.js'></script>
<script src='reference-implementation/resources/streams-utils.js'></script>
<script>
// This is updated till https://github.com/whatwg/streams/commit/4ba861e6f60c248060811830e11271c84b439cc3
// This test is alone here for timing reasons though it should be at streams/reference-implementation/pipe-to.html.
var test24 = async_test('Piping to a writable stream that does not consume the writes fast enough exerts backpressure on the source');
test24.step(function() {
const timeoutMultiplier = 15;
var desiredSizes = [];
var rs = new ReadableStream({
start: function(c) {
setTimeout(test24.step_func(function() { enqueue('a'); }), 100 * timeoutMultiplier);
setTimeout(test24.step_func(function() { enqueue('b'); }), 200 * timeoutMultiplier);
setTimeout(test24.step_func(function() { enqueue('c'); }), 300 * timeoutMultiplier);
setTimeout(test24.step_func(function() { enqueue('d'); }), 400 * timeoutMultiplier);
setTimeout(test24.step_func(function() { c.close(); }), 500 * timeoutMultiplier);
function enqueue(chunk) {
c.enqueue(chunk);
desiredSizes.push(c.desiredSize);
}
}
});
var chunksGivenToWrite = [];
var chunksFinishedWriting = [];
var startPromise = Promise.resolve();
var ws = new WritableStream({
start: function() {
return startPromise;
},
write: function(chunk) {
chunksGivenToWrite.push(chunk);
return new Promise(test24.step_func(function(resolve) {
setTimeout(test24.step_func(function() {
chunksFinishedWriting.push(chunk);
resolve();
}), 350 * timeoutMultiplier);
}));
}
});
startPromise.then(test24.step_func(function() {
rs.pipeTo(ws).then(test24.step_func(function() {
assert_array_equals(desiredSizes, [1, 1, 0, -1], 'backpressure was correctly exerted at the source');
assert_array_equals(chunksFinishedWriting, ['a', 'b', 'c', 'd'], 'all chunks were written');
test24.done();
}));
assert_equals(ws.state, 'writable', 'at t = 0 ms, ws should be writable');
setTimeout(test24.step_func(function() {
assert_equals(ws.state, 'waiting', 'at t = 125 ms, ws should be waiting');
assert_array_equals(chunksGivenToWrite, ['a'], 'at t = 125 ms, ws.write should have been called with one chunk');
assert_array_equals(chunksFinishedWriting, [], 'at t = 125 ms, no chunks should have finished writing');
// When 'a' (the very first chunk) was enqueued, it was immediately used to fulfill the outstanding read request
// promise, leaving room in the queue
assert_array_equals(desiredSizes, [1], 'at t = 125 ms, the one enqueued chunk in rs did not cause backpressure');
}), 125 * timeoutMultiplier);
setTimeout(test24.step_func(function() {
assert_equals(ws.state, 'waiting', 'at t = 225 ms, ws should be waiting');
assert_array_equals(chunksGivenToWrite, ['a'], 'at t = 225 ms, ws.write should have been called with one chunk');
assert_array_equals(chunksFinishedWriting, [], 'at t = 225 ms, no chunks should have finished writing');
// When 'b' was enqueued at 200 ms, the queue was also empty, since immediately after enqueuing 'a' at
// t = 100 ms, it was dequeued in order to fulfill the read() call that was made at time t = 0.
assert_array_equals(desiredSizes, [1, 1], 'at t = 225 ms, the two enqueued chunks in rs did not cause backpressure');
}), 225 * timeoutMultiplier);
setTimeout(test24.step_func(function() {
assert_equals(ws.state, 'waiting', 'at t = 325 ms, ws should be waiting');
assert_array_equals(chunksGivenToWrite, ['a'], 'at t = 325 ms, ws.write should have been called with one chunk');
assert_array_equals(chunksFinishedWriting, [], 'at t = 325 ms, no chunks should have finished writing');
// When 'c' was enqueued at 300 ms, the queue was again empty, since at time t = 200 ms when 'b' was enqueued,
// it was immediately dequeued in order to fulfill the second read() call that was made at time t = 0.
// However, this time there was no pending read request to whisk it away, so after the enqueue desired size is 0.
assert_array_equals(desiredSizes, [1, 1, 0], 'at t = 325 ms, the three enqueued chunks in rs did not cause backpressure');
}), 325 * timeoutMultiplier);
setTimeout(test24.step_func(function() {
assert_equals(ws.state, 'waiting', 'at t = 425 ms, ws should be waiting');
assert_array_equals(chunksGivenToWrite, ['a'], 'at t = 425 ms, ws.write should have been called with one chunk');
assert_array_equals(chunksFinishedWriting, [], 'at t = 425 ms, no chunks should have finished writing');
// When 'd' was enqueued at 400 ms, the queue was *not* empty. 'c' was still in it, since the write() of 'b' will
// not finish until t = 100 ms + 350 ms = 450 ms. Thus backpressure should have been exerted.
assert_array_equals(desiredSizes, [1, 1, 0, -1], 'at t = 425 ms, the fourth enqueued chunks in rs did cause backpressure');
}), 425 * timeoutMultiplier);
setTimeout(test24.step_func(function() {
assert_equals(ws.state, 'waiting', 'at t = 475 ms, ws should be waiting');
assert_array_equals(chunksGivenToWrite, ['a', 'b'], 'at t = 475 ms, ws.write should have been called with two chunks');
assert_array_equals(chunksFinishedWriting, ['a'], 'at t = 475 ms, one chunk should have finished writing');
}), 475 * timeoutMultiplier);
}));
});
</script>