inspector: introduce a smoke test
This test executes a simple debug session over the inspector protocol. PR-URL: https://github.com/nodejs/node/pull/8429 Reviewed-By: ofrobots - Ali Ijaz Sheikh <ofrobots@google.com>
This commit is contained in:
parent
c5545f2c63
commit
b4a249f66b
7
Makefile
7
Makefile
@ -119,7 +119,7 @@ test: all
|
||||
$(MAKE) build-addons
|
||||
$(MAKE) cctest
|
||||
$(PYTHON) tools/test.py --mode=release -J \
|
||||
addons doctool known_issues message pseudo-tty parallel sequential
|
||||
addons doctool inspector known_issues message pseudo-tty parallel sequential
|
||||
$(MAKE) lint
|
||||
|
||||
test-parallel: all
|
||||
@ -193,7 +193,7 @@ test-all-valgrind: test-build
|
||||
$(PYTHON) tools/test.py --mode=debug,release --valgrind
|
||||
|
||||
CI_NATIVE_SUITES := addons
|
||||
CI_JS_SUITES := doctool known_issues message parallel pseudo-tty sequential
|
||||
CI_JS_SUITES := doctool inspector known_issues message parallel pseudo-tty sequential
|
||||
|
||||
# Build and test addons without building anything else
|
||||
test-ci-native: | test/addons/.buildstamp
|
||||
@ -233,6 +233,9 @@ test-internet: all
|
||||
test-debugger: all
|
||||
$(PYTHON) tools/test.py debugger
|
||||
|
||||
test-inspector: all
|
||||
$(PYTHON) tools/test.py inspector
|
||||
|
||||
test-known-issues: all
|
||||
$(PYTHON) tools/test.py known_issues
|
||||
|
||||
|
@ -48,6 +48,7 @@ void PrintDebuggerReadyMessage(int port) {
|
||||
"@%s/inspector.html?"
|
||||
"experiments=true&v8only=true&ws=localhost:%d/node\n",
|
||||
port, DEVTOOLS_HASH, port);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
bool AcceptsConnection(inspector_socket_t* socket, const std::string& path) {
|
||||
@ -525,6 +526,7 @@ bool AgentImpl::IsStarted() {
|
||||
void AgentImpl::WaitForDisconnect() {
|
||||
shutting_down_ = true;
|
||||
fprintf(stderr, "Waiting for the debugger to disconnect...\n");
|
||||
fflush(stderr);
|
||||
inspector_->runMessageLoopOnPause(0);
|
||||
}
|
||||
|
||||
@ -620,6 +622,7 @@ bool AgentImpl::OnInspectorHandshakeIO(inspector_socket_t* socket,
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ static void dump_hex(const char* buf, size_t len) {
|
||||
while (ptr < end) {
|
||||
cptr = ptr;
|
||||
for (i = 0; i < 16 && ptr < end; i++) {
|
||||
printf("%2.2X ", *(ptr++));
|
||||
printf("%2.2X ", static_cast<unsigned char>(*(ptr++)));
|
||||
}
|
||||
for (i = 72 - (i * 4); i > 0; i--) {
|
||||
printf(" ");
|
||||
|
@ -54,6 +54,15 @@ Tests for garbage collection related functionality.
|
||||
|:----------:|
|
||||
| No |
|
||||
|
||||
|
||||
### inspector
|
||||
|
||||
Tests for the V8 inspector integration.
|
||||
|
||||
| Runs on CI |
|
||||
|:----------:|
|
||||
| Yes |
|
||||
|
||||
### internet
|
||||
|
||||
Tests that make real outbound connections (mainly networking related modules).
|
||||
|
10
test/fixtures/loop.js
vendored
Normal file
10
test/fixtures/loop.js
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
var t = 1;
|
||||
var k = 1;
|
||||
console.log('A message', 5);
|
||||
while (t > 0) {
|
||||
if (t++ === 1000) {
|
||||
t = 0;
|
||||
console.log('Outputed message #' + k++);
|
||||
}
|
||||
}
|
||||
process.exit(55);
|
424
test/inspector/inspector-helper.js
Normal file
424
test/inspector/inspector-helper.js
Normal file
@ -0,0 +1,424 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
const path = require('path');
|
||||
const spawn = require('child_process').spawn;
|
||||
|
||||
const TIMEOUT = 15 * 1000;
|
||||
|
||||
const mainScript = path.join(common.fixturesDir, 'loop.js');
|
||||
|
||||
function send(socket, message, id, callback) {
|
||||
const msg = JSON.parse(JSON.stringify(message)); // Clone!
|
||||
msg['id'] = id;
|
||||
const messageBuf = Buffer.from(JSON.stringify(msg));
|
||||
|
||||
const wsHeaderBuf = Buffer.allocUnsafe(16);
|
||||
wsHeaderBuf.writeUInt8(0x81, 0);
|
||||
let byte2 = 0x80;
|
||||
const bodyLen = messageBuf.length;
|
||||
let maskOffset = 2;
|
||||
if (bodyLen < 126) {
|
||||
byte2 = 0x80 + bodyLen;
|
||||
} else if (bodyLen < 65536) {
|
||||
byte2 = 0xFE;
|
||||
wsHeaderBuf.writeUInt16BE(bodyLen, 2);
|
||||
maskOffset = 4;
|
||||
} else {
|
||||
byte2 = 0xFF;
|
||||
wsHeaderBuf.writeUInt32BE(bodyLen, 2);
|
||||
wsHeaderBuf.writeUInt32BE(0, 6);
|
||||
maskOffset = 10;
|
||||
}
|
||||
wsHeaderBuf.writeUInt8(byte2, 1);
|
||||
wsHeaderBuf.writeUInt32BE(0x01020408, maskOffset);
|
||||
|
||||
for (let i = 0; i < messageBuf.length; i++)
|
||||
messageBuf[i] = messageBuf[i] ^ (1 << (i % 4));
|
||||
socket.write(
|
||||
Buffer.concat([wsHeaderBuf.slice(0, maskOffset + 4), messageBuf]),
|
||||
callback);
|
||||
}
|
||||
|
||||
function parseWSFrame(buffer, handler) {
|
||||
if (buffer.length < 2)
|
||||
return 0;
|
||||
assert.strictEqual(0x81, buffer[0]);
|
||||
let dataLen = 0x7F & buffer[1];
|
||||
let bodyOffset = 2;
|
||||
if (buffer.length < bodyOffset + dataLen)
|
||||
return 0;
|
||||
if (dataLen === 126) {
|
||||
dataLen = buffer.readUInt16BE(2);
|
||||
bodyOffset = 4;
|
||||
} else if (dataLen === 127) {
|
||||
dataLen = buffer.readUInt32BE(2);
|
||||
bodyOffset = 10;
|
||||
}
|
||||
if (buffer.length < bodyOffset + dataLen)
|
||||
return 0;
|
||||
const message = JSON.parse(
|
||||
buffer.slice(bodyOffset, bodyOffset + dataLen).toString('utf8'));
|
||||
handler(message);
|
||||
return bodyOffset + dataLen;
|
||||
}
|
||||
|
||||
function tearDown(child, err) {
|
||||
child.kill();
|
||||
if (err instanceof Error) {
|
||||
console.error(err.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function checkHttpResponse(port, path, callback) {
|
||||
http.get({port, path}, function(res) {
|
||||
let response = '';
|
||||
res.setEncoding('utf8');
|
||||
res.
|
||||
on('data', (data) => response += data.toString()).
|
||||
on('end', () => callback(JSON.parse(response)));
|
||||
});
|
||||
}
|
||||
|
||||
function makeBufferingDataCallback(dataCallback) {
|
||||
let buffer = new Buffer(0);
|
||||
return (data) => {
|
||||
const newData = Buffer.concat([buffer, data]);
|
||||
const str = newData.toString('utf8');
|
||||
const lines = str.split('\n');
|
||||
if (str.endsWith('\n'))
|
||||
buffer = new Buffer(0);
|
||||
else
|
||||
buffer = Buffer.from(lines.pop(), 'utf8');
|
||||
for (var line of lines)
|
||||
dataCallback(line);
|
||||
};
|
||||
}
|
||||
|
||||
function timeout(message, multiplicator) {
|
||||
return setTimeout(() => common.fail(message), TIMEOUT * (multiplicator || 1));
|
||||
}
|
||||
|
||||
const TestSession = function(socket, harness) {
|
||||
this.mainScriptPath = harness.mainScriptPath;
|
||||
this.mainScriptId = null;
|
||||
|
||||
this.harness_ = harness;
|
||||
this.socket_ = socket;
|
||||
this.expectClose_ = false;
|
||||
this.scripts_ = {};
|
||||
this.messagefilter_ = null;
|
||||
this.responseCheckers_ = {};
|
||||
this.lastId_ = 0;
|
||||
this.messages_ = {};
|
||||
this.expectedId_ = 1;
|
||||
this.lastMessageResponseCallback_ = null;
|
||||
|
||||
let buffer = Buffer.from('');
|
||||
socket.on('data', (data) => {
|
||||
buffer = Buffer.concat([buffer, data]);
|
||||
let consumed;
|
||||
do {
|
||||
consumed = parseWSFrame(buffer, this.processMessage_.bind(this));
|
||||
if (consumed)
|
||||
buffer = buffer.slice(consumed);
|
||||
} while (consumed);
|
||||
}).on('close', () => assert(this.expectClose_, 'Socket closed prematurely'));
|
||||
};
|
||||
|
||||
TestSession.prototype.scriptUrlForId = function(id) {
|
||||
return this.scripts_[id];
|
||||
};
|
||||
|
||||
TestSession.prototype.processMessage_ = function(message) {
|
||||
const method = message['method'];
|
||||
if (method === 'Debugger.scriptParsed') {
|
||||
const script = message['params'];
|
||||
const scriptId = script['scriptId'];
|
||||
const url = script['url'];
|
||||
this.scripts_[scriptId] = url;
|
||||
if (url === mainScript)
|
||||
this.mainScriptId = scriptId;
|
||||
}
|
||||
this.messagefilter_ && this.messagefilter_(message);
|
||||
const id = message['id'];
|
||||
if (id) {
|
||||
assert.strictEqual(id, this.expectedId_);
|
||||
this.expectedId_++;
|
||||
if (this.responseCheckers_[id]) {
|
||||
assert(message['result'], JSON.stringify(message) + ' (response to ' +
|
||||
JSON.stringify(this.messages_[id]) + ')');
|
||||
this.responseCheckers_[id](message['result']);
|
||||
delete this.responseCheckers_[id];
|
||||
}
|
||||
assert(!message['error'], JSON.stringify(message) + ' (replying to ' +
|
||||
JSON.stringify(this.messages_[id]) + ')');
|
||||
delete this.messages_[id];
|
||||
if (id === this.lastId_) {
|
||||
this.lastMessageResponseCallback_ && this.lastMessageResponseCallback_();
|
||||
this.lastMessageResponseCallback_ = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TestSession.prototype.sendAll_ = function(commands, callback) {
|
||||
if (!commands.length) {
|
||||
callback();
|
||||
} else {
|
||||
this.lastId_++;
|
||||
let command = commands[0];
|
||||
if (command instanceof Array) {
|
||||
this.responseCheckers_[this.lastId_] = command[1];
|
||||
command = command[0];
|
||||
}
|
||||
if (command instanceof Function)
|
||||
command = command();
|
||||
this.messages_[this.lastId_] = command;
|
||||
send(this.socket_, command, this.lastId_,
|
||||
() => this.sendAll_(commands.slice(1), callback));
|
||||
}
|
||||
};
|
||||
|
||||
TestSession.prototype.sendInspectorCommands = function(commands) {
|
||||
if (!(commands instanceof Array))
|
||||
commands = [commands];
|
||||
return this.enqueue((callback) => {
|
||||
let timeoutId = null;
|
||||
this.lastMessageResponseCallback_ = () => {
|
||||
timeoutId && clearTimeout(timeoutId);
|
||||
callback();
|
||||
};
|
||||
this.sendAll_(commands, () => {
|
||||
timeoutId = setTimeout(() => {
|
||||
let s = '';
|
||||
for (const id in this.messages_) {
|
||||
s += this.messages_[id] + '\n';
|
||||
}
|
||||
common.fail(s.substring(0, s.length - 1));
|
||||
}, TIMEOUT);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
TestSession.prototype.createCallbackWithTimeout_ = function(message) {
|
||||
var promise = new Promise((resolve) => {
|
||||
this.enqueue((callback) => {
|
||||
const timeoutId = timeout(message);
|
||||
resolve(() => {
|
||||
clearTimeout(timeoutId);
|
||||
callback();
|
||||
});
|
||||
});
|
||||
});
|
||||
return () => promise.then((callback) => callback());
|
||||
};
|
||||
|
||||
TestSession.prototype.expectMessages = function(expects) {
|
||||
if (!(expects instanceof Array)) expects = [ expects ];
|
||||
|
||||
const callback = this.createCallbackWithTimeout_(
|
||||
'Matching response was not received:\n' + expects[0]);
|
||||
this.messagefilter_ = (message) => {
|
||||
if (expects[0](message))
|
||||
expects.shift();
|
||||
if (!expects.length) {
|
||||
this.messagefilter_ = null;
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
TestSession.prototype.expectStderrOutput = function(regexp) {
|
||||
this.harness_.addStderrFilter(
|
||||
regexp,
|
||||
this.createCallbackWithTimeout_('Timed out waiting for ' + regexp));
|
||||
return this;
|
||||
};
|
||||
|
||||
TestSession.prototype.runNext_ = function() {
|
||||
if (this.task_) {
|
||||
setTimeout(() => {
|
||||
this.task_(() => {
|
||||
this.task_ = this.task_.next_;
|
||||
this.runNext_();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
TestSession.prototype.enqueue = function(task) {
|
||||
if (!this.task_) {
|
||||
this.task_ = task;
|
||||
this.runNext_();
|
||||
} else {
|
||||
let t = this.task_;
|
||||
while (t.next_)
|
||||
t = t.next_;
|
||||
t.next_ = task;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
TestSession.prototype.disconnect = function(childDone) {
|
||||
return this.enqueue((callback) => {
|
||||
this.expectClose_ = true;
|
||||
this.harness_.childInstanceDone =
|
||||
this.harness_.childInstanceDone || childDone;
|
||||
this.socket_.end();
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
const Harness = function(port, childProcess) {
|
||||
this.port = port;
|
||||
this.mainScriptPath = mainScript;
|
||||
this.stderrFilters_ = [];
|
||||
this.process_ = childProcess;
|
||||
this.childInstanceDone = false;
|
||||
this.returnCode_ = null;
|
||||
this.running_ = true;
|
||||
|
||||
childProcess.stdout.on('data', makeBufferingDataCallback(
|
||||
(line) => console.log('[out]', line)));
|
||||
|
||||
|
||||
childProcess.stderr.on('data', makeBufferingDataCallback((message) => {
|
||||
const pending = [];
|
||||
console.log('[err]', message);
|
||||
for (const filter of this.stderrFilters_)
|
||||
if (!filter(message)) pending.push(filter);
|
||||
this.stderrFilters_ = pending;
|
||||
}));
|
||||
childProcess.on('close', (code, signal) => {
|
||||
assert(this.childInstanceDone, 'Child instance died prematurely');
|
||||
this.returnCode_ = code;
|
||||
this.running_ = false;
|
||||
});
|
||||
};
|
||||
|
||||
Harness.prototype.addStderrFilter = function(regexp, callback) {
|
||||
this.stderrFilters_.push((message) => {
|
||||
if (message.match(regexp)) {
|
||||
callback();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Harness.prototype.run_ = function() {
|
||||
setTimeout(() => {
|
||||
this.task_(() => {
|
||||
this.task_ = this.task_.next_;
|
||||
if (this.task_)
|
||||
this.run_();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Harness.prototype.enqueue_ = function(task) {
|
||||
if (!this.task_) {
|
||||
this.task_ = task;
|
||||
this.run_();
|
||||
} else {
|
||||
let chain = this.task_;
|
||||
while (chain.next_)
|
||||
chain = chain.next_;
|
||||
chain.next_ = task;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Harness.prototype.testHttpResponse = function(path, check) {
|
||||
return this.enqueue_((doneCallback) => {
|
||||
checkHttpResponse(this.port, path, (response) => {
|
||||
check.call(this, response);
|
||||
doneCallback();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Harness.prototype.runFrontendSession = function(tests) {
|
||||
return this.enqueue_((callback) => {
|
||||
http.get({
|
||||
port: this.port,
|
||||
path: '/node',
|
||||
headers: {
|
||||
'Connection': 'Upgrade',
|
||||
'Upgrade': 'websocket',
|
||||
'Sec-WebSocket-Version': 13,
|
||||
'Sec-WebSocket-Key': 'key=='
|
||||
}
|
||||
}).on('upgrade', (message, socket) => {
|
||||
const session = new TestSession(socket, this);
|
||||
if (!(tests instanceof Array))
|
||||
tests = [tests];
|
||||
function enqueue(tests) {
|
||||
session.enqueue((sessionCb) => {
|
||||
if (tests.length) {
|
||||
tests[0](session);
|
||||
session.enqueue((cb2) => {
|
||||
enqueue(tests.slice(1));
|
||||
cb2();
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
sessionCb();
|
||||
});
|
||||
}
|
||||
enqueue(tests);
|
||||
}).on('response', () => common.fail('Upgrade was not received'));
|
||||
});
|
||||
};
|
||||
|
||||
Harness.prototype.expectShutDown = function(errorCode) {
|
||||
this.enqueue_((callback) => {
|
||||
if (this.running_) {
|
||||
const timeoutId = timeout('Have not terminated');
|
||||
this.process_.on('exit', (code) => {
|
||||
clearTimeout(timeoutId);
|
||||
assert.strictEqual(errorCode, code);
|
||||
callback();
|
||||
});
|
||||
} else {
|
||||
assert.strictEqual(errorCode, this.returnCode_);
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.startNodeForInspectorTest = function(callback) {
|
||||
const child = spawn(process.execPath,
|
||||
[ '--inspect', '--debug-brk', mainScript ]);
|
||||
|
||||
const timeoutId = timeout('Child process did not start properly', 4);
|
||||
|
||||
let found = false;
|
||||
|
||||
const dataCallback = makeBufferingDataCallback((text) => {
|
||||
clearTimeout(timeoutId);
|
||||
console.log('[err]', text);
|
||||
if (found) return;
|
||||
const match = text.match(/Debugger listening on port (\d+)/);
|
||||
found = true;
|
||||
child.stderr.removeListener('data', dataCallback);
|
||||
assert.ok(match, text);
|
||||
callback(new Harness(match[1], child));
|
||||
});
|
||||
|
||||
child.stderr.on('data', dataCallback);
|
||||
|
||||
const handler = tearDown.bind(null, child);
|
||||
|
||||
process.on('exit', handler);
|
||||
process.on('uncaughtException', handler);
|
||||
process.on('SIGINT', handler);
|
||||
};
|
||||
|
||||
exports.mainScriptSource = function() {
|
||||
return fs.readFileSync(mainScript, 'utf8');
|
||||
};
|
167
test/inspector/test-inspector.js
Normal file
167
test/inspector/test-inspector.js
Normal file
@ -0,0 +1,167 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const helper = require('./inspector-helper.js');
|
||||
|
||||
let scopeId;
|
||||
|
||||
function checkListResponse(response) {
|
||||
assert.strictEqual(1, response.length);
|
||||
assert.ok(response[0]['devtoolsFrontendUrl']);
|
||||
assert.strictEqual('ws://localhost:' + this.port + '/node',
|
||||
response[0]['webSocketDebuggerUrl']);
|
||||
}
|
||||
|
||||
function expectMainScriptSource(result) {
|
||||
const expected = helper.mainScriptSource();
|
||||
const source = result['scriptSource'];
|
||||
assert(source && (source.indexOf(expected) >= 0),
|
||||
'Script source is wrong: ' + source);
|
||||
}
|
||||
|
||||
function setupExpectBreakOnLine(line, url, session, scopeIdCallback) {
|
||||
return function(message) {
|
||||
if ('Debugger.paused' === message['method']) {
|
||||
const callFrame = message['params']['callFrames'][0];
|
||||
const location = callFrame['location'];
|
||||
assert.strictEqual(url, session.scriptUrlForId(location['scriptId']));
|
||||
assert.strictEqual(line, location['lineNumber']);
|
||||
scopeIdCallback &&
|
||||
scopeIdCallback(callFrame['scopeChain'][0]['object']['objectId']);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function setupExpectConsoleOutput(type, values) {
|
||||
if (!(values instanceof Array))
|
||||
values = [ values ];
|
||||
return function(message) {
|
||||
if ('Runtime.consoleAPICalled' === message['method']) {
|
||||
const params = message['params'];
|
||||
if (params['type'] === type) {
|
||||
let i = 0;
|
||||
for (const value of params['args']) {
|
||||
if (value['value'] !== values[i++])
|
||||
return false;
|
||||
}
|
||||
return i === values.length;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function setupExpectScopeValues(expected) {
|
||||
return function(result) {
|
||||
for (const actual of result['result']) {
|
||||
const value = expected[actual['name']];
|
||||
if (value)
|
||||
assert.strictEqual(value, actual['value']['value']);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function setupExpectValue(value) {
|
||||
return function(result) {
|
||||
assert.strictEqual(value, result['result']['value']);
|
||||
};
|
||||
}
|
||||
|
||||
function testBreakpointOnStart(session) {
|
||||
console.log('[test]',
|
||||
'Verifying debugger stops on start (--debug-brk option)');
|
||||
const commands = [
|
||||
{ 'method': 'Runtime.enable' },
|
||||
{ 'method': 'Debugger.enable' },
|
||||
{ 'method': 'Debugger.setPauseOnExceptions',
|
||||
'params': {'state': 'none'} },
|
||||
{ 'method': 'Debugger.setAsyncCallStackDepth',
|
||||
'params': {'maxDepth': 0} },
|
||||
{ 'method': 'Profiler.enable' },
|
||||
{ 'method': 'Profiler.setSamplingInterval',
|
||||
'params': {'interval': 100} },
|
||||
{ 'method': 'Debugger.setBlackboxPatterns',
|
||||
'params': {'patterns': []} },
|
||||
{ 'method': 'Runtime.runIfWaitingForDebugger' }
|
||||
];
|
||||
|
||||
session.
|
||||
sendInspectorCommands(commands).
|
||||
expectMessages(setupExpectBreakOnLine(0, session.mainScriptPath, session));
|
||||
}
|
||||
|
||||
function testSetBreakpointAndResume(session) {
|
||||
console.log('[test]', 'Setting a breakpoint and verifying it is hit');
|
||||
const commands = [
|
||||
{ 'method': 'Debugger.setBreakpointByUrl',
|
||||
'params': { 'lineNumber': 5,
|
||||
'url': session.mainScriptPath,
|
||||
'columnNumber': 0,
|
||||
'condition': ''
|
||||
}
|
||||
},
|
||||
{ 'method': 'Debugger.resume'},
|
||||
[ { 'method': 'Debugger.getScriptSource',
|
||||
'params': { 'scriptId': session.mainScriptId } },
|
||||
expectMainScriptSource ],
|
||||
];
|
||||
session.
|
||||
sendInspectorCommands(commands).
|
||||
expectMessages([
|
||||
setupExpectConsoleOutput('log', ['A message', 5]),
|
||||
setupExpectBreakOnLine(5, session.mainScriptPath,
|
||||
session, (id) => scopeId = id),
|
||||
]);
|
||||
}
|
||||
|
||||
function testInspectScope(session) {
|
||||
console.log('[test]', 'Verify we can read current application state');
|
||||
session.sendInspectorCommands([
|
||||
[
|
||||
{
|
||||
'method': 'Runtime.getProperties',
|
||||
'params': {
|
||||
'objectId': scopeId,
|
||||
'ownProperties': false,
|
||||
'accessorPropertiesOnly': false,
|
||||
'generatePreview': true
|
||||
}
|
||||
}, setupExpectScopeValues({t: 1001, k: 1})
|
||||
],
|
||||
[
|
||||
{
|
||||
'method': 'Debugger.evaluateOnCallFrame', 'params': {
|
||||
'callFrameId': '{\"ordinal\":0,\"injectedScriptId\":1}',
|
||||
'expression': 'k + t',
|
||||
'objectGroup': 'console',
|
||||
'includeCommandLineAPI': true,
|
||||
'silent': false,
|
||||
'returnByValue': false,
|
||||
'generatePreview': true
|
||||
}
|
||||
}, setupExpectValue(1002)
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
function testWaitsForFrontendDisconnect(session, harness) {
|
||||
console.log('[test]', 'Verify node waits for the frontend to disconnect');
|
||||
session.sendInspectorCommands({ 'method': 'Debugger.resume'}).
|
||||
expectStderrOutput('Waiting for the debugger to disconnect...').
|
||||
disconnect(true);
|
||||
}
|
||||
|
||||
function runTests(harness) {
|
||||
harness
|
||||
.testHttpResponse('/json', checkListResponse)
|
||||
.testHttpResponse('/json/list', checkListResponse)
|
||||
.testHttpResponse('/json/version', assert.ok)
|
||||
.runFrontendSession([
|
||||
testBreakpointOnStart,
|
||||
testSetBreakpointAndResume,
|
||||
testInspectScope,
|
||||
testWaitsForFrontendDisconnect
|
||||
]).expectShutDown(55);
|
||||
}
|
||||
|
||||
helper.startNodeForInspectorTest(runTests);
|
6
test/inspector/testcfg.py
Normal file
6
test/inspector/testcfg.py
Normal file
@ -0,0 +1,6 @@
|
||||
import sys, os
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
import testpy
|
||||
|
||||
def GetConfiguration(context, root):
|
||||
return testpy.SimpleTestConfiguration(context, root, 'inspector')
|
@ -1465,6 +1465,7 @@ BUILT_IN_TESTS = [
|
||||
'gc',
|
||||
'debugger',
|
||||
'doctool',
|
||||
'inspector',
|
||||
]
|
||||
|
||||
|
||||
|
@ -57,14 +57,15 @@ if /i "%1"=="noetw" set noetw=1&goto arg-ok
|
||||
if /i "%1"=="noperfctr" set noperfctr=1&goto arg-ok
|
||||
if /i "%1"=="licensertf" set licensertf=1&goto arg-ok
|
||||
if /i "%1"=="test" set test_args=%test_args% addons doctool known_issues message parallel sequential -J&set jslint=1&set build_addons=1&goto arg-ok
|
||||
if /i "%1"=="test-ci" set test_args=%test_args% %test_ci_args% -p tap --logfile test.tap addons doctool known_issues message sequential parallel&set build_addons=1&goto arg-ok
|
||||
if /i "%1"=="test-ci" set test_args=%test_args% %test_ci_args% -p tap --logfile test.tap addons doctool inspector known_issues message sequential parallel&set build_addons=1&goto arg-ok
|
||||
if /i "%1"=="test-addons" set test_args=%test_args% addons&set build_addons=1&goto arg-ok
|
||||
if /i "%1"=="test-simple" set test_args=%test_args% sequential parallel -J&goto arg-ok
|
||||
if /i "%1"=="test-message" set test_args=%test_args% message&goto arg-ok
|
||||
if /i "%1"=="test-gc" set test_args=%test_args% gc&set buildnodeweak=1&goto arg-ok
|
||||
if /i "%1"=="test-inspector" set test_args=%test_args% inspector&goto arg-ok
|
||||
if /i "%1"=="test-internet" set test_args=%test_args% internet&goto arg-ok
|
||||
if /i "%1"=="test-pummel" set test_args=%test_args% pummel&goto arg-ok
|
||||
if /i "%1"=="test-all" set test_args=%test_args% sequential parallel message gc internet pummel&set buildnodeweak=1&set jslint=1&goto arg-ok
|
||||
if /i "%1"=="test-all" set test_args=%test_args% sequential parallel message gc inspector internet pummel&set buildnodeweak=1&set jslint=1&goto arg-ok
|
||||
if /i "%1"=="test-known-issues" set test_args=%test_args% known_issues&goto arg-ok
|
||||
if /i "%1"=="jslint" set jslint=1&goto arg-ok
|
||||
if /i "%1"=="jslint-ci" set jslint_ci=1&goto arg-ok
|
||||
@ -387,7 +388,7 @@ echo Failed to create vc project files.
|
||||
goto exit
|
||||
|
||||
:help
|
||||
echo vcbuild.bat [debug/release] [msi] [test-all/test-uv/test-internet/test-pummel/test-simple/test-message] [clean] [noprojgen] [small-icu/full-icu/without-intl] [nobuild] [nosign] [x86/x64] [vc2013/vc2015] [download-all] [enable-vtune]
|
||||
echo vcbuild.bat [debug/release] [msi] [test-all/test-uv/test-inspector/test-internet/test-pummel/test-simple/test-message] [clean] [noprojgen] [small-icu/full-icu/without-intl] [nobuild] [nosign] [x86/x64] [vc2013/vc2015] [download-all] [enable-vtune]
|
||||
echo Examples:
|
||||
echo vcbuild.bat : builds release build
|
||||
echo vcbuild.bat debug : builds debug build
|
||||
|
Loading…
x
Reference in New Issue
Block a user