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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 * received from the server with 'analyzing' set to false. | 81 * received from the server with 'analyzing' set to false. |
82 * | 82 * |
83 * The future will only be completed by 'server.status' notifications that are | 83 * The future will only be completed by 'server.status' notifications that are |
84 * received after this function call. So it is safe to use this getter | 84 * received after this function call. So it is safe to use this getter |
85 * multiple times in one test; each time it is used it will wait afresh for | 85 * multiple times in one test; each time it is used it will wait afresh for |
86 * analysis to finish. | 86 * analysis to finish. |
87 */ | 87 */ |
88 Future get analysisFinished { | 88 Future get analysisFinished { |
89 Completer completer = new Completer(); | 89 Completer completer = new Completer(); |
90 StreamSubscription subscription; | 90 StreamSubscription subscription; |
91 subscription = server.onNotification(SERVER_STATUS).listen((params) { | 91 subscription = server.onNotification(SERVER_STATUS).listen(wrapAsync( |
| 92 (params) { |
92 bool analysisComplete = false; | 93 bool analysisComplete = false; |
93 try { | 94 try { |
94 analysisComplete = !params['analysis']['analyzing']; | 95 analysisComplete = !params['analysis']['analyzing']; |
95 } catch (_) { | 96 } catch (_) { |
96 // Status message was mal-formed or missing optional parameters. That's | 97 // Status message was mal-formed or missing optional parameters. That's |
97 // fine, since we'll detect a mal-formed status message below. | 98 // fine, since we'll detect a mal-formed status message below. |
98 } | 99 } |
99 if (analysisComplete) { | 100 if (analysisComplete) { |
100 completer.complete(params); | 101 completer.complete(params); |
101 subscription.cancel(); | 102 subscription.cancel(); |
102 } | 103 } |
103 expect(params, isServerStatusParams); | 104 expect(params, isServerStatusParams); |
104 }); | 105 })); |
105 return completer.future; | 106 return completer.future; |
106 } | 107 } |
107 | 108 |
108 /** | 109 /** |
109 * Print out any messages exchanged with the server. If some messages have | 110 * Print out any messages exchanged with the server. If some messages have |
110 * already been exchanged with the server, they are printed out immediately. | 111 * already been exchanged with the server, they are printed out immediately. |
111 */ | 112 */ |
112 void debugStdio() { | 113 void debugStdio() { |
113 server.debugStdio(); | 114 server.debugStdio(); |
114 } | 115 } |
115 | 116 |
116 /** | 117 /** |
117 * The server is automatically started before every test, and a temporary | 118 * The server is automatically started before every test, and a temporary |
118 * [sourceDirectory] is created. | 119 * [sourceDirectory] is created. |
119 */ | 120 */ |
120 Future setUp() { | 121 Future setUp() { |
121 sourceDirectory = Directory.systemTemp.createTempSync('analysisServer'); | 122 sourceDirectory = Directory.systemTemp.createTempSync('analysisServer'); |
122 return Server.start().then((Server server) { | 123 return Server.start().then((Server server) { |
123 this.server = server; | 124 this.server = server; |
124 server.onNotification(ANALYSIS_ERRORS).listen((params) { | 125 server.onNotification(ANALYSIS_ERRORS).listen(wrapAsync((params) { |
125 expect(params, isMap); | 126 expect(params, isMap); |
126 expect(params['file'], isString); | 127 expect(params['file'], isString); |
127 currentAnalysisErrors[params['file']] = params['errors']; | 128 currentAnalysisErrors[params['file']] = params['errors']; |
128 }); | 129 })); |
129 }); | 130 }); |
130 } | 131 } |
131 | 132 |
132 /** | 133 /** |
133 * After every test, the server stopped and [sourceDirectory] is deleted. | 134 * After every test, the server stopped and [sourceDirectory] is deleted. |
134 */ | 135 */ |
135 Future tearDown() { | 136 Future tearDown() { |
136 return server.kill().then((_) { | 137 return server.kill().then((_) { |
137 sourceDirectory.deleteSync(recursive: true); | 138 sourceDirectory.deleteSync(recursive: true); |
138 }); | 139 }); |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 String serverPath = normalize(join(dirname(Platform.script.path), '..', | 504 String serverPath = normalize(join(dirname(Platform.script.path), '..', |
504 '..', 'bin', 'server.dart')); | 505 '..', 'bin', 'server.dart')); |
505 List<String> arguments = []; | 506 List<String> arguments = []; |
506 if (debugServer) { | 507 if (debugServer) { |
507 arguments.add('--debug'); | 508 arguments.add('--debug'); |
508 } | 509 } |
509 arguments.add(serverPath); | 510 arguments.add(serverPath); |
510 return Process.start(dartBinary, arguments).then((Process process) { | 511 return Process.start(dartBinary, arguments).then((Process process) { |
511 Server server = new Server._(process); | 512 Server server = new Server._(process); |
512 process.stdout.transform((new Utf8Codec()).decoder).transform( | 513 process.stdout.transform((new Utf8Codec()).decoder).transform( |
513 new LineSplitter()).listen((String line) { | 514 new LineSplitter()).listen(wrapAsync((String line) { |
514 String trimmedLine = line.trim(); | 515 String trimmedLine = line.trim(); |
515 server._recordStdio('RECV: $trimmedLine'); | 516 server._recordStdio('RECV: $trimmedLine'); |
516 var message = JSON.decoder.convert(trimmedLine); | 517 var message = JSON.decoder.convert(trimmedLine); |
517 expect(message, isMap); | 518 expect(message, isMap); |
518 Map messageAsMap = message; | 519 Map messageAsMap = message; |
519 if (messageAsMap.containsKey('id')) { | 520 if (messageAsMap.containsKey('id')) { |
520 expect(messageAsMap['id'], isString); | 521 expect(messageAsMap['id'], isString); |
521 String id = message['id']; | 522 String id = message['id']; |
522 Completer completer = server._pendingCommands[id]; | 523 Completer completer = server._pendingCommands[id]; |
523 if (completer == null) { | 524 if (completer == null) { |
(...skipping 25 matching lines...) Expand all Loading... |
549 StreamController notificationController = | 550 StreamController notificationController = |
550 server._notificationControllers[event]; | 551 server._notificationControllers[event]; |
551 if (notificationController != null) { | 552 if (notificationController != null) { |
552 notificationController.add(messageAsMap['params']); | 553 notificationController.add(messageAsMap['params']); |
553 } | 554 } |
554 // Check that the message is well-formed. We do this after calling | 555 // Check that the message is well-formed. We do this after calling |
555 // notificationController.add() so that we don't stall the test in the | 556 // notificationController.add() so that we don't stall the test in the |
556 // event of an error. | 557 // event of an error. |
557 expect(message, isNotification); | 558 expect(message, isNotification); |
558 } | 559 } |
559 }); | 560 })); |
560 process.stderr.listen((List<int> data) { | 561 process.stderr.listen(wrapAsync((List<int> data) { |
561 fail('Unexpected output from stderr'); | 562 fail('Unexpected output from stderr'); |
562 }); | 563 })); |
563 return server; | 564 return server; |
564 }); | 565 }); |
565 } | 566 } |
566 | 567 |
567 /** | 568 /** |
568 * Stop the server. | 569 * Stop the server. |
569 */ | 570 */ |
570 Future kill() { | 571 Future kill() { |
571 _process.kill(); | 572 _process.kill(); |
572 return _process.exitCode; | 573 return _process.exitCode; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 * Record a message that was exchanged with the server, and print it out if | 616 * Record a message that was exchanged with the server, and print it out if |
616 * [debugStdio] has been called. | 617 * [debugStdio] has been called. |
617 */ | 618 */ |
618 void _recordStdio(String line) { | 619 void _recordStdio(String line) { |
619 if (_debuggingStdio) { | 620 if (_debuggingStdio) { |
620 print(line); | 621 print(line); |
621 } | 622 } |
622 _recordedStdio.add(line); | 623 _recordedStdio.add(line); |
623 } | 624 } |
624 } | 625 } |
| 626 |
| 627 /** |
| 628 * Wrap a callback function that will be called an unknown number of times. |
| 629 * This won't prevent the integration test from completing, but it will ensure |
| 630 * that any exceptions thrown from the callback are properly reported as unit |
| 631 * test failures. |
| 632 */ |
| 633 Function wrapAsync(Function callback) => expectAsync(callback, count: 0, max: -1 |
| 634 ); |
OLD | NEW |