Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Unified Diff: tools/coverage.dart

Issue 1497033003: - Remove the legacy debug protocol. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« tests/standalone/coverage_test.dart ('K') | « tests/standalone/coverage_test.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/coverage.dart
diff --git a/tools/coverage.dart b/tools/coverage.dart
deleted file mode 100644
index b5cc61812d5e41e8578626f0cc08050e0c680166..0000000000000000000000000000000000000000
--- a/tools/coverage.dart
+++ /dev/null
@@ -1,545 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// This test forks a second vm process that runs a dart script as
-// a debug target, single stepping through the entire program, and
-// recording each breakpoint. At the end, a coverage map of the source
-// is printed.
-//
-// Usage: dart coverage.dart [--wire] [--verbose] target_script.dart
-//
-// --wire see json messages sent between the processes.
-// --verbose see the stdout and stderr output of the debug
-// target process.
-
-import "dart:convert";
-import "dart:io";
-
-
-// Whether or not to print debug target process on the console.
-var showDebuggeeOutput = false;
-
-// Whether or not to print the debugger wire messages on the console.
-var verboseWire = false;
-
-var debugger = null;
-
-class Program {
- static int numBps = 0;
-
- // Maps source code url to source.
- static var sources = new Map<String, Source>();
-
- // Takes a JSON Debugger response and increments the count for
- // the source position.
- static void recordBp(Map<String,dynamic> msg) {
- // Progress indicator.
- if (++numBps % 1000 == 0) print(numBps);
- var location = msg["params"]["location"];
- if (location == null) return;
- String url = location["url"];
- assert(url != null);
- int libId = location["libraryId"];
- assert(libId != null);
- int tokenPos = location["tokenOffset"];;
- Source s = sources[url];
- if (s == null) {
- debugger.getLineNumberTable(url, libId);
- s = new Source(url);
- sources[url] = s;
- }
- s.recordBp(tokenPos);
- }
-
- // Prints the annotated source code.
- static void printCoverage() {
- print("Coverage info collected from $numBps breakpoints:");
- for(Source s in sources.values) s.printCoverage();
- }
-}
-
-
-class Source {
- final String url;
-
- // Maps token position to breakpoint count.
- final tokenCounts = new Map<int,int>();
-
- // Maps token position to line number.
- final tokenPosToLine = new Map<int,int>();
-
- Source(this.url);
-
- void recordBp(int tokenPos) {
- var count = tokenCounts[tokenPos];
- tokenCounts[tokenPos] = count == null ? 1 : count + 1;
- }
-
- void SetLineInfo(List lineInfoTable) {
- // Each line is encoded as an array with first element being the line
- // number, followed by pairs of (tokenPosition, columnNumber).
- lineInfoTable.forEach((List<int> line) {
- int lineNumber = line[0];
- for (int t = 1; t < line.length; t += 2) {
- assert(tokenPosToLine[line[t]] == null);
- tokenPosToLine[line[t]] = lineNumber;
- }
- });
- }
-
- // Print out the annotated source code. For each line that has seen
- // a breakpoint, print out the maximum breakpoint count for all
- // tokens in the line.
- void printCoverage() {
- var lineCounts = new Map<int,int>(); // BP counts for each line.
- print(url);
- tokenCounts.forEach((tp, bpCount) {
- int lineNumber = tokenPosToLine[tp];
- var lineCount = lineCounts[lineNumber];
- // Remember maximum breakpoint count of all tokens in this line.
- if (lineCount == null || lineCount < bpCount) {
- lineCounts[lineNumber] = bpCount;
- }
- });
-
- String srcPath = Uri.parse(url).toFilePath();
- List lines = new File(srcPath).readAsLinesSync();
- for (int line = 1; line <= lines.length; line++) {
- String prefix = " ";
- if (lineCounts.containsKey(line)) {
- prefix = lineCounts[line].toString();
- StringBuffer b = new StringBuffer();
- for (int i = prefix.length; i < 6; i++) b.write(" ");
- b.write(prefix);
- prefix = b.toString();
- }
- print("${prefix}|${lines[line-1]}");
- }
- }
-}
-
-
-class StepCmd {
- Map msg;
- StepCmd(int isolateId) {
- msg = {"id": 0, "command": "stepInto", "params": {"isolateId": isolateId}};
- }
- void handleResponse(Map response) {}
-}
-
-
-class GetLineTableCmd {
- Map msg;
- GetLineTableCmd(int isolateId, int libraryId, String url) {
- msg = { "id": 0,
- "command": "getLineNumberTable",
- "params": { "isolateId" : isolateId,
- "libraryId": libraryId,
- "url": url } };
- }
-
- void handleResponse(Map response) {
- var url = msg["params"]["url"];
- Source s = Program.sources[url];
- assert(s != null);
- s.SetLineInfo(response["result"]["lines"]);
- }
-}
-
-
-class GetLibrariesCmd {
- Map msg;
- GetLibrariesCmd(int isolateId) {
- msg = { "id": 0,
- "command": "getLibraries",
- "params": { "isolateId" : isolateId } };
- }
-
- void handleResponse(Map response) {
- List libs = response["result"]["libraries"];
- for (var lib in libs) {
- String url = lib["url"];
- int libraryId = lib["id"];
- bool enable = !url.startsWith("dart:") && !url.startsWith("package:");
- if (enable) {
- print("Enable stepping for '$url'");
- debugger.enableDebugging(libraryId, true);
- }
- }
- }
-}
-
-
-class SetLibraryPropertiesCmd {
- Map msg;
- SetLibraryPropertiesCmd(int isolateId, int libraryId, bool enableDebugging) {
- // Note that in the debugger protocol, boolean values true and false
- // must be sent as string literals.
- msg = { "id": 0,
- "command": "setLibraryProperties",
- "params": { "isolateId" : isolateId,
- "libraryId": libraryId,
- "debuggingEnabled": "$enableDebugging" } };
- }
-
- void handleResponse(Map response) {
- // Nothing to do.
- }
-}
-
-
-class Debugger {
- // Debug target process properties.
- Process targetProcess;
- Socket socket;
- bool cleanupDone = false;
- JsonBuffer responses = new JsonBuffer();
- List<String> errors = new List();
-
- // Data collected from debug target.
- Map currentMessage = null; // Currently handled message sent by target.
- var outstandingCommand = null;
- var queuedCommands = new List();
- String scriptUrl = null;
- bool shutdownEventSeen = false;
- int isolateId = 0;
- int libraryId = null;
-
- int nextMessageId = 0;
- bool isPaused = false;
- bool pendingAck = false;
-
- Debugger(this.targetProcess) {
- var stdoutStringStream = targetProcess.stdout
- .transform(UTF8.decoder)
- .transform(new LineSplitter());
- stdoutStringStream.listen((line) {
- if (showDebuggeeOutput) {
- print("TARG: $line");
- }
- if (line.startsWith("Debugger listening")) {
- RegExp portExpr = new RegExp(r"\d+");
- var port = portExpr.stringMatch(line);
- var pid = targetProcess.pid;
- print("Coverage target process (pid $pid) found "
- "listening on port $port.");
- openConnection(int.parse(port));
- }
- });
-
- var stderrStringStream = targetProcess.stderr
- .transform(UTF8.decoder)
- .transform(new LineSplitter());
- stderrStringStream.listen((line) {
- if (showDebuggeeOutput) {
- print("TARG: $line");
- }
- });
- }
-
- // Handle debugger events, updating the debugger state.
- void handleEvent(Map<String,dynamic> msg) {
- if (msg["event"] == "isolate") {
- if (msg["params"]["reason"] == "created") {
- isolateId = msg["params"]["id"];
- assert(isolateId != null);
- print("Debuggee isolate id $isolateId created.");
- } else if (msg["params"]["reason"] == "shutdown") {
- print("Debuggee isolate id ${msg["params"]["id"]} shut down.");
- shutdownEventSeen = true;
- }
- } else if (msg["event"] == "breakpointResolved") {
- var bpId = msg["params"]["breakpointId"];
- assert(bpId != null);
- var isolateId = msg["params"]["isolateId"];
- assert(isolateId != null);
- var location = msg["params"]["location"];
- assert(location != null);
- print("Isolate $isolateId: breakpoint $bpId resolved"
- " at location $location");
- // We may want to maintain a table of breakpoints in the future.
- } else if (msg["event"] == "paused") {
- isPaused = true;
- if (libraryId == null) {
- libraryId = msg["params"]["location"]["libraryId"];
- assert(libraryId != null);
- // This is the first paused event we got. Get all libraries from
- // the debugger so we can turn on debugging events for them.
- getLibraries();
- }
- if (msg["params"]["reason"] == "breakpoint") {
- Program.recordBp(msg);
- }
- } else {
- error("Error: unknown debugger event received");
- }
- }
-
- // Handle one JSON message object.
- void handleMessage(Map<String,dynamic> receivedMsg) {
- currentMessage = receivedMsg;
- if (receivedMsg["event"] != null) {
- handleEvent(receivedMsg);
- if (errorsDetected) {
- error("Error while handling event message");
- error("Event received from coverage target: $receivedMsg");
- }
- } else if (receivedMsg["id"] != null) {
- // This is a response to the last command we sent.
- int id = receivedMsg["id"];
- assert(outstandingCommand != null);
- assert(outstandingCommand.msg["id"] == id);
- outstandingCommand.handleResponse(receivedMsg);
- outstandingCommand = null;
- } else {
- error("Unexpected message from target");
- }
- }
-
- // Handle data received over the wire from the coverage target
- // process. Split input from JSON wire format into individual
- // message objects (maps).
- void handleMessages() {
- var msg = responses.getNextMessage();
- while (msg != null) {
- if (verboseWire) print("RECV: $msg");
- if (responses.haveGarbage()) {
- error("Error: leftover text after message: '${responses.buffer}'");
- error("Previous message may be malformed, was: '$msg'");
- cleanup();
- return;
- }
- var msgObj = JSON.decode(msg);
- handleMessage(msgObj);
- if (errorsDetected) {
- error("Error while handling message from coverage target");
- error("Message received from coverage target: $msg");
- cleanup();
- return;
- }
- if (shutdownEventSeen) {
- if (outstandingCommand != null) {
- error("Error: outstanding command when shutdown received");
- }
- cleanup();
- return;
- }
- if (isPaused && (outstandingCommand == null)) {
- var cmd = queuedCommands.length > 0 ? queuedCommands.removeAt(0) : null;
- if (cmd == null) {
- cmd = new StepCmd(isolateId);
- isPaused = false;
- }
- sendMessage(cmd.msg);
- outstandingCommand = cmd;
- }
- msg = responses.getNextMessage();
- }
- }
-
- // Send a debugger command to the target VM.
- void sendMessage(Map<String,dynamic> msg) {
- assert(msg["id"] != null);
- msg["id"] = nextMessageId++;
- String jsonMsg = JSON.encode(msg);
- if (verboseWire) print("SEND: $jsonMsg");
- socket.write(jsonMsg);
- }
-
- void getLineNumberTable(String url, int libId) {
- queuedCommands.add(new GetLineTableCmd(isolateId, libId, url));
- }
-
- void getLibraries() {
- queuedCommands.add(new GetLibrariesCmd(isolateId));
- }
-
- void enableDebugging(libraryId, enable) {
- queuedCommands.add(new SetLibraryPropertiesCmd(isolateId, libraryId, enable));
- }
-
- bool get errorsDetected => errors.length > 0;
-
- // Record error message.
- void error(String s) {
- errors.add(s);
- }
-
- void openConnection(int portNumber) {
- Socket.connect("127.0.0.1", portNumber).then((s) {
- socket = s;
- socket.setOption(SocketOption.TCP_NODELAY, true);
- var stringStream = socket.transform(UTF8.decoder);
- stringStream.listen(
- (str) {
- try {
- responses.append(str);
- handleMessages();
- } catch(e, trace) {
- print("Unexpected exception:\n$e\n$trace");
- cleanup();
- }
- },
- onDone: () {
- print("Connection closed by coverage target");
- cleanup();
- },
- onError: (e) {
- print("Error '$e' detected in input stream from coverage target");
- cleanup();
- });
- },
- onError: (e, trace) {
- String msg = "Error while connecting to coverage target: $e";
- if (trace != null) msg += "\nStackTrace: $trace";
- error(msg);
- cleanup();
- });
- }
-
- void cleanup() {
- if (cleanupDone) return;
- if (socket != null) {
- socket.close().catchError((error) {
- // Print this directly in addition to adding it to the
- // error message queue, in case the error message queue
- // gets printed before this error handler is called.
- print("Error occurred while closing socket: $error");
- error("Error while closing socket: $error");
- });
- }
- var targetPid = targetProcess.pid;
- print("Sending kill signal to process $targetPid.");
- targetProcess.kill();
- // If the process was already dead exitCode is already
- // available and we call exit() in the next event loop cycle.
- // Otherwise this will wait for the process to exit.
-
- targetProcess.exitCode.then((exitCode) {
- print("Process $targetPid terminated with exit code $exitCode.");
- if (errorsDetected) {
- print("\n===== Errors detected: =====");
- for (int i = 0; i < errors.length; i++) print(errors[i]);
- print("============================\n");
- }
- Program.printCoverage();
- exit(errors.length);
- });
- cleanupDone = true;
- }
-}
-
-
-// Class to buffer wire protocol data from coverage target and
-// break it down to individual json messages.
-class JsonBuffer {
- String buffer = null;
-
- append(String s) {
- if (buffer == null || buffer.length == 0) {
- buffer = s;
- } else {
- buffer = buffer + s;
- }
- }
-
- String getNextMessage() {
- if (buffer == null) return null;
- int msgLen = objectLength();
- if (msgLen == 0) return null;
- String msg = null;
- if (msgLen == buffer.length) {
- msg = buffer;
- buffer = null;
- } else {
- assert(msgLen < buffer.length);
- msg = buffer.substring(0, msgLen);
- buffer = buffer.substring(msgLen);
- }
- return msg;
- }
-
- bool haveGarbage() {
- if (buffer == null || buffer.length == 0) return false;
- var i = 0, char = " ";
- while (i < buffer.length) {
- char = buffer[i];
- if (char != " " && char != "\n" && char != "\r" && char != "\t") break;
- i++;
- }
- if (i >= buffer.length) {
- return false;
- } else {
- return char != "{";
- }
- }
-
- // Returns the character length of the next json message in the
- // buffer, or 0 if there is only a partial message in the buffer.
- // The object value must start with '{' and continues to the
- // matching '}'. No attempt is made to otherwise validate the contents
- // as JSON. If it is invalid, a later JSON.decode() will fail.
- int objectLength() {
- int skipWhitespace(int index) {
- while (index < buffer.length) {
- String char = buffer[index];
- if (char != " " && char != "\n" && char != "\r" && char != "\t") break;
- index++;
- }
- return index;
- }
- int skipString(int index) {
- assert(buffer[index - 1] == '"');
- while (index < buffer.length) {
- String char = buffer[index];
- if (char == '"') return index + 1;
- if (char == r'\') index++;
- if (index == buffer.length) return index;
- index++;
- }
- return index;
- }
- int index = 0;
- index = skipWhitespace(index);
- // Bail out if the first non-whitespace character isn't '{'.
- if (index == buffer.length || buffer[index] != '{') return 0;
- int nesting = 0;
- while (index < buffer.length) {
- String char = buffer[index++];
- if (char == '{') {
- nesting++;
- } else if (char == '}') {
- nesting--;
- if (nesting == 0) return index;
- } else if (char == '"') {
- // Strings can contain braces. Skip their content.
- index = skipString(index);
- }
- }
- return 0;
- }
-}
-
-
-void main(List<String> arguments) {
- var targetOpts = [ "--debug:0" ];
- for (String str in arguments) {
- switch (str) {
- case "--verbose":
- showDebuggeeOutput = true;
- break;
- case "--wire":
- verboseWire = true;
- break;
- default:
- targetOpts.add(str);
- break;
- }
- }
-
- Process.start(Platform.executable, targetOpts).then((Process process) {
- process.stdin.close();
- debugger = new Debugger(process);
- });
-}
« tests/standalone/coverage_test.dart ('K') | « tests/standalone/coverage_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698