| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Library used by debugger wire protocol tests (standalone VM debugging). | 5 // Library used by debugger wire protocol tests (standalone VM debugging). |
| 6 | 6 |
| 7 library DartDebugger; | 7 library DartDebugger; |
| 8 | 8 |
| 9 import "dart:io"; | 9 import "dart:io"; |
| 10 import "dart:utf"; | 10 import "dart:utf"; |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 currentIndex++; | 303 currentIndex++; |
| 304 } | 304 } |
| 305 } | 305 } |
| 306 | 306 |
| 307 | 307 |
| 308 class Debugger { | 308 class Debugger { |
| 309 // Debug target process properties. | 309 // Debug target process properties. |
| 310 Process targetProcess; | 310 Process targetProcess; |
| 311 int portNumber; | 311 int portNumber; |
| 312 Socket socket; | 312 Socket socket; |
| 313 OutputStream to; | |
| 314 StringInputStream from; | |
| 315 JsonBuffer responses = new JsonBuffer(); | 313 JsonBuffer responses = new JsonBuffer(); |
| 316 | 314 |
| 317 DebugScript script; | 315 DebugScript script; |
| 318 int seqNr = 0; // Sequence number of next debugger command message. | 316 int seqNr = 0; // Sequence number of next debugger command message. |
| 319 Command lastCommand = null; // Most recent command sent to target. | 317 Command lastCommand = null; // Most recent command sent to target. |
| 320 List<String> errors = new List(); | 318 List<String> errors = new List(); |
| 321 | 319 |
| 322 // Data collected from debug target. | 320 // Data collected from debug target. |
| 323 Map currentMessage = null; // Currently handled message sent by target. | 321 Map currentMessage = null; // Currently handled message sent by target. |
| 324 String scriptUrl = null; | 322 String scriptUrl = null; |
| 325 bool shutdownEventSeen = false; | 323 bool shutdownEventSeen = false; |
| 326 int isolateId = 0; | 324 int isolateId = 0; |
| 327 | 325 |
| 326 // stdin subscription to allow terminating the test via command-line. |
| 327 var stdinSubscription; |
| 328 |
| 328 Debugger(this.targetProcess, this.portNumber) { | 329 Debugger(this.targetProcess, this.portNumber) { |
| 329 var targetStdout = new StringInputStream(targetProcess.stdout); | 330 stdinSubscription = |
| 330 targetStdout.onLine = () { | 331 stdin.listen((d) {}, |
| 331 var s = targetStdout.readLine(); | 332 onError: (error) => close(killDebugee: true), |
| 333 onDone: () => close(killDebugee: true)); |
| 334 |
| 335 var stdoutStringStream = targetProcess.stdout |
| 336 .transform(new StringDecoder()) |
| 337 .transform(new LineTransformer()); |
| 338 stdoutStringStream.listen((line) { |
| 332 if (showDebuggeeOutput) { | 339 if (showDebuggeeOutput) { |
| 333 print("TARG: $s"); | 340 print("TARG: $line"); |
| 334 } | 341 } |
| 335 }; | 342 }); |
| 336 var targetStderr = new StringInputStream(targetProcess.stderr); | 343 |
| 337 targetStderr.onLine = () { | 344 var stderrStringStream = targetProcess.stderr |
| 338 var s = targetStderr.readLine(); | 345 .transform(new StringDecoder()) |
| 346 .transform(new LineTransformer()); |
| 347 stderrStringStream.listen((line) { |
| 339 if (showDebuggeeOutput) { | 348 if (showDebuggeeOutput) { |
| 340 print("TARG: $s"); | 349 print("TARG: $line"); |
| 341 } | 350 } |
| 342 }; | 351 }); |
| 343 } | 352 } |
| 344 | 353 |
| 345 // Handle debugger events for which there is no explicit | 354 // Handle debugger events for which there is no explicit |
| 346 // entry in the debug script, for example isolate create and | 355 // entry in the debug script, for example isolate create and |
| 347 // shutdown events, breakpoint resolution events, etc. | 356 // shutdown events, breakpoint resolution events, etc. |
| 348 bool handleImplicitEvents(Map<String,dynamic> msg) { | 357 bool handleImplicitEvents(Map<String,dynamic> msg) { |
| 349 if (msg["event"] == "isolate") { | 358 if (msg["event"] == "isolate") { |
| 350 if (msg["params"]["reason"] == "created") { | 359 if (msg["params"]["reason"] == "created") { |
| 351 isolateId = msg["params"]["id"]; | 360 isolateId = msg["params"]["id"]; |
| 352 assert(isolateId != null); | 361 assert(isolateId != null); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 | 453 |
| 445 runScript(List entries) { | 454 runScript(List entries) { |
| 446 script = new DebugScript(entries); | 455 script = new DebugScript(entries); |
| 447 openConnection(); | 456 openConnection(); |
| 448 } | 457 } |
| 449 | 458 |
| 450 // Send a debugger command to the target VM. | 459 // Send a debugger command to the target VM. |
| 451 void sendMessage(Map<String,dynamic> msg) { | 460 void sendMessage(Map<String,dynamic> msg) { |
| 452 String jsonMsg = JSON.stringify(msg); | 461 String jsonMsg = JSON.stringify(msg); |
| 453 if (verboseWire) print("SEND: $jsonMsg"); | 462 if (verboseWire) print("SEND: $jsonMsg"); |
| 454 to.writeString(jsonMsg, Encoding.UTF_8); | 463 socket.addString(jsonMsg); |
| 455 } | 464 } |
| 456 | 465 |
| 457 bool get errorsDetected => errors.length > 0; | 466 bool get errorsDetected => errors.length > 0; |
| 458 | 467 |
| 459 // Record error message. | 468 // Record error message. |
| 460 void error(String s) { | 469 void error(String s) { |
| 461 errors.add(s); | 470 errors.add(s); |
| 462 } | 471 } |
| 463 | 472 |
| 464 void openConnection() { | 473 void openConnection() { |
| 465 socket = new Socket("127.0.0.1", portNumber); | 474 Socket.connect("127.0.0.1", portNumber).then((s) { |
| 466 to = socket.outputStream; | 475 socket = s; |
| 467 from = new StringInputStream(socket.inputStream, Encoding.UTF_8); | 476 var stringStream = socket.transform(new StringDecoder()); |
| 468 from.onData = () { | 477 stringStream.listen( |
| 469 try { | 478 (str) { |
| 470 responses.append(from.read()); | 479 try { |
| 471 handleMessages(); | 480 responses.append(str); |
| 472 } catch(e, trace) { | 481 handleMessages(); |
| 473 print("Unexpected exception:\n$e\n$trace"); | 482 } catch(e, trace) { |
| 474 close(killDebugee: true); | 483 print("Unexpected exception:\n$e\n$trace"); |
| 475 } | 484 close(killDebugee: true); |
| 476 }; | 485 } |
| 477 from.onClosed = () { | 486 }, |
| 478 print("Connection closed by debug target"); | 487 onDone: () { |
| 479 close(killDebugee: true); | 488 print("Connection closed by debug target"); |
| 480 }; | 489 close(killDebugee: true); |
| 481 from.onError = (e) { | 490 }, |
| 482 print("Error '$e' detected in input stream from debug target"); | 491 onError: (e) { |
| 483 close(killDebugee: true); | 492 print("Error '$e' detected in input stream from debug target"); |
| 484 }; | 493 close(killDebugee: true); |
| 494 }); |
| 495 }); |
| 485 } | 496 } |
| 486 | 497 |
| 487 void close({killDebugee: false}) { | 498 void close({killDebugee: false}) { |
| 488 if (errorsDetected) { | 499 if (errorsDetected) { |
| 489 for (int i = 0; i < errors.length; i++) print(errors[i]); | 500 for (int i = 0; i < errors.length; i++) print(errors[i]); |
| 490 } | 501 } |
| 491 to.close(); | |
| 492 socket.close(); | 502 socket.close(); |
| 503 stdinSubscription.cancel(); |
| 493 if (killDebugee) { | 504 if (killDebugee) { |
| 494 targetProcess.kill(); | 505 targetProcess.kill(); |
| 495 print("Target process killed"); | 506 print("Target process killed"); |
| 496 } | 507 } |
| 497 Expect.isTrue(!errorsDetected); | 508 Expect.isTrue(!errorsDetected); |
| 498 stdin.close(); | 509 stdin.close(); |
| 499 stdout.close(); | 510 stdout.close(); |
| 500 stderr.close(); | 511 stderr.close(); |
| 501 } | 512 } |
| 502 } | 513 } |
| 503 | 514 |
| 504 | 515 |
| 505 bool RunScript(List script) { | 516 bool RunScript(List script) { |
| 506 var options = new Options(); | 517 var options = new Options(); |
| 507 if (options.arguments.contains("--debuggee")) { | 518 if (options.arguments.contains("--debuggee")) { |
| 508 return false; | 519 return false; |
| 509 } | 520 } |
| 510 showDebuggeeOutput = options.arguments.contains("--verbose"); | 521 showDebuggeeOutput = options.arguments.contains("--verbose"); |
| 511 verboseWire = options.arguments.contains("--wire"); | 522 verboseWire = options.arguments.contains("--wire"); |
| 512 | 523 |
| 513 var targetOpts = [ "--debug:$debugPort" ]; | 524 var targetOpts = [ "--debug:$debugPort" ]; |
| 514 if (showDebuggeeOutput) targetOpts.add("--verbose_debug"); | 525 if (showDebuggeeOutput) targetOpts.add("--verbose_debug"); |
| 515 targetOpts.add(options.script); | 526 targetOpts.add(options.script); |
| 516 targetOpts.add("--debuggee"); | 527 targetOpts.add("--debuggee"); |
| 517 | 528 |
| 518 Process.start(options.executable, targetOpts).then((Process process) { | 529 Process.start(options.executable, targetOpts).then((Process process) { |
| 519 print("Debug target process started"); | 530 print("Debug target process started"); |
| 520 process.stdin.close(); | 531 process.stdin.close(); |
| 521 process.stdout.onData = process.stdout.read; | 532 process.exitCode.then((int exitCode) { |
| 522 process.stderr.onData = process.stderr.read; | 533 Expect.equals(0, exitCode); |
| 523 process.onExit = (int exitCode) { | |
| 524 Expect.equals(0, exitCode); | 534 Expect.equals(0, exitCode); |
| 525 print("Debug target process exited with exit code $exitCode"); | 535 print("Debug target process exited with exit code $exitCode"); |
| 526 }; | 536 }); |
| 527 var debugger = new Debugger(process, debugPort); | 537 var debugger = new Debugger(process, debugPort); |
| 528 stdin.onClosed = () => debugger.close(killDebugee: true); | |
| 529 stdin.onError = (error) => debugger.close(killDebugee: true); | |
| 530 debugger.runScript(script); | 538 debugger.runScript(script); |
| 531 }); | 539 }); |
| 532 return true; | 540 return true; |
| 533 } | 541 } |
| OLD | NEW |