blob: 236f85bd2dbe9fac846ed483184f1a1dfa6fb690 [file] [log] [blame]
(async function(testRunner) {
var {page, session, dp} = await testRunner.startBlank(
`Tests that resource bodies can be taken as streams.`);
await session.protocol.Network.clearBrowserCache();
await session.protocol.Network.setCacheDisabled({cacheDisabled: true});
await session.protocol.Network.enable();
await session.protocol.Runtime.enable();
await dp.Network.setRequestInterception({patterns: [
{urlPattern: '*', interceptionStage: 'HeadersReceived'}
]});
const bodyPattern = 'The_quick_brown_fox_jumps_over_the_lazy_dog_0123456789';
function checkData(str, pattern) {
for (let i = 0; i < Math.ceil(str.length / pattern.length); ++i) {
const start = i * pattern.length;
const length = Math.min(pattern.length, str.length - start);
const expected = pattern.substr(0, length);
const fragment = str.substr(start, length);
if (expected != fragment) {
testRunner.log(`Data mistmatch near offset ${start}, got ${fragment}, expected: ${expected}`);
break;
}
}
}
let lastInterceptionId;
let lastStreamId;
async function startRequestAndTakeStream(size, params) {
cancelAndClose();
params = params || {};
params["size"] = size;
params["body_pattern"] = bodyPattern;
let paramStr = Object.keys(params).map(k => `${k}=${params[k]}`).join('&');
const url = `/devtools/network/resources/resource.php?${paramStr}`;
session.evaluate(`fetch("${url}");`);
const intercepted = (await dp.Network.onceRequestIntercepted()).params;
lastInterceptionId = intercepted.interceptionId;
let response = await dp.Network.takeResponseBodyForInterceptionAsStream({interceptionId: lastInterceptionId});
if (response.error) {
testRunner.log(`Error taking stream: ${response.error.message}`);
return;
}
lastStreamId = response.result.stream;
return lastStreamId;
}
function cancelAndClose() {
if (lastInterceptionId) {
dp.Network.continueInterceptedRequest({interceptionId: lastInterceptionId, errorReason: 'Aborted'});
lastInterceptionId = undefined;
}
if (lastStreamId) {
dp.IO.close({handle: lastStreamId});
lastStreamId = undefined;
}
}
testRunner.runTestSuite([
async function testBasicUsage() {
const stream = await startRequestAndTakeStream(100);
if (!stream)
return;
let result = (await dp.IO.read({handle: stream, size: 100})).result;
testRunner.log(`data: ${result.data} (${result.data.length}) eof: ${result.eof}`);
result = (await dp.IO.read({handle: stream, size: 100})).result;
testRunner.log(`eof: ${result.eof}`);
},
async function testLargeRead() {
const stream = await startRequestAndTakeStream(100000, {chunked: true});
if (!stream)
return;
let result = (await dp.IO.read({handle: stream, size: 100001})).result;
testRunner.log(`data: (${result.data.length}) eof: ${result.eof}`);
checkData(result.data, bodyPattern);
result = (await dp.IO.read({handle: stream, size: 100001})).result;
testRunner.log(`eof: ${result.eof}`);
},
async function testSmallNonOverlappingReads() {
const stream = await startRequestAndTakeStream(10000, {chunked: true});
if (!stream)
return;
let data = '';
for (;;) {
const response = (await dp.IO.read({handle: stream, size: 333})).result;
data += response.data;
if (response.eof)
break;
}
testRunner.log(`data: (${data.length})`);
checkData(data, bodyPattern);
},
async function testSmallOverlappingReads() {
const streamSize = 100000;
const readSize = 333;
const stream = await startRequestAndTakeStream(streamSize, {chunked: true});
if (!stream)
return;
let data = await new Promise(fulfill => {
let data = '';
let pendingReads = 0;
function onResponse(response) {
--pendingReads;
data += response.data;
if (response.eof) {
fulfill(data);
return;
}
for (;pendingReads < 4; ++pendingReads)
dp.IO.read({handle: stream, size: readSize}).then(r => onResponse(r.result));
}
for (;pendingReads < 4; ++pendingReads)
dp.IO.read({handle: stream, size: readSize}).then(r => onResponse(r.result));
});
testRunner.log(`data: (${data.length})`);
checkData(data, bodyPattern);
},
async function testRead0() {
const stream = await startRequestAndTakeStream(100);
if (!stream)
return;
const {error} = (await dp.IO.read({handle: stream, size: 0}));
testRunner.log(`reading 0: ${error.message}`);
const result = (await dp.IO.read({handle: stream, size: 100})).result;
testRunner.log(`data: ${result.data} (${result.data.length}) eof: ${result.eof}`);
},
async function testTakeTwice() {
const stream = await startRequestAndTakeStream(100);
if (!stream)
return;
let response = await dp.Network.takeResponseBodyForInterceptionAsStream({interceptionId: lastInterceptionId});
testRunner.log(`Trying to take stream twice: ${response.error.message}`);
},
async function testReadAfterCancel() {
const stream = await startRequestAndTakeStream(100);
if (!stream)
return;
dp.Network.continueInterceptedRequest({interceptionId: lastInterceptionId, errorReason: 'Aborted'});
lastInterceptionId = undefined;
let result = (await dp.IO.read({handle: stream, size: 100})).result;
testRunner.log(`data: ${result.data} (${result.data.length}) eof: ${result.eof}`);
result = (await dp.IO.read({handle: stream, size: 100})).result;
testRunner.log(`eof: ${result.eof}`);
},
async function testContinueAfterBodyTaken() {
const stream = await startRequestAndTakeStream(100);
if (!stream)
return;
const response = await dp.Network.continueInterceptedRequest({interceptionId: lastInterceptionId});
testRunner.log(`Attempting to continue as is after taking request: ${response.error.message}`);
},
async function testReadAfterClose() {
const stream = await startRequestAndTakeStream(100);
if (!stream)
return;
dp.IO.close({handle: stream});
const response = await dp.IO.read({handle: stream, size: 100});
testRunner.log(`Attempting read after close: ${response.error.message}`);
},
]);
})