OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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:math"; | 10 import "dart:math"; |
11 import "dart:utf"; | 11 import "dart:utf"; |
12 import "dart:json" as JSON; | 12 import "dart:json" as JSON; |
13 | 13 |
14 // Whether or not to print debug target process on the console. | |
15 var showDebuggeeOutput = true; | |
16 | |
17 // Whether or not to print the debugger wire messages on the console. | 14 // Whether or not to print the debugger wire messages on the console. |
18 var verboseWire = false; | 15 var verboseWire = false; |
19 | 16 |
20 // The number of attempts made to find an unused debugger port. | 17 // The number of attempts made to find an unused debugger port. |
21 var retries = 0; | 18 var retries = 0; |
22 | 19 |
23 // Class to buffer wire protocol data from debug target and | 20 // Class to buffer wire protocol data from debug target and |
24 // break it down to individual json messages. | 21 // break it down to individual json messages. |
25 class JsonBuffer { | 22 class JsonBuffer { |
26 String buffer = null; | 23 String buffer = null; |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
286 Command lastCommand = null; // Most recent command sent to target. | 283 Command lastCommand = null; // Most recent command sent to target. |
287 List<String> errors = new List(); | 284 List<String> errors = new List(); |
288 | 285 |
289 // Data collected from debug target. | 286 // Data collected from debug target. |
290 Map currentMessage = null; // Currently handled message sent by target. | 287 Map currentMessage = null; // Currently handled message sent by target. |
291 String scriptUrl = null; | 288 String scriptUrl = null; |
292 bool shutdownEventSeen = false; | 289 bool shutdownEventSeen = false; |
293 int isolateId = 0; | 290 int isolateId = 0; |
294 bool isPaused = false; | 291 bool isPaused = false; |
295 | 292 |
296 Debugger(this.targetProcess, this.portNumber) { | 293 Debugger(this.targetProcess, this.portNumber, this.script) { |
297 stdin.listen((_) {}); | 294 stdin.listen((_) {}); |
298 var stdoutStringStream = targetProcess.stdout | 295 var stdoutStringStream = targetProcess.stdout |
299 .transform(new StringDecoder()) | 296 .transform(new StringDecoder()) |
300 .transform(new LineTransformer()); | 297 .transform(new LineTransformer()); |
298 var started = false; | |
301 stdoutStringStream.listen((line) { | 299 stdoutStringStream.listen((line) { |
302 if (showDebuggeeOutput) { | 300 if (!started) { |
301 // Debuggee initialized message received. | |
302 started = true; | |
303 openConnection(); | |
304 } else { | |
303 print("TARG: $line"); | 305 print("TARG: $line"); |
304 } | 306 } |
kustermann
2013/04/05 08:20:08
I'd actually test if 'line == "Debugger initialize
Tom Ball
2013/04/05 21:28:52
Done.
| |
305 }); | 307 }); |
306 | 308 |
307 var stderrStringStream = targetProcess.stderr | 309 var stderrStringStream = targetProcess.stderr |
308 .transform(new StringDecoder()) | 310 .transform(new StringDecoder()) |
309 .transform(new LineTransformer()); | 311 .transform(new LineTransformer()); |
310 stderrStringStream.listen((line) { | 312 stderrStringStream.listen((line) { |
311 if (showDebuggeeOutput) { | 313 print("TARG: $line"); |
312 print("TARG: $line"); | |
313 } | |
314 }); | 314 }); |
315 } | 315 } |
316 | 316 |
317 // Handle debugger events, updating the debugger state. | 317 // Handle debugger events, updating the debugger state. |
318 void handleEvent(Map<String,dynamic> msg) { | 318 void handleEvent(Map<String,dynamic> msg) { |
319 if (msg["event"] == "isolate") { | 319 if (msg["event"] == "isolate") { |
320 if (msg["params"]["reason"] == "created") { | 320 if (msg["params"]["reason"] == "created") { |
321 isolateId = msg["params"]["id"]; | 321 isolateId = msg["params"]["id"]; |
322 assert(isolateId != null); | 322 assert(isolateId != null); |
323 print("Debuggee isolate id $isolateId created."); | 323 print("Debuggee isolate id $isolateId created."); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 onDone: () { | 438 onDone: () { |
439 print("Connection closed by debug target"); | 439 print("Connection closed by debug target"); |
440 close(killDebugee: true); | 440 close(killDebugee: true); |
441 }, | 441 }, |
442 onError: (e) { | 442 onError: (e) { |
443 print("Error '$e' detected in input stream from debug target"); | 443 print("Error '$e' detected in input stream from debug target"); |
444 close(killDebugee: true); | 444 close(killDebugee: true); |
445 }); | 445 }); |
446 }, | 446 }, |
447 onError: (asyncErr) { | 447 onError: (asyncErr) { |
448 print("Error while connecting to debugee: $asyncErr"); | 448 print("Error while connecting to debugee: $asyncErr"); |
kustermann
2013/04/05 08:20:08
Would be nice if you could change that from
prin
Tom Ball
2013/04/05 21:28:52
Done.
| |
449 close(killDebugee: true); | 449 close(killDebugee: true); |
450 }); | 450 }); |
451 } | 451 } |
452 | 452 |
453 void close({killDebugee: false}) { | 453 void close({killDebugee: false}) { |
454 if (errorsDetected) { | 454 if (errorsDetected) { |
455 for (int i = 0; i < errors.length; i++) print(errors[i]); | 455 for (int i = 0; i < errors.length; i++) print(errors[i]); |
456 } | 456 } |
457 if (socket != null) socket.close(); | 457 if (socket != null) socket.close(); |
458 if (killDebugee) { | 458 if (killDebugee) { |
459 targetProcess.kill(); | 459 targetProcess.kill(); |
460 print("Target process killed"); | 460 print("Target process killed"); |
461 } | 461 } |
462 Expect.isTrue(!errorsDetected); | 462 Expect.isTrue(!errorsDetected); |
463 exit(errors.length); | 463 exit(errors.length); |
464 } | 464 } |
465 } | 465 } |
466 | 466 |
467 | 467 |
468 bool RunScript(List script) { | 468 bool RunScript(List script) { |
469 var options = new Options(); | 469 var options = new Options(); |
470 if (options.arguments.contains("--debuggee")) { | 470 if (options.arguments.contains("--debuggee")) { |
471 return false; | 471 return false; |
472 } | 472 } |
473 // The default is to show debugging output. | |
474 showDebuggeeOutput = !options.arguments.contains("--non-verbose"); | |
475 verboseWire = options.arguments.contains("--wire"); | 473 verboseWire = options.arguments.contains("--wire"); |
476 | 474 |
477 // Pick a port in the upper half of the port number range. | 475 // Pick a port in the upper half of the port number range. |
478 var seed = new DateTime.now().millisecondsSinceEpoch; | 476 var seed = new DateTime.now().millisecondsSinceEpoch; |
479 Random random = new Random(seed); | 477 Random random = new Random(seed); |
480 var debugPort = random.nextInt(32000) + 32000; | 478 var debugPort = random.nextInt(32000) + 32000; |
481 print('using debug port $debugPort ...'); | 479 print('using debug port $debugPort ...'); |
482 ServerSocket.bind('127.0.0.1', debugPort).then((ServerSocket s) { | 480 ServerSocket.bind('127.0.0.1', debugPort).then((ServerSocket s) { |
483 s.close(); | 481 s.close(); |
484 var targetOpts = [ "--debug:$debugPort" ]; | 482 var targetOpts = [ "--debug:$debugPort" ]; |
485 if (showDebuggeeOutput) targetOpts.add("--verbose_debug"); | 483 // --verbose_debug is necessary so the test knows when the debuggee |
484 // is initialized. | |
485 targetOpts.add("--verbose_debug"); | |
486 targetOpts.add(options.script); | 486 targetOpts.add(options.script); |
487 targetOpts.add("--debuggee"); | 487 targetOpts.add("--debuggee"); |
488 | 488 |
489 Process.start(options.executable, targetOpts).then((Process process) { | 489 Process.start(options.executable, targetOpts).then((Process process) { |
490 print("Debug target process started"); | 490 print("Debug target process started"); |
491 process.stdin.close(); | 491 process.stdin.close(); |
492 process.exitCode.then((int exitCode) { | 492 process.exitCode.then((int exitCode) { |
493 Expect.equals(0, exitCode); | 493 Expect.equals(0, exitCode); |
494 print("Debug target process exited with exit code $exitCode"); | 494 print("Debug target process exited with exit code $exitCode"); |
495 }); | 495 }); |
496 var debugger = new Debugger(process, debugPort); | 496 var debugger = |
497 debugger.runScript(script); | 497 new Debugger(process, debugPort, new DebugScript(script)); |
498 }); | 498 }); |
499 }, | 499 }, |
500 onError: (e) { | 500 onError: (e) { |
501 if (++retries >= 3) { | 501 if (++retries >= 3) { |
502 print('unable to find unused port: $e'); | 502 print('unable to find unused port: $e'); |
503 return -1; | 503 return -1; |
504 } else { | 504 } else { |
505 // Retry with another random port. | 505 // Retry with another random port. |
506 RunScript(script); | 506 RunScript(script); |
507 } | 507 } |
508 }); | 508 }); |
509 return true; | 509 return true; |
510 } | 510 } |
OLD | NEW |