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 22 matching lines...) Expand all Loading... |
33 optionalFields: {'result': anything, 'error': isRequestError}); | 33 optionalFields: {'result': anything, 'error': isRequestError}); |
34 | 34 |
35 Matcher isListOf(Matcher elementMatcher) => new _ListOf(elementMatcher); | 35 Matcher isListOf(Matcher elementMatcher) => new _ListOf(elementMatcher); |
36 | 36 |
37 Matcher isMapOf(Matcher keyMatcher, Matcher valueMatcher) => | 37 Matcher isMapOf(Matcher keyMatcher, Matcher valueMatcher) => |
38 new _MapOf(keyMatcher, valueMatcher); | 38 new _MapOf(keyMatcher, valueMatcher); |
39 | 39 |
40 Matcher isOneOf(List<Matcher> choiceMatchers) => new _OneOf(choiceMatchers); | 40 Matcher isOneOf(List<Matcher> choiceMatchers) => new _OneOf(choiceMatchers); |
41 | 41 |
42 /** | 42 /** |
| 43 * Assert that [actual] matches [matcher]. |
| 44 */ |
| 45 void outOfTestExpect(actual, matcher, |
| 46 {String reason, skip, bool verbose: false}) { |
| 47 var matchState = {}; |
| 48 try { |
| 49 if (matcher.matches(actual, matchState)) return; |
| 50 } catch (e, trace) { |
| 51 if (reason == null) { |
| 52 reason = '${(e is String) ? e : e.toString()} at $trace'; |
| 53 } |
| 54 } |
| 55 fail(_defaultFailFormatter(actual, matcher, reason, matchState, verbose)); |
| 56 } |
| 57 |
| 58 String _defaultFailFormatter( |
| 59 actual, Matcher matcher, String reason, Map matchState, bool verbose) { |
| 60 var description = new StringDescription(); |
| 61 description.add('Expected: ').addDescriptionOf(matcher).add('\n'); |
| 62 description.add(' Actual: ').addDescriptionOf(actual).add('\n'); |
| 63 |
| 64 var mismatchDescription = new StringDescription(); |
| 65 matcher.describeMismatch(actual, mismatchDescription, matchState, verbose); |
| 66 |
| 67 if (mismatchDescription.length > 0) { |
| 68 description.add(' Which: $mismatchDescription\n'); |
| 69 } |
| 70 if (reason != null) description.add(reason).add('\n'); |
| 71 return description.toString(); |
| 72 } |
| 73 |
| 74 /** |
43 * Type of closures used by LazyMatcher. | 75 * Type of closures used by LazyMatcher. |
44 */ | 76 */ |
45 typedef Matcher MatcherCreator(); | 77 typedef Matcher MatcherCreator(); |
46 | 78 |
47 /** | 79 /** |
48 * Type of closures used by MatchesJsonObject to record field mismatches. | 80 * Type of closures used by MatchesJsonObject to record field mismatches. |
49 */ | 81 */ |
50 typedef Description MismatchDescriber(Description mismatchDescription); | 82 typedef Description MismatchDescriber(Description mismatchDescription); |
51 | 83 |
52 /** | 84 /** |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 * The future will only be completed by 'server.status' notifications that are | 136 * The future will only be completed by 'server.status' notifications that are |
105 * received after this function call. So it is safe to use this getter | 137 * received after this function call. So it is safe to use this getter |
106 * multiple times in one test; each time it is used it will wait afresh for | 138 * multiple times in one test; each time it is used it will wait afresh for |
107 * analysis to finish. | 139 * analysis to finish. |
108 */ | 140 */ |
109 Future get analysisFinished { | 141 Future get analysisFinished { |
110 Completer completer = new Completer(); | 142 Completer completer = new Completer(); |
111 StreamSubscription subscription; | 143 StreamSubscription subscription; |
112 // This will only work if the caller has already subscribed to | 144 // This will only work if the caller has already subscribed to |
113 // SERVER_STATUS (e.g. using sendServerSetSubscriptions(['STATUS'])) | 145 // SERVER_STATUS (e.g. using sendServerSetSubscriptions(['STATUS'])) |
114 expect(_subscribedToServerStatus, isTrue); | 146 outOfTestExpect(_subscribedToServerStatus, isTrue); |
115 subscription = onServerStatus.listen((ServerStatusParams params) { | 147 subscription = onServerStatus.listen((ServerStatusParams params) { |
116 if (params.analysis != null && !params.analysis.isAnalyzing) { | 148 if (params.analysis != null && !params.analysis.isAnalyzing) { |
117 completer.complete(params); | 149 completer.complete(params); |
118 subscription.cancel(); | 150 subscription.cancel(); |
119 } | 151 } |
120 }); | 152 }); |
121 return completer.future; | 153 return completer.future; |
122 } | 154 } |
123 | 155 |
124 /** | 156 /** |
(...skipping 15 matching lines...) Expand all Loading... |
140 * [sourceDirectory] is created. | 172 * [sourceDirectory] is created. |
141 */ | 173 */ |
142 Future setUp() { | 174 Future setUp() { |
143 sourceDirectory = Directory.systemTemp.createTempSync('analysisServer'); | 175 sourceDirectory = Directory.systemTemp.createTempSync('analysisServer'); |
144 | 176 |
145 onAnalysisErrors.listen((AnalysisErrorsParams params) { | 177 onAnalysisErrors.listen((AnalysisErrorsParams params) { |
146 currentAnalysisErrors[params.file] = params.errors; | 178 currentAnalysisErrors[params.file] = params.errors; |
147 }); | 179 }); |
148 Completer serverConnected = new Completer(); | 180 Completer serverConnected = new Completer(); |
149 onServerConnected.listen((_) { | 181 onServerConnected.listen((_) { |
150 expect(serverConnected.isCompleted, isFalse); | 182 outOfTestExpect(serverConnected.isCompleted, isFalse); |
151 serverConnected.complete(); | 183 serverConnected.complete(); |
152 }); | 184 }); |
153 onServerError.listen((ServerErrorParams params) { | 185 onServerError.listen((ServerErrorParams params) { |
154 // A server error should never happen during an integration test. | 186 // A server error should never happen during an integration test. |
155 fail('${params.message}\n${params.stackTrace}'); | 187 fail('${params.message}\n${params.stackTrace}'); |
156 }); | 188 }); |
157 return startServer().then((_) { | 189 return startServer().then((_) { |
158 server.listenToOutput(dispatchNotification); | 190 server.listenToOutput(dispatchNotification); |
159 server.exitCode.then((_) { | 191 server.exitCode.then((_) { |
160 skipShutdown = true; | 192 skipShutdown = true; |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 return; | 550 return; |
519 } | 551 } |
520 _recordStdio('RECV: $trimmedLine'); | 552 _recordStdio('RECV: $trimmedLine'); |
521 var message; | 553 var message; |
522 try { | 554 try { |
523 message = JSON.decoder.convert(trimmedLine); | 555 message = JSON.decoder.convert(trimmedLine); |
524 } catch (exception) { | 556 } catch (exception) { |
525 _badDataFromServer('JSON decode failure: $exception'); | 557 _badDataFromServer('JSON decode failure: $exception'); |
526 return; | 558 return; |
527 } | 559 } |
528 expect(message, isMap); | 560 outOfTestExpect(message, isMap); |
529 Map messageAsMap = message; | 561 Map messageAsMap = message; |
530 if (messageAsMap.containsKey('id')) { | 562 if (messageAsMap.containsKey('id')) { |
531 expect(messageAsMap['id'], isString); | 563 outOfTestExpect(messageAsMap['id'], isString); |
532 String id = message['id']; | 564 String id = message['id']; |
533 Completer completer = _pendingCommands[id]; | 565 Completer completer = _pendingCommands[id]; |
534 if (completer == null) { | 566 if (completer == null) { |
535 fail('Unexpected response from server: id=$id'); | 567 fail('Unexpected response from server: id=$id'); |
536 } else { | 568 } else { |
537 _pendingCommands.remove(id); | 569 _pendingCommands.remove(id); |
538 } | 570 } |
539 if (messageAsMap.containsKey('error')) { | 571 if (messageAsMap.containsKey('error')) { |
540 // TODO(paulberry): propagate the error info to the completer. | 572 // TODO(paulberry): propagate the error info to the completer. |
541 completer.completeError(new UnimplementedError( | 573 completer.completeError(new UnimplementedError( |
542 'Server responded with an error: ${JSON.encode(message)}')); | 574 'Server responded with an error: ${JSON.encode(message)}')); |
543 } else { | 575 } else { |
544 completer.complete(messageAsMap['result']); | 576 completer.complete(messageAsMap['result']); |
545 } | 577 } |
546 // Check that the message is well-formed. We do this after calling | 578 // Check that the message is well-formed. We do this after calling |
547 // completer.complete() or completer.completeError() so that we don't | 579 // completer.complete() or completer.completeError() so that we don't |
548 // stall the test in the event of an error. | 580 // stall the test in the event of an error. |
549 expect(message, isResponse); | 581 outOfTestExpect(message, isResponse); |
550 } else { | 582 } else { |
551 // Message is a notification. It should have an event and possibly | 583 // Message is a notification. It should have an event and possibly |
552 // params. | 584 // params. |
553 expect(messageAsMap, contains('event')); | 585 outOfTestExpect(messageAsMap, contains('event')); |
554 expect(messageAsMap['event'], isString); | 586 outOfTestExpect(messageAsMap['event'], isString); |
555 notificationProcessor(messageAsMap['event'], messageAsMap['params']); | 587 notificationProcessor(messageAsMap['event'], messageAsMap['params']); |
556 // Check that the message is well-formed. We do this after calling | 588 // Check that the message is well-formed. We do this after calling |
557 // notificationController.add() so that we don't stall the test in the | 589 // notificationController.add() so that we don't stall the test in the |
558 // event of an error. | 590 // event of an error. |
559 expect(message, isNotification); | 591 outOfTestExpect(message, isNotification); |
560 } | 592 } |
561 }); | 593 }); |
562 _process.stderr | 594 _process.stderr |
563 .transform((new Utf8Codec()).decoder) | 595 .transform((new Utf8Codec()).decoder) |
564 .transform(new LineSplitter()) | 596 .transform(new LineSplitter()) |
565 .listen((String line) { | 597 .listen((String line) { |
566 String trimmedLine = line.trim(); | 598 String trimmedLine = line.trim(); |
567 _recordStdio('ERR: $trimmedLine'); | 599 _recordStdio('ERR: $trimmedLine'); |
568 _badDataFromServer('Message received on stderr', silent: true); | 600 _badDataFromServer('Message received on stderr', silent: true); |
569 }); | 601 }); |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 void populateMismatches(item, List<MismatchDescriber> mismatches); | 952 void populateMismatches(item, List<MismatchDescriber> mismatches); |
921 | 953 |
922 /** | 954 /** |
923 * Create a [MismatchDescriber] describing a mismatch with a simple string. | 955 * Create a [MismatchDescriber] describing a mismatch with a simple string. |
924 */ | 956 */ |
925 MismatchDescriber simpleDescription(String description) => | 957 MismatchDescriber simpleDescription(String description) => |
926 (Description mismatchDescription) { | 958 (Description mismatchDescription) { |
927 mismatchDescription.add(description); | 959 mismatchDescription.add(description); |
928 }; | 960 }; |
929 } | 961 } |
OLD | NEW |