node/test/sequential/test-inspector-network-resource.js
Shima Ryuhei 04c5a18e4c
test: make test-inspector-network-resource sequential
PR-URL: https://github.com/nodejs/node/pull/59104
Refs: https://github.com/nodejs/node/issues/59090
Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com>
Reviewed-By: Kohei Ueno <kohei.ueno119@gmail.com>
2025-07-28 13:29:23 +00:00

181 lines
7.3 KiB
JavaScript

// Flags: --inspect=0 --experimental-network-inspection
'use strict';
const common = require('../common');
common.skipIfInspectorDisabled();
const { NodeInstance } = require('../common/inspector-helper');
const test = require('node:test');
const assert = require('node:assert');
const path = require('path');
const fs = require('fs');
const resourceUrl = 'http://localhost:3000/app.js';
const resourcePath = path.join(__dirname, '../fixtures/inspector-network-resource/app.js.map');
const resourceText = fs.readFileSync(resourcePath, 'utf8');
const embedPath = resourcePath.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
const script = `
const { NetworkResources } = require('node:inspector');
const fs = require('fs');
NetworkResources.put('${resourceUrl}', fs.readFileSync('${embedPath}', 'utf8'));
console.log('Network resource loaded:', '${resourceUrl}');
debugger;
`;
async function setupSessionAndPauseAtEvalLastLine(script) {
const instance = new NodeInstance([
'--inspect-wait=0',
'--experimental-inspector-network-resource',
], script);
const session = await instance.connectInspectorSession();
await session.send({ method: 'NodeRuntime.enable' });
await session.waitForNotification('NodeRuntime.waitingForDebugger');
await session.send({ method: 'Runtime.enable' });
await session.send({ method: 'Debugger.enable' });
await session.send({ method: 'Runtime.runIfWaitingForDebugger' });
await session.waitForNotification('Debugger.paused');
return { instance, session };
}
test('should load and stream a static network resource using loadNetworkResource and IO.read', async () => {
const { session } = await setupSessionAndPauseAtEvalLastLine(script);
const { resource } = await session.send({
method: 'Network.loadNetworkResource',
params: { url: resourceUrl },
});
assert(resource.success, 'Resource should be loaded successfully');
assert(resource.stream, 'Resource should have a stream handle');
let result = await session.send({ method: 'IO.read', params: { handle: resource.stream } });
let data = result.data;
let eof = result.eof;
let content = '';
while (!eof) {
content += data;
result = await session.send({ method: 'IO.read', params: { handle: resource.stream } });
data = result.data;
eof = result.eof;
}
content += data;
assert.strictEqual(content, resourceText);
await session.send({ method: 'IO.close', params: { handle: resource.stream } });
await session.send({ method: 'Debugger.resume' });
await session.waitForDisconnect();
});
test('should return success: false for missing resource', async () => {
const { session } = await setupSessionAndPauseAtEvalLastLine(script);
const { resource } = await session.send({
method: 'Network.loadNetworkResource',
params: { url: 'http://localhost:3000/does-not-exist.js' },
});
assert.strictEqual(resource.success, false);
assert(!resource.stream, 'No stream should be returned for missing resource');
await session.send({ method: 'Debugger.resume' });
await session.waitForDisconnect();
});
test('should error or return empty for wrong stream id', async () => {
const { session } = await setupSessionAndPauseAtEvalLastLine(script);
const { resource } = await session.send({
method: 'Network.loadNetworkResource',
params: { url: resourceUrl },
});
assert(resource.success);
const bogus = '999999';
const result = await session.send({ method: 'IO.read', params: { handle: bogus } });
assert(result.eof, 'Should be eof for bogus stream id');
assert.strictEqual(result.data, '');
await session.send({ method: 'IO.close', params: { handle: resource.stream } });
await session.send({ method: 'Debugger.resume' });
await session.waitForDisconnect();
});
test('should support IO.read with size and offset', async () => {
const { session } = await setupSessionAndPauseAtEvalLastLine(script);
const { resource } = await session.send({
method: 'Network.loadNetworkResource',
params: { url: resourceUrl },
});
assert(resource.success);
assert(resource.stream);
let result = await session.send({ method: 'IO.read', params: { handle: resource.stream, size: 5 } });
assert.strictEqual(result.data, resourceText.slice(0, 5));
result = await session.send({ method: 'IO.read', params: { handle: resource.stream, offset: 5, size: 5 } });
assert.strictEqual(result.data, resourceText.slice(5, 10));
result = await session.send({ method: 'IO.read', params: { handle: resource.stream, offset: 10 } });
assert.strictEqual(result.data, resourceText.slice(10));
await session.send({ method: 'IO.close', params: { handle: resource.stream } });
await session.send({ method: 'Debugger.resume' });
await session.waitForDisconnect();
});
test('should load resource put from another thread', async () => {
const workerScript = `
console.log('this is worker thread');
debugger;
`;
const script = `
const { NetworkResources } = require('node:inspector');
const fs = require('fs');
NetworkResources.put('${resourceUrl}', fs.readFileSync('${embedPath}', 'utf8'));
const { Worker } = require('worker_threads');
const worker = new Worker(\`${workerScript}\`, {eval: true});
`;
const instance = new NodeInstance([
'--experimental-inspector-network-resource',
'--experimental-worker-inspection',
'--inspect-brk=0',
], script);
const session = await instance.connectInspectorSession();
await setupInspector(session);
await session.waitForNotification('Debugger.paused');
await session.send({ method: 'Debugger.resume' });
await session.waitForNotification('Target.targetCreated');
await session.send({ method: 'Target.setAutoAttach', params: { autoAttach: true, waitForDebuggerOnStart: true } });
let sessionId;
await session.waitForNotification((notification) => {
if (notification.method === 'Target.attachedToTarget') {
sessionId = notification.params.sessionId;
return true;
}
return false;
});
await setupInspector(session, sessionId);
await session.waitForNotification('Debugger.paused');
const { resource } = await session.send({
method: 'Network.loadNetworkResource',
params: { url: resourceUrl, sessionId },
});
assert(resource.success, 'Resource should be loaded successfully');
assert(resource.stream, 'Resource should have a stream handle');
let result = await session.send({ method: 'IO.read', params: { handle: resource.stream, sessionId } });
let data = result.data;
let eof = result.eof;
let content = '';
while (!eof) {
content += data;
result = await session.send({ method: 'IO.read', params: { handle: resource.stream, sessionId } });
data = result.data;
eof = result.eof;
}
content += data;
assert.strictEqual(content, resourceText);
await session.send({ method: 'IO.close', params: { handle: resource.stream, sessionId } });
await session.send({ method: 'Debugger.resume', sessionId });
await session.waitForDisconnect();
async function setupInspector(session, sessionId) {
await session.send({ method: 'NodeRuntime.enable', sessionId });
await session.waitForNotification('NodeRuntime.waitingForDebugger');
await session.send({ method: 'Runtime.enable', sessionId });
await session.send({ method: 'Debugger.enable', sessionId });
await session.send({ method: 'Runtime.runIfWaitingForDebugger', sessionId });
}
});