| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 test.integration.analysis; | 5 library test.integration.analysis; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 import 'dart:convert'; | 9 import 'dart:convert'; |
| 10 import 'dart:io'; | 10 import 'dart:io'; |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 * up until the test finishes, so that they can be examined in the debugger | 464 * up until the test finishes, so that they can be examined in the debugger |
| 465 * or printed out in response to a call to [debugStdio]. | 465 * or printed out in response to a call to [debugStdio]. |
| 466 */ | 466 */ |
| 467 final List<String> _recordedStdio = <String>[]; | 467 final List<String> _recordedStdio = <String>[]; |
| 468 | 468 |
| 469 /** | 469 /** |
| 470 * True if we are currently printing out messages exchanged with the server. | 470 * True if we are currently printing out messages exchanged with the server. |
| 471 */ | 471 */ |
| 472 bool _debuggingStdio = false; | 472 bool _debuggingStdio = false; |
| 473 | 473 |
| 474 /** |
| 475 * True if we've received bad data from the server, and we are aborting the |
| 476 * test. |
| 477 */ |
| 478 bool _receivedBadDataFromServer = false; |
| 479 |
| 474 Server._(this._process); | 480 Server._(this._process); |
| 475 | 481 |
| 476 /** | 482 /** |
| 477 * Get a stream which will receive notifications of the given event type. | 483 * Get a stream which will receive notifications of the given event type. |
| 478 * The values delivered to the stream will be the contents of the 'params' | 484 * The values delivered to the stream will be the contents of the 'params' |
| 479 * field of the notification message. | 485 * field of the notification message. |
| 480 */ | 486 */ |
| 481 Stream onNotification(String event) { | 487 Stream onNotification(String event) { |
| 482 Stream notificationStream = _notificationStreams[event]; | 488 Stream notificationStream = _notificationStreams[event]; |
| 483 if (notificationStream == null) { | 489 if (notificationStream == null) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 arguments.add('--debug'); | 523 arguments.add('--debug'); |
| 518 } | 524 } |
| 519 arguments.add('--package-root=$packageRoot'); | 525 arguments.add('--package-root=$packageRoot'); |
| 520 arguments.add(serverPath); | 526 arguments.add(serverPath); |
| 521 return Process.start(dartBinary, arguments).then((Process process) { | 527 return Process.start(dartBinary, arguments).then((Process process) { |
| 522 Server server = new Server._(process); | 528 Server server = new Server._(process); |
| 523 process.stdout.transform((new Utf8Codec()).decoder).transform( | 529 process.stdout.transform((new Utf8Codec()).decoder).transform( |
| 524 new LineSplitter()).listen((String line) { | 530 new LineSplitter()).listen((String line) { |
| 525 String trimmedLine = line.trim(); | 531 String trimmedLine = line.trim(); |
| 526 server._recordStdio('RECV: $trimmedLine'); | 532 server._recordStdio('RECV: $trimmedLine'); |
| 527 var message = JSON.decoder.convert(trimmedLine); | 533 var message; |
| 534 try { |
| 535 message = JSON.decoder.convert(trimmedLine); |
| 536 } catch (exception) { |
| 537 server._badDataFromServer(); |
| 538 return; |
| 539 } |
| 528 expect(message, isMap); | 540 expect(message, isMap); |
| 529 Map messageAsMap = message; | 541 Map messageAsMap = message; |
| 530 if (messageAsMap.containsKey('id')) { | 542 if (messageAsMap.containsKey('id')) { |
| 531 expect(messageAsMap['id'], isString); | 543 expect(messageAsMap['id'], isString); |
| 532 String id = message['id']; | 544 String id = message['id']; |
| 533 Completer completer = server._pendingCommands[id]; | 545 Completer completer = server._pendingCommands[id]; |
| 534 if (completer == null) { | 546 if (completer == null) { |
| 535 fail('Unexpected response from server: id=$id'); | 547 fail('Unexpected response from server: id=$id'); |
| 536 } else { | 548 } else { |
| 537 server._pendingCommands.remove(id); | 549 server._pendingCommands.remove(id); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 557 server._notificationControllers[event]; | 569 server._notificationControllers[event]; |
| 558 if (notificationController != null) { | 570 if (notificationController != null) { |
| 559 notificationController.add(messageAsMap['params']); | 571 notificationController.add(messageAsMap['params']); |
| 560 } | 572 } |
| 561 // Check that the message is well-formed. We do this after calling | 573 // Check that the message is well-formed. We do this after calling |
| 562 // notificationController.add() so that we don't stall the test in the | 574 // notificationController.add() so that we don't stall the test in the |
| 563 // event of an error. | 575 // event of an error. |
| 564 expect(message, isNotification); | 576 expect(message, isNotification); |
| 565 } | 577 } |
| 566 }); | 578 }); |
| 567 process.stderr.listen((List<int> data) { | 579 process.stderr.transform((new Utf8Codec()).decoder).transform( |
| 568 fail('Unexpected output from stderr'); | 580 new LineSplitter()).listen((String line) { |
| 581 String trimmedLine = line.trim(); |
| 582 server._recordStdio('ERR: $trimmedLine'); |
| 583 server._badDataFromServer(); |
| 569 }); | 584 }); |
| 570 return server; | 585 return server; |
| 571 }); | 586 }); |
| 572 } | 587 } |
| 573 | 588 |
| 574 /** | 589 /** |
| 575 * Stop the server. | 590 * Stop the server. |
| 576 */ | 591 */ |
| 577 Future kill() { | 592 Future kill() { |
| 578 _process.kill(); | 593 _process.kill(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 if (_debuggingStdio) { | 627 if (_debuggingStdio) { |
| 613 return; | 628 return; |
| 614 } | 629 } |
| 615 _debuggingStdio = true; | 630 _debuggingStdio = true; |
| 616 for (String line in _recordedStdio) { | 631 for (String line in _recordedStdio) { |
| 617 print(line); | 632 print(line); |
| 618 } | 633 } |
| 619 } | 634 } |
| 620 | 635 |
| 621 /** | 636 /** |
| 637 * Deal with bad data received from the server. |
| 638 */ |
| 639 void _badDataFromServer() { |
| 640 if (_receivedBadDataFromServer) { |
| 641 // We're already dealing with it. |
| 642 return; |
| 643 } |
| 644 _receivedBadDataFromServer = true; |
| 645 debugStdio(); |
| 646 // Give the server 1 second to continue outputting bad data before we kill |
| 647 // the test. This is helpful if the server has had an unhandled exception |
| 648 // and is outputting a stacktrace, because it ensures that we see the |
| 649 // entire stacktrace. Use expectAsync() to prevent the test from |
| 650 // ending during this 1 second. |
| 651 new Future.delayed(new Duration(seconds: 1), expectAsync(() { |
| 652 fail('Bad data received from server'); |
| 653 })); |
| 654 } |
| 655 |
| 656 /** |
| 622 * Record a message that was exchanged with the server, and print it out if | 657 * Record a message that was exchanged with the server, and print it out if |
| 623 * [debugStdio] has been called. | 658 * [debugStdio] has been called. |
| 624 */ | 659 */ |
| 625 void _recordStdio(String line) { | 660 void _recordStdio(String line) { |
| 626 if (_debuggingStdio) { | 661 if (_debuggingStdio) { |
| 627 print(line); | 662 print(line); |
| 628 } | 663 } |
| 629 _recordedStdio.add(line); | 664 _recordedStdio.add(line); |
| 630 } | 665 } |
| 631 } | 666 } |
| OLD | NEW |