// 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);
  });
}
