Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: pkg/analysis_server/test/stress/utilities/server.dart

Issue 2611593002: Rework the replay test to be more correct (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/analysis_server/test/stress/utilities/logger.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 /** 5 /**
6 * Support for interacting with an analysis server running in a separate 6 * Support for interacting with an analysis server that is running in a separate
7 * process. 7 * process.
8 */ 8 */
9 library analysis_server.test.stress.utilities.server;
10
11 import 'dart:async'; 9 import 'dart:async';
12 import 'dart:collection'; 10 import 'dart:collection';
11 import 'dart:convert' hide JsonDecoder;
12 import 'dart:io';
13 import 'dart:math' as math;
13 14
14 import 'package:analysis_server/plugin/protocol/protocol.dart'; 15 import 'package:analysis_server/plugin/protocol/protocol.dart';
16 import 'package:path/path.dart' as path;
15 17
16 import '../../integration/integration_test_methods.dart'; 18 import 'logger.dart';
17 import '../../integration/integration_tests.dart' as base; 19
20 /**
21 * Return the current time expressed as milliseconds since the epoch.
22 */
23 int get currentTime => new DateTime.now().millisecondsSinceEpoch;
18 24
19 /** 25 /**
20 * ??? 26 * ???
21 */ 27 */
22 class ErrorMap { 28 class ErrorMap {
23 /** 29 /**
24 * A table mapping file paths to the errors associated with that file. 30 * A table mapping file paths to the errors associated with that file.
25 */ 31 */
26 final Map<String, List<AnalysisError>> pathMap = 32 final Map<String, List<AnalysisError>> pathMap =
27 new HashMap<String, List<AnalysisError>>(); 33 new HashMap<String, List<AnalysisError>>();
(...skipping 24 matching lines...) Expand all
52 _ErrorComparator comparator = new _ErrorComparator(buffer); 58 _ErrorComparator comparator = new _ErrorComparator(buffer);
53 comparator.compare(pathMap, errorMap.pathMap); 59 comparator.compare(pathMap, errorMap.pathMap);
54 if (buffer.length > 0) { 60 if (buffer.length > 0) {
55 return buffer.toString(); 61 return buffer.toString();
56 } 62 }
57 return null; 63 return null;
58 } 64 }
59 } 65 }
60 66
61 /** 67 /**
62 * An interface for starting and communicating with an analysis server running 68 * Data that has been collected about a request sent to the server.
63 * in a separate process.
64 */ 69 */
65 class Server extends base.Server with IntegrationTestMixin { 70 class RequestData {
71 /**
72 * The unique id of the request.
73 */
74 final String id;
75
76 /**
77 * The method that was requested.
78 */
79 final String method;
80
81 /**
82 * The request parameters.
83 */
84 final Map<String, dynamic> params;
85
86 /**
87 * The time at which the request was sent.
88 */
89 final int requestTime;
90
91 /**
92 * The time at which the response was received, or `null` if no response has
93 * been received.
94 */
95 int responseTime = null;
96
97 /**
98 * The response that was received.
99 */
100 Response _response;
101
102 /**
103 * The completer that will be completed when a response is received.
104 */
105 Completer<Response> _responseCompleter;
106
107 /**
108 * Initialize a newly created set of request data.
109 */
110 RequestData(this.id, this.method, this.params, this.requestTime);
111
112 /**
113 * Return the number of milliseconds that elapsed betwee the request and the
114 * response. This getter assumes that the response was received.
115 */
116 int get elapsedTime => responseTime - requestTime;
117
118 /**
119 * Return a future that will complete when a response is received.
120 */
121 Future<Response> get respondedTo {
122 if (_response != null) {
123 return new Future.value(_response);
124 }
125 if (_responseCompleter == null) {
126 _responseCompleter = new Completer<Response>();
127 }
128 return _responseCompleter.future;
129 }
130
131 /**
132 * Record that the given [response] was received.
133 */
134 void recordResponse(Response response) {
135 if (_response != null) {
136 stdout.writeln(
137 'Received a second response to a $method request (id = $id)');
138 return;
139 }
140 responseTime = currentTime;
141 _response = response;
142 if (_responseCompleter != null) {
143 _responseCompleter.complete(response);
144 _responseCompleter = null;
145 }
146 }
147 }
148
149 /**
150 * A utility for starting and communicating with an analysis server that is
151 * running in a separate process.
152 */
153 class Server {
154 /**
155 * The label used for communications from the client.
156 */
157 static const String fromClient = 'client';
158
159 /**
160 * The label used for normal communications from the server.
161 */
162 static const String fromServer = 'server';
163
164 /**
165 * The label used for output written by the server on [fromStderr].
166 */
167 static const String fromStderr = 'stderr';
168
169 /**
170 * The logger to which the communications log should be written, or `null` if
171 * the log should not be written.
172 */
173 final Logger logger;
174
175 /**
176 * The process in which the server is running, or `null` if the server hasn't
177 * been started yet.
178 */
179 Process _process = null;
180
181 /**
182 * Number that should be used to compute the 'id' to send in the next command
183 * sent to the server.
184 */
185 int _nextId = 0;
186
187 /**
188 * The analysis roots that are included.
189 */
190 List<String> _analysisRootIncludes = <String>[];
191
192 /**
193 * The analysis roots that are excluded.
194 */
195 List<String> _analysisRootExcludes = <String>[];
196
66 /** 197 /**
67 * A list containing the paths of files for which an overlay has been created. 198 * A list containing the paths of files for which an overlay has been created.
68 */ 199 */
69 List<String> filesWithOverlays = <String>[]; 200 List<String> filesWithOverlays = <String>[];
70 201
71 /** 202 /**
203 * The files that the server reported as being analyzed.
204 */
205 List<String> _analyzedFiles = <String>[];
206
207 /**
72 * A mapping from the absolute paths of files to the most recent set of errors 208 * A mapping from the absolute paths of files to the most recent set of errors
73 * received for that file. 209 * received for that file.
74 */ 210 */
75 ErrorMap _errorMap = new ErrorMap(); 211 ErrorMap _errorMap = new ErrorMap();
76 212
77 /** 213 /**
214 * The completer that will be completed the next time a 'server.status'
215 * notification is received from the server with 'analyzing' set to false.
216 */
217 Completer<Null> _analysisFinishedCompleter;
218
219 /**
220 * The completer that will be completed the next time a 'server.connected'
221 * notification is received from the server.
222 */
223 Completer<Null> _serverConnectedCompleter;
224
225 /**
226 * A table mapping the ids of requests that have been sent to the server to
227 * data about those requests.
228 */
229 final Map<String, RequestData> _requestDataMap = <String, RequestData>{};
230
231 /**
232 * A table mapping the number of times a request whose 'event' is equal to the
233 * key was sent to the server.
234 */
235 final Map<String, int> _notificationCountMap = <String, int>{};
236
237 /**
78 * Initialize a new analysis server. The analysis server is not running and 238 * Initialize a new analysis server. The analysis server is not running and
79 * must be started using [start]. 239 * must be started using [start].
80 */ 240 *
81 Server() { 241 * If a [logger] is provided, the communications between the client (this
82 initializeInttestMixin(); 242 * test) and the server will be written to it.
83 onAnalysisErrors.listen(_recordErrors); 243 */
244 Server({this.logger = null});
245
246 /**
247 * Return a future that will complete when a 'server.status' notification is
248 * received from the server with 'analyzing' set to false.
249 *
250 * The future will only be completed by 'server.status' notifications that are
251 * received after this function call, so it is safe to use this getter
252 * multiple times in one test; each time it is used it will wait afresh for
253 * analysis to finish.
254 */
255 Future get analysisFinished {
256 if (_analysisFinishedCompleter == null) {
257 _analysisFinishedCompleter = new Completer();
258 }
259 return _analysisFinishedCompleter.future;
84 } 260 }
85 261
86 /** 262 /**
87 * Return a list of the paths of files that are currently being analyzed. 263 * Return a list of the paths of files that are currently being analyzed.
88 */ 264 */
89 List<String> get analyzedDartFiles { 265 List<String> get analyzedDartFiles {
90 // TODO(brianwilkerson) Implement this. 266 bool isAnalyzed(String filePath) {
91 return <String>[]; 267 // TODO(brianwilkerson) This should use the path package to determine
92 } 268 // inclusion, and needs to take exclusions into account.
93 269 for (String includedRoot in _analysisRootIncludes) {
94 /** 270 if (filePath.startsWith(includedRoot)) {
271 return true;
272 }
273 }
274 return false;
275 }
276
277 List<String> analyzedFiles = <String>[];
278 for (String filePath in _analyzedFiles) {
279 if (filePath.endsWith('.dart') && isAnalyzed(filePath)) {
280 analyzedFiles.add(filePath);
281 }
282 }
283 return analyzedFiles;
284 }
285
286 /**
95 * Return a table mapping the absolute paths of files to the most recent set 287 * Return a table mapping the absolute paths of files to the most recent set
96 * of errors received for that file. The content of the map will not change 288 * of errors received for that file. The content of the map will not change
97 * when new sets of errors are received. 289 * when new sets of errors are received.
98 */ 290 */
99 ErrorMap get errorMap => new ErrorMap.from(_errorMap); 291 ErrorMap get errorMap => new ErrorMap.from(_errorMap);
100 292
101 @override
102 base.Server get server => this;
103
104 /** 293 /**
105 * Compute a mapping from each of the file paths in the given list of 294 * Compute a mapping from each of the file paths in the given list of
106 * [filePaths] to the list of errors in the file at that path. 295 * [filePaths] to the list of errors in the file at that path.
107 */ 296 */
108 Future<ErrorMap> computeErrorMap(List<String> filePaths) async { 297 Future<ErrorMap> computeErrorMap(List<String> filePaths) async {
109 ErrorMap errorMap = new ErrorMap(); 298 ErrorMap errorMap = new ErrorMap();
110 List<Future> futures = <Future>[]; 299 List<Future> futures = <Future>[];
111 for (String filePath in filePaths) { 300 for (String filePath in filePaths) {
112 futures.add(sendAnalysisGetErrors(filePath) 301 RequestData requestData = sendAnalysisGetErrors(filePath);
113 .then((AnalysisGetErrorsResult result) { 302 futures.add(requestData.respondedTo.then((Response response) {
114 errorMap[filePath] = result.errors; 303 if (response.result != null) {
304 AnalysisGetErrorsResult result =
305 new AnalysisGetErrorsResult.fromResponse(response);
306 errorMap[filePath] = result.errors;
307 }
115 })); 308 }));
116 } 309 }
117 await Future.wait(futures); 310 await Future.wait(futures);
118 return errorMap; 311 return errorMap;
119 } 312 }
120 313
121 /** 314 /**
315 * Print information about the communications with the server.
316 */
317 void printStatistics() {
318 void writeSpaces(int count) {
319 for (int i = 0; i < count; i++) {
320 stdout.write(' ');
321 }
322 }
323
324 //
325 // Print information about the requests that were sent.
326 //
327 stdout.writeln('Request Counts');
328 if (_requestDataMap.isEmpty) {
329 stdout.writeln(' none');
330 } else {
331 Map<String, List<RequestData>> requestsByMethod =
332 <String, List<RequestData>>{};
333 _requestDataMap.values.forEach((RequestData requestData) {
334 requestsByMethod
335 .putIfAbsent(requestData.method, () => <RequestData>[])
336 .add(requestData);
337 });
338 List<String> keys = requestsByMethod.keys.toList();
339 keys.sort();
340 int maxCount = requestsByMethod.values
341 .fold(0, (int count, List<RequestData> list) => count + list.length);
342 int countWidth = maxCount.toString().length;
343 for (String key in keys) {
344 List<RequestData> requests = requestsByMethod[key];
345 int noResponseCount = 0;
346 int responseCount = 0;
347 int minTime = -1;
348 int maxTime = -1;
349 int totalTime = 0;
350 requests.forEach((RequestData data) {
351 if (data.responseTime == null) {
352 noResponseCount++;
353 } else {
354 responseCount++;
355 int time = data.elapsedTime;
356 minTime = minTime < 0 ? time : math.min(minTime, time);
357 maxTime = math.max(maxTime, time);
358 totalTime += time;
359 }
360 });
361 String count = requests.length.toString();
362 writeSpaces(countWidth - count.length);
363 stdout.write(' ');
364 stdout.write(count);
365 stdout.write(' - ');
366 stdout.write(key);
367 if (noResponseCount > 0) {
368 stdout.write(', ');
369 stdout.write(noResponseCount);
370 stdout.write(' with no response');
371 }
372 if (maxTime >= 0) {
373 stdout.write(' (');
374 stdout.write(minTime);
375 stdout.write(', ');
376 stdout.write(totalTime / responseCount);
377 stdout.write(', ');
378 stdout.write(maxTime);
379 stdout.write(')');
380 }
381 stdout.writeln();
382 }
383 }
384 //
385 // Print information about the notifications that were received.
386 //
387 stdout.writeln();
388 stdout.writeln('Notification Counts');
389 if (_notificationCountMap.isEmpty) {
390 stdout.writeln(' none');
391 } else {
392 List<String> keys = _notificationCountMap.keys.toList();
393 keys.sort();
394 int maxCount = _notificationCountMap.values.fold(0, math.max);
395 int countWidth = maxCount.toString().length;
396 for (String key in keys) {
397 String count = _notificationCountMap[key].toString();
398 writeSpaces(countWidth - count.length);
399 stdout.write(' ');
400 stdout.write(count);
401 stdout.write(' - ');
402 stdout.writeln(key);
403 }
404 }
405 }
406
407 /**
122 * Remove any existing overlays. 408 * Remove any existing overlays.
123 */ 409 */
124 Future<AnalysisUpdateContentResult> removeAllOverlays() { 410 void removeAllOverlays() {
125 Map<String, dynamic> files = new HashMap<String, dynamic>(); 411 Map<String, dynamic> files = new HashMap<String, dynamic>();
126 for (String path in filesWithOverlays) { 412 for (String path in filesWithOverlays) {
127 files[path] = new RemoveContentOverlay(); 413 files[path] = new RemoveContentOverlay();
128 } 414 }
129 return sendAnalysisUpdateContent(files); 415 sendAnalysisUpdateContent(files);
130 } 416 }
131 417
132 @override 418 RequestData sendAnalysisGetErrors(String file) {
133 Future<AnalysisUpdateContentResult> sendAnalysisUpdateContent( 419 var params = new AnalysisGetErrorsParams(file).toJson();
134 Map<String, dynamic> files) { 420 return _send("analysis.getErrors", params);
421 }
422
423 RequestData sendAnalysisGetHover(String file, int offset) {
424 var params = new AnalysisGetHoverParams(file, offset).toJson();
425 return _send("analysis.getHover", params);
426 }
427
428 RequestData sendAnalysisGetLibraryDependencies() {
429 return _send("analysis.getLibraryDependencies", null);
430 }
431
432 RequestData sendAnalysisGetNavigation(String file, int offset, int length) {
433 var params = new AnalysisGetNavigationParams(file, offset, length).toJson();
434 return _send("analysis.getNavigation", params);
435 }
436
437 RequestData sendAnalysisGetReachableSources(String file) {
438 var params = new AnalysisGetReachableSourcesParams(file).toJson();
439 return _send("analysis.getReachableSources", params);
440 }
441
442 void sendAnalysisReanalyze({List<String> roots}) {
443 var params = new AnalysisReanalyzeParams(roots: roots).toJson();
444 _send("analysis.reanalyze", params);
445 }
446
447 void sendAnalysisSetAnalysisRoots(
448 List<String> included, List<String> excluded,
449 {Map<String, String> packageRoots}) {
450 _analysisRootIncludes = included;
451 _analysisRootExcludes = excluded;
452 var params = new AnalysisSetAnalysisRootsParams(included, excluded,
453 packageRoots: packageRoots)
454 .toJson();
455 _send("analysis.setAnalysisRoots", params);
456 }
457
458 void sendAnalysisSetGeneralSubscriptions(
459 List<GeneralAnalysisService> subscriptions) {
460 var params =
461 new AnalysisSetGeneralSubscriptionsParams(subscriptions).toJson();
462 _send("analysis.setGeneralSubscriptions", params);
463 }
464
465 void sendAnalysisSetPriorityFiles(List<String> files) {
466 var params = new AnalysisSetPriorityFilesParams(files).toJson();
467 _send("analysis.setPriorityFiles", params);
468 }
469
470 void sendAnalysisSetSubscriptions(
471 Map<AnalysisService, List<String>> subscriptions) {
472 var params = new AnalysisSetSubscriptionsParams(subscriptions).toJson();
473 _send("analysis.setSubscriptions", params);
474 }
475
476 void sendAnalysisUpdateContent(Map<String, dynamic> files) {
135 files.forEach((String path, dynamic overlay) { 477 files.forEach((String path, dynamic overlay) {
136 if (overlay is AddContentOverlay) { 478 if (overlay is AddContentOverlay) {
137 filesWithOverlays.add(path); 479 filesWithOverlays.add(path);
138 } else if (overlay is RemoveContentOverlay) { 480 } else if (overlay is RemoveContentOverlay) {
139 filesWithOverlays.remove(path); 481 filesWithOverlays.remove(path);
140 } 482 }
141 }); 483 });
142 return super.sendAnalysisUpdateContent(files); 484 var params = new AnalysisUpdateContentParams(files).toJson();
143 } 485 _send('analysis.updateContent', params);
144 486 }
145 /** 487
146 * Record the errors in the given [params]. 488 void sendAnalysisUpdateOptions(AnalysisOptions options) {
147 */ 489 var params = new AnalysisUpdateOptionsParams(options).toJson();
148 void _recordErrors(AnalysisErrorsParams params) { 490 _send("analysis.updateOptions", params);
149 _errorMap[params.file] = params.errors; 491 }
492
493 void sendCompletionGetSuggestions(String file, int offset) {
494 var params = new CompletionGetSuggestionsParams(file, offset).toJson();
495 _send("completion.getSuggestions", params);
496 }
497
498 RequestData sendDiagnosticGetDiagnostics() {
499 return _send("diagnostic.getDiagnostics", null);
500 }
501
502 RequestData sendEditFormat(
503 String file, int selectionOffset, int selectionLength,
504 {int lineLength}) {
505 var params = new EditFormatParams(file, selectionOffset, selectionLength,
506 lineLength: lineLength)
507 .toJson();
508 return _send("edit.format", params);
509 }
510
511 RequestData sendEditGetAssists(String file, int offset, int length) {
512 var params = new EditGetAssistsParams(file, offset, length).toJson();
513 return _send("edit.getAssists", params);
514 }
515
516 RequestData sendEditGetAvailableRefactorings(
517 String file, int offset, int length) {
518 var params =
519 new EditGetAvailableRefactoringsParams(file, offset, length).toJson();
520 return _send("edit.getAvailableRefactorings", params);
521 }
522
523 RequestData sendEditGetFixes(String file, int offset) {
524 var params = new EditGetFixesParams(file, offset).toJson();
525 return _send("edit.getFixes", params);
526 }
527
528 RequestData sendEditGetRefactoring(RefactoringKind kind, String file,
529 int offset, int length, bool validateOnly,
530 {RefactoringOptions options}) {
531 var params = new EditGetRefactoringParams(
532 kind, file, offset, length, validateOnly,
533 options: options)
534 .toJson();
535 return _send("edit.getRefactoring", params);
536 }
537
538 RequestData sendEditOrganizeDirectives(String file) {
539 var params = new EditOrganizeDirectivesParams(file).toJson();
540 return _send("edit.organizeDirectives", params);
541 }
542
543 RequestData sendEditSortMembers(String file) {
544 var params = new EditSortMembersParams(file).toJson();
545 return _send("edit.sortMembers", params);
546 }
547
548 RequestData sendExecutionCreateContext(String contextRoot) {
549 var params = new ExecutionCreateContextParams(contextRoot).toJson();
550 return _send("execution.createContext", params);
551 }
552
553 RequestData sendExecutionDeleteContext(String id) {
554 var params = new ExecutionDeleteContextParams(id).toJson();
555 return _send("execution.deleteContext", params);
556 }
557
558 RequestData sendExecutionMapUri(String id, {String file, String uri}) {
559 var params = new ExecutionMapUriParams(id, file: file, uri: uri).toJson();
560 return _send("execution.mapUri", params);
561 }
562
563 RequestData sendExecutionSetSubscriptions(
564 List<ExecutionService> subscriptions) {
565 var params = new ExecutionSetSubscriptionsParams(subscriptions).toJson();
566 return _send("execution.setSubscriptions", params);
567 }
568
569 void sendSearchFindElementReferences(
570 String file, int offset, bool includePotential) {
571 var params =
572 new SearchFindElementReferencesParams(file, offset, includePotential)
573 .toJson();
574 _send("search.findElementReferences", params);
575 }
576
577 void sendSearchFindMemberDeclarations(String name) {
578 var params = new SearchFindMemberDeclarationsParams(name).toJson();
579 _send("search.findMemberDeclarations", params);
580 }
581
582 void sendSearchFindMemberReferences(String name) {
583 var params = new SearchFindMemberReferencesParams(name).toJson();
584 _send("search.findMemberReferences", params);
585 }
586
587 void sendSearchFindTopLevelDeclarations(String pattern) {
588 var params = new SearchFindTopLevelDeclarationsParams(pattern).toJson();
589 _send("search.findTopLevelDeclarations", params);
590 }
591
592 void sendSearchGetTypeHierarchy(String file, int offset, {bool superOnly}) {
593 var params =
594 new SearchGetTypeHierarchyParams(file, offset, superOnly: superOnly)
595 .toJson();
596 _send("search.getTypeHierarchy", params);
597 }
598
599 RequestData sendServerGetVersion() {
600 return _send("server.getVersion", null);
601 }
602
603 void sendServerSetSubscriptions(List<ServerService> subscriptions) {
604 var params = new ServerSetSubscriptionsParams(subscriptions).toJson();
605 _send("server.setSubscriptions", params);
606 }
607
608 void sendServerShutdown() {
609 _send("server.shutdown", null);
610 }
611
612 /**
613 * Start the server and listen for communications from it.
614 *
615 * If [checked] is `true`, the server's VM will be running in checked mode.
616 *
617 * If [debugServer] is `true`, the server will be started with "--debug",
618 * allowing a debugger to be attached.
619 *
620 * If [diagnosticPort] is not `null`, the server will serve status pages to
621 * the specified port.
622 *
623 * If [enableNewAnalysisDriver] is `true`, the server will use the new
624 * analysis driver.
625 *
626 * If [profileServer] is `true`, the server will be started with "--observe"
627 * and "--pause-isolates-on-exit", allowing the observatory to be used.
628 *
629 * If [useAnalysisHighlight2] is `true`, the server will use the new highlight
630 * APIs.
631 */
632 Future<Null> start(
633 {bool checked: true,
634 bool debugServer: false,
635 int diagnosticPort,
636 bool enableNewAnalysisDriver: false,
637 bool profileServer: false,
638 String sdkPath,
639 int servicesPort,
640 bool useAnalysisHighlight2: false}) async {
641 if (_process != null) {
642 throw new Exception('Process already started');
643 }
644 String dartBinary = Platform.executable;
645 String rootDir =
646 _findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
647 String serverPath =
648 path.normalize(path.join(rootDir, 'bin', 'server.dart'));
649 List<String> arguments = [];
650 //
651 // Add VM arguments.
652 //
653 if (debugServer) {
654 arguments.add('--debug');
655 }
656 if (profileServer) {
657 if (servicesPort == null) {
658 arguments.add('--observe');
659 } else {
660 arguments.add('--observe=$servicesPort');
661 }
662 arguments.add('--pause-isolates-on-exit');
663 } else if (servicesPort != null) {
664 arguments.add('--enable-vm-service=$servicesPort');
665 }
666 if (Platform.packageRoot != null) {
667 arguments.add('--package-root=${Platform.packageRoot}');
668 }
669 if (Platform.packageConfig != null) {
670 arguments.add('--packages=${Platform.packageConfig}');
671 }
672 if (checked) {
673 arguments.add('--checked');
674 }
675 //
676 // Add the server executable.
677 //
678 arguments.add(serverPath);
679 //
680 // Add server arguments.
681 //
682 if (diagnosticPort != null) {
683 arguments.add('--port');
684 arguments.add(diagnosticPort.toString());
685 }
686 if (sdkPath != null) {
687 arguments.add('--sdk=$sdkPath');
688 }
689 if (useAnalysisHighlight2) {
690 arguments.add('--useAnalysisHighlight2');
691 }
692 if (enableNewAnalysisDriver) {
693 arguments.add('--enable-new-analysis-driver');
694 }
695 // stdout.writeln('Launching $serverPath');
696 // stdout.writeln('$dartBinary ${arguments.join(' ')}');
697 _process = await Process.start(dartBinary, arguments);
698 _process.exitCode.then((int code) {
699 if (code != 0) {
700 throw new StateError('Server terminated with exit code $code');
701 }
702 });
703 _listenToOutput();
704 _serverConnectedCompleter = new Completer();
705 return _serverConnectedCompleter.future;
706 }
707
708 /**
709 * Find the root directory of the analysis_server package by proceeding
710 * upward to the 'test' dir, and then going up one more directory.
711 */
712 String _findRoot(String pathname) {
713 while (!['benchmark', 'test'].contains(path.basename(pathname))) {
714 String parent = path.dirname(pathname);
715 if (parent.length >= pathname.length) {
716 throw new Exception("Can't find root directory");
717 }
718 pathname = parent;
719 }
720 return path.dirname(pathname);
721 }
722
723 /**
724 * Handle a [notification] received from the server.
725 */
726 void _handleNotification(Notification notification) {
727 switch (notification.event) {
728 case "server.connected":
729 // new ServerConnectedParams.fromNotification(notification);
730 _serverConnectedCompleter.complete(null);
731 break;
732 case "server.error":
733 // new ServerErrorParams.fromNotification(notification);
734 throw new StateError('Server error: ${notification.toJson()}');
735 break;
736 case "server.status":
737 if (_analysisFinishedCompleter != null) {
738 ServerStatusParams params =
739 new ServerStatusParams.fromNotification(notification);
740 var analysis = params.analysis;
741 if (analysis != null && !analysis.isAnalyzing) {
742 _analysisFinishedCompleter.complete(null);
743 }
744 }
745 break;
746 case "analysis.analyzedFiles":
747 AnalysisAnalyzedFilesParams params =
748 new AnalysisAnalyzedFilesParams.fromNotification(notification);
749 _analyzedFiles = params.directories;
750 break;
751 case "analysis.errors":
752 AnalysisErrorsParams params =
753 new AnalysisErrorsParams.fromNotification(notification);
754 _errorMap.pathMap[params.file] = params.errors;
755 break;
756 case "analysis.flushResults":
757 // new AnalysisFlushResultsParams.fromNotification(notification);
758 _errorMap.pathMap.clear();
759 break;
760 case "analysis.folding":
761 // new AnalysisFoldingParams.fromNotification(notification);
762 break;
763 case "analysis.highlights":
764 // new AnalysisHighlightsParams.fromNotification(notification);
765 break;
766 case "analysis.implemented":
767 // new AnalysisImplementedParams.fromNotification(notification);
768 break;
769 case "analysis.invalidate":
770 // new AnalysisInvalidateParams.fromNotification(notification);
771 break;
772 case "analysis.navigation":
773 // new AnalysisNavigationParams.fromNotification(notification);
774 break;
775 case "analysis.occurrences":
776 // new AnalysisOccurrencesParams.fromNotification(notification);
777 break;
778 case "analysis.outline":
779 // new AnalysisOutlineParams.fromNotification(notification);
780 break;
781 case "analysis.overrides":
782 // new AnalysisOverridesParams.fromNotification(notification);
783 break;
784 case "completion.results":
785 // new CompletionResultsParams.fromNotification(notification);
786 break;
787 case "search.results":
788 // new SearchResultsParams.fromNotification(notification);
789 break;
790 case "execution.launchData":
791 // new ExecutionLaunchDataParams.fromNotification(notification);
792 break;
793 default:
794 throw new StateError(
795 'Unhandled notification: ${notification.toJson()}');
796 }
797 }
798
799 /**
800 * Handle a [response] received from the server.
801 */
802 void _handleResponse(Response response) {
803 String id = response.id.toString();
804 RequestData requestData = _requestDataMap[id];
805 requestData.recordResponse(response);
806 // switch (requestData.method) {
807 // case "analysis.getErrors":
808 // break;
809 // case "analysis.getHover":
810 // break;
811 // case "analysis.getLibraryDependencies":
812 // break;
813 // case "analysis.getNavigation":
814 // break;
815 // case "analysis.getReachableSources":
816 // break;
817 // case "analysis.reanalyze":
818 // break;
819 // case "analysis.setAnalysisRoots":
820 // break;
821 // case "analysis.setGeneralSubscriptions":
822 // break;
823 // case "analysis.setPriorityFiles":
824 // break;
825 // case "analysis.setSubscriptions":
826 // break;
827 // case 'analysis.updateContent':
828 // break;
829 // case "analysis.updateOptions":
830 // break;
831 // case "completion.getSuggestions":
832 // break;
833 // case "diagnostic.getDiagnostics":
834 // break;
835 // case "edit.format":
836 // break;
837 // case "edit.getAssists":
838 // break;
839 // case "edit.getAvailableRefactorings":
840 // break;
841 // case "edit.getFixes":
842 // break;
843 // case "edit.getRefactoring":
844 // break;
845 // case "edit.organizeDirectives":
846 // break;
847 // case "edit.sortMembers":
848 // break;
849 // case "execution.createContext":
850 // break;
851 // case "execution.deleteContext":
852 // break;
853 // case "execution.mapUri":
854 // break;
855 // case "execution.setSubscriptions":
856 // break;
857 // case "search.findElementReferences":
858 // break;
859 // case "search.findMemberDeclarations":
860 // break;
861 // case "search.findMemberReferences":
862 // break;
863 // case "search.findTopLevelDeclarations":
864 // break;
865 // case "search.getTypeHierarchy":
866 // break;
867 // case "server.getVersion":
868 // break;
869 // case "server.setSubscriptions":
870 // break;
871 // case "server.shutdown":
872 // break;
873 // default:
874 // throw new StateError('Unhandled response: ${response.toJson()}');
875 // }
876 }
877
878 /**
879 * Handle a [line] of input read from stderr.
880 */
881 void _handleStdErr(String line) {
882 String trimmedLine = line.trim();
883 logger?.log(fromStderr, '$trimmedLine');
884 throw new StateError('Message received on stderr: "$trimmedLine"');
885 }
886
887 /**
888 * Handle a [line] of input read from stdout.
889 */
890 void _handleStdOut(String line) {
891 /**
892 * Cast the given [value] to a Map, or throw an [ArgumentError] if the value
893 * cannot be cast.
894 */
895 Map asMap(Object value) {
896 if (value is Map) {
897 return value;
898 }
899 throw new ArgumentError('Expected a Map, found a ${value.runtimeType}');
900 }
901
902 String trimmedLine = line.trim();
903 if (trimmedLine.isEmpty ||
904 trimmedLine.startsWith('Observatory listening on ')) {
905 return;
906 }
907 logger?.log(fromServer, '$trimmedLine');
908 Map message = asMap(JSON.decoder.convert(trimmedLine));
909 if (message.containsKey('id')) {
910 // The message is a response.
911 Response response = new Response.fromJson(message);
912 _handleResponse(response);
913 } else {
914 // The message is a notification.
915 Notification notification = new Notification.fromJson(message);
916 String event = notification.event;
917 _notificationCountMap[event] = (_notificationCountMap[event] ?? 0) + 1;
918 _handleNotification(notification);
919 }
920 }
921
922 /**
923 * Start listening to output from the server.
924 */
925 void _listenToOutput() {
926 /**
927 * Install the given [handler] to listen to transformed output from the
928 * given [stream].
929 */
930 void installHandler(Stream<List<int>> stream, handler(String line)) {
931 stream
932 .transform((new Utf8Codec()).decoder)
933 .transform(new LineSplitter())
934 .listen(handler);
935 }
936
937 installHandler(_process.stdout, _handleStdOut);
938 installHandler(_process.stderr, _handleStdErr);
939 }
940
941 /**
942 * Send a command to the server. An 'id' will be automatically assigned.
943 */
944 RequestData _send(String method, Map<String, dynamic> params,
945 {void onResponse(Response response)}) {
946 String id = '${_nextId++}';
947 RequestData requestData = new RequestData(id, method, params, currentTime);
948 _requestDataMap[id] = requestData;
949 Map<String, dynamic> command = <String, dynamic>{
950 'id': id,
951 'method': method
952 };
953 if (params != null) {
954 command['params'] = params;
955 }
956 String line = JSON.encode(command);
957 _process.stdin.add(UTF8.encoder.convert('$line\n'));
958 logger?.log(fromClient, '$line');
959 return requestData;
150 } 960 }
151 } 961 }
152 962
153 /** 963 /**
154 * A utility class used to compare two sets of errors. 964 * A utility class used to compare two sets of errors.
155 */ 965 */
156 class _ErrorComparator { 966 class _ErrorComparator {
157 /** 967 /**
158 * An empty list of analysis errors. 968 * An empty list of analysis errors.
159 */ 969 */
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 */ 1087 */
278 void _writeReport(String filePath, List<AnalysisError> actualErrors, 1088 void _writeReport(String filePath, List<AnalysisError> actualErrors,
279 List<AnalysisError> expectedErrors) { 1089 List<AnalysisError> expectedErrors) {
280 if (buffer.length > 0) { 1090 if (buffer.length > 0) {
281 buffer.writeln(); 1091 buffer.writeln();
282 buffer.writeln(); 1092 buffer.writeln();
283 } 1093 }
284 buffer.writeln(filePath); 1094 buffer.writeln(filePath);
285 _writeErrors(' Expected ', expectedErrors); 1095 _writeErrors(' Expected ', expectedErrors);
286 buffer.writeln(); 1096 buffer.writeln();
287 _writeErrors(' Found ', expectedErrors); 1097 _writeErrors(' Found ', actualErrors);
288 } 1098 }
289 } 1099 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/test/stress/utilities/logger.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698