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 |