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

Unified 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, 12 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analysis_server/test/stress/utilities/logger.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analysis_server/test/stress/utilities/server.dart
diff --git a/pkg/analysis_server/test/stress/utilities/server.dart b/pkg/analysis_server/test/stress/utilities/server.dart
index ee52fdd6551ecd7369699b19ed6de443218225d6..cc96aca88af5f5aa892ee70b2ba7feb89b65ba3f 100644
--- a/pkg/analysis_server/test/stress/utilities/server.dart
+++ b/pkg/analysis_server/test/stress/utilities/server.dart
@@ -3,18 +3,24 @@
// BSD-style license that can be found in the LICENSE file.
/**
- * Support for interacting with an analysis server running in a separate
+ * Support for interacting with an analysis server that is running in a separate
* process.
*/
-library analysis_server.test.stress.utilities.server;
-
import 'dart:async';
import 'dart:collection';
+import 'dart:convert' hide JsonDecoder;
+import 'dart:io';
+import 'dart:math' as math;
import 'package:analysis_server/plugin/protocol/protocol.dart';
+import 'package:path/path.dart' as path;
+
+import 'logger.dart';
-import '../../integration/integration_test_methods.dart';
-import '../../integration/integration_tests.dart' as base;
+/**
+ * Return the current time expressed as milliseconds since the epoch.
+ */
+int get currentTime => new DateTime.now().millisecondsSinceEpoch;
/**
* ???
@@ -59,36 +65,222 @@ class ErrorMap {
}
/**
- * An interface for starting and communicating with an analysis server running
- * in a separate process.
+ * Data that has been collected about a request sent to the server.
+ */
+class RequestData {
+ /**
+ * The unique id of the request.
+ */
+ final String id;
+
+ /**
+ * The method that was requested.
+ */
+ final String method;
+
+ /**
+ * The request parameters.
+ */
+ final Map<String, dynamic> params;
+
+ /**
+ * The time at which the request was sent.
+ */
+ final int requestTime;
+
+ /**
+ * The time at which the response was received, or `null` if no response has
+ * been received.
+ */
+ int responseTime = null;
+
+ /**
+ * The response that was received.
+ */
+ Response _response;
+
+ /**
+ * The completer that will be completed when a response is received.
+ */
+ Completer<Response> _responseCompleter;
+
+ /**
+ * Initialize a newly created set of request data.
+ */
+ RequestData(this.id, this.method, this.params, this.requestTime);
+
+ /**
+ * Return the number of milliseconds that elapsed betwee the request and the
+ * response. This getter assumes that the response was received.
+ */
+ int get elapsedTime => responseTime - requestTime;
+
+ /**
+ * Return a future that will complete when a response is received.
+ */
+ Future<Response> get respondedTo {
+ if (_response != null) {
+ return new Future.value(_response);
+ }
+ if (_responseCompleter == null) {
+ _responseCompleter = new Completer<Response>();
+ }
+ return _responseCompleter.future;
+ }
+
+ /**
+ * Record that the given [response] was received.
+ */
+ void recordResponse(Response response) {
+ if (_response != null) {
+ stdout.writeln(
+ 'Received a second response to a $method request (id = $id)');
+ return;
+ }
+ responseTime = currentTime;
+ _response = response;
+ if (_responseCompleter != null) {
+ _responseCompleter.complete(response);
+ _responseCompleter = null;
+ }
+ }
+}
+
+/**
+ * A utility for starting and communicating with an analysis server that is
+ * running in a separate process.
*/
-class Server extends base.Server with IntegrationTestMixin {
+class Server {
+ /**
+ * The label used for communications from the client.
+ */
+ static const String fromClient = 'client';
+
+ /**
+ * The label used for normal communications from the server.
+ */
+ static const String fromServer = 'server';
+
+ /**
+ * The label used for output written by the server on [fromStderr].
+ */
+ static const String fromStderr = 'stderr';
+
+ /**
+ * The logger to which the communications log should be written, or `null` if
+ * the log should not be written.
+ */
+ final Logger logger;
+
+ /**
+ * The process in which the server is running, or `null` if the server hasn't
+ * been started yet.
+ */
+ Process _process = null;
+
+ /**
+ * Number that should be used to compute the 'id' to send in the next command
+ * sent to the server.
+ */
+ int _nextId = 0;
+
+ /**
+ * The analysis roots that are included.
+ */
+ List<String> _analysisRootIncludes = <String>[];
+
+ /**
+ * The analysis roots that are excluded.
+ */
+ List<String> _analysisRootExcludes = <String>[];
+
/**
* A list containing the paths of files for which an overlay has been created.
*/
List<String> filesWithOverlays = <String>[];
/**
+ * The files that the server reported as being analyzed.
+ */
+ List<String> _analyzedFiles = <String>[];
+
+ /**
* A mapping from the absolute paths of files to the most recent set of errors
* received for that file.
*/
ErrorMap _errorMap = new ErrorMap();
/**
+ * The completer that will be completed the next time a 'server.status'
+ * notification is received from the server with 'analyzing' set to false.
+ */
+ Completer<Null> _analysisFinishedCompleter;
+
+ /**
+ * The completer that will be completed the next time a 'server.connected'
+ * notification is received from the server.
+ */
+ Completer<Null> _serverConnectedCompleter;
+
+ /**
+ * A table mapping the ids of requests that have been sent to the server to
+ * data about those requests.
+ */
+ final Map<String, RequestData> _requestDataMap = <String, RequestData>{};
+
+ /**
+ * A table mapping the number of times a request whose 'event' is equal to the
+ * key was sent to the server.
+ */
+ final Map<String, int> _notificationCountMap = <String, int>{};
+
+ /**
* Initialize a new analysis server. The analysis server is not running and
* must be started using [start].
+ *
+ * If a [logger] is provided, the communications between the client (this
+ * test) and the server will be written to it.
+ */
+ Server({this.logger = null});
+
+ /**
+ * Return a future that will complete when a 'server.status' notification is
+ * received from the server with 'analyzing' set to false.
+ *
+ * The future will only be completed by 'server.status' notifications that are
+ * received after this function call, so it is safe to use this getter
+ * multiple times in one test; each time it is used it will wait afresh for
+ * analysis to finish.
*/
- Server() {
- initializeInttestMixin();
- onAnalysisErrors.listen(_recordErrors);
+ Future get analysisFinished {
+ if (_analysisFinishedCompleter == null) {
+ _analysisFinishedCompleter = new Completer();
+ }
+ return _analysisFinishedCompleter.future;
}
/**
* Return a list of the paths of files that are currently being analyzed.
*/
List<String> get analyzedDartFiles {
- // TODO(brianwilkerson) Implement this.
- return <String>[];
+ bool isAnalyzed(String filePath) {
+ // TODO(brianwilkerson) This should use the path package to determine
+ // inclusion, and needs to take exclusions into account.
+ for (String includedRoot in _analysisRootIncludes) {
+ if (filePath.startsWith(includedRoot)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ List<String> analyzedFiles = <String>[];
+ for (String filePath in _analyzedFiles) {
+ if (filePath.endsWith('.dart') && isAnalyzed(filePath)) {
+ analyzedFiles.add(filePath);
+ }
+ }
+ return analyzedFiles;
}
/**
@@ -98,9 +290,6 @@ class Server extends base.Server with IntegrationTestMixin {
*/
ErrorMap get errorMap => new ErrorMap.from(_errorMap);
- @override
- base.Server get server => this;
-
/**
* Compute a mapping from each of the file paths in the given list of
* [filePaths] to the list of errors in the file at that path.
@@ -109,9 +298,13 @@ class Server extends base.Server with IntegrationTestMixin {
ErrorMap errorMap = new ErrorMap();
List<Future> futures = <Future>[];
for (String filePath in filePaths) {
- futures.add(sendAnalysisGetErrors(filePath)
- .then((AnalysisGetErrorsResult result) {
- errorMap[filePath] = result.errors;
+ RequestData requestData = sendAnalysisGetErrors(filePath);
+ futures.add(requestData.respondedTo.then((Response response) {
+ if (response.result != null) {
+ AnalysisGetErrorsResult result =
+ new AnalysisGetErrorsResult.fromResponse(response);
+ errorMap[filePath] = result.errors;
+ }
}));
}
await Future.wait(futures);
@@ -119,19 +312,168 @@ class Server extends base.Server with IntegrationTestMixin {
}
/**
+ * Print information about the communications with the server.
+ */
+ void printStatistics() {
+ void writeSpaces(int count) {
+ for (int i = 0; i < count; i++) {
+ stdout.write(' ');
+ }
+ }
+
+ //
+ // Print information about the requests that were sent.
+ //
+ stdout.writeln('Request Counts');
+ if (_requestDataMap.isEmpty) {
+ stdout.writeln(' none');
+ } else {
+ Map<String, List<RequestData>> requestsByMethod =
+ <String, List<RequestData>>{};
+ _requestDataMap.values.forEach((RequestData requestData) {
+ requestsByMethod
+ .putIfAbsent(requestData.method, () => <RequestData>[])
+ .add(requestData);
+ });
+ List<String> keys = requestsByMethod.keys.toList();
+ keys.sort();
+ int maxCount = requestsByMethod.values
+ .fold(0, (int count, List<RequestData> list) => count + list.length);
+ int countWidth = maxCount.toString().length;
+ for (String key in keys) {
+ List<RequestData> requests = requestsByMethod[key];
+ int noResponseCount = 0;
+ int responseCount = 0;
+ int minTime = -1;
+ int maxTime = -1;
+ int totalTime = 0;
+ requests.forEach((RequestData data) {
+ if (data.responseTime == null) {
+ noResponseCount++;
+ } else {
+ responseCount++;
+ int time = data.elapsedTime;
+ minTime = minTime < 0 ? time : math.min(minTime, time);
+ maxTime = math.max(maxTime, time);
+ totalTime += time;
+ }
+ });
+ String count = requests.length.toString();
+ writeSpaces(countWidth - count.length);
+ stdout.write(' ');
+ stdout.write(count);
+ stdout.write(' - ');
+ stdout.write(key);
+ if (noResponseCount > 0) {
+ stdout.write(', ');
+ stdout.write(noResponseCount);
+ stdout.write(' with no response');
+ }
+ if (maxTime >= 0) {
+ stdout.write(' (');
+ stdout.write(minTime);
+ stdout.write(', ');
+ stdout.write(totalTime / responseCount);
+ stdout.write(', ');
+ stdout.write(maxTime);
+ stdout.write(')');
+ }
+ stdout.writeln();
+ }
+ }
+ //
+ // Print information about the notifications that were received.
+ //
+ stdout.writeln();
+ stdout.writeln('Notification Counts');
+ if (_notificationCountMap.isEmpty) {
+ stdout.writeln(' none');
+ } else {
+ List<String> keys = _notificationCountMap.keys.toList();
+ keys.sort();
+ int maxCount = _notificationCountMap.values.fold(0, math.max);
+ int countWidth = maxCount.toString().length;
+ for (String key in keys) {
+ String count = _notificationCountMap[key].toString();
+ writeSpaces(countWidth - count.length);
+ stdout.write(' ');
+ stdout.write(count);
+ stdout.write(' - ');
+ stdout.writeln(key);
+ }
+ }
+ }
+
+ /**
* Remove any existing overlays.
*/
- Future<AnalysisUpdateContentResult> removeAllOverlays() {
+ void removeAllOverlays() {
Map<String, dynamic> files = new HashMap<String, dynamic>();
for (String path in filesWithOverlays) {
files[path] = new RemoveContentOverlay();
}
- return sendAnalysisUpdateContent(files);
+ sendAnalysisUpdateContent(files);
+ }
+
+ RequestData sendAnalysisGetErrors(String file) {
+ var params = new AnalysisGetErrorsParams(file).toJson();
+ return _send("analysis.getErrors", params);
+ }
+
+ RequestData sendAnalysisGetHover(String file, int offset) {
+ var params = new AnalysisGetHoverParams(file, offset).toJson();
+ return _send("analysis.getHover", params);
+ }
+
+ RequestData sendAnalysisGetLibraryDependencies() {
+ return _send("analysis.getLibraryDependencies", null);
+ }
+
+ RequestData sendAnalysisGetNavigation(String file, int offset, int length) {
+ var params = new AnalysisGetNavigationParams(file, offset, length).toJson();
+ return _send("analysis.getNavigation", params);
+ }
+
+ RequestData sendAnalysisGetReachableSources(String file) {
+ var params = new AnalysisGetReachableSourcesParams(file).toJson();
+ return _send("analysis.getReachableSources", params);
+ }
+
+ void sendAnalysisReanalyze({List<String> roots}) {
+ var params = new AnalysisReanalyzeParams(roots: roots).toJson();
+ _send("analysis.reanalyze", params);
+ }
+
+ void sendAnalysisSetAnalysisRoots(
+ List<String> included, List<String> excluded,
+ {Map<String, String> packageRoots}) {
+ _analysisRootIncludes = included;
+ _analysisRootExcludes = excluded;
+ var params = new AnalysisSetAnalysisRootsParams(included, excluded,
+ packageRoots: packageRoots)
+ .toJson();
+ _send("analysis.setAnalysisRoots", params);
+ }
+
+ void sendAnalysisSetGeneralSubscriptions(
+ List<GeneralAnalysisService> subscriptions) {
+ var params =
+ new AnalysisSetGeneralSubscriptionsParams(subscriptions).toJson();
+ _send("analysis.setGeneralSubscriptions", params);
+ }
+
+ void sendAnalysisSetPriorityFiles(List<String> files) {
+ var params = new AnalysisSetPriorityFilesParams(files).toJson();
+ _send("analysis.setPriorityFiles", params);
+ }
+
+ void sendAnalysisSetSubscriptions(
+ Map<AnalysisService, List<String>> subscriptions) {
+ var params = new AnalysisSetSubscriptionsParams(subscriptions).toJson();
+ _send("analysis.setSubscriptions", params);
}
- @override
- Future<AnalysisUpdateContentResult> sendAnalysisUpdateContent(
- Map<String, dynamic> files) {
+ void sendAnalysisUpdateContent(Map<String, dynamic> files) {
files.forEach((String path, dynamic overlay) {
if (overlay is AddContentOverlay) {
filesWithOverlays.add(path);
@@ -139,14 +481,482 @@ class Server extends base.Server with IntegrationTestMixin {
filesWithOverlays.remove(path);
}
});
- return super.sendAnalysisUpdateContent(files);
+ var params = new AnalysisUpdateContentParams(files).toJson();
+ _send('analysis.updateContent', params);
+ }
+
+ void sendAnalysisUpdateOptions(AnalysisOptions options) {
+ var params = new AnalysisUpdateOptionsParams(options).toJson();
+ _send("analysis.updateOptions", params);
+ }
+
+ void sendCompletionGetSuggestions(String file, int offset) {
+ var params = new CompletionGetSuggestionsParams(file, offset).toJson();
+ _send("completion.getSuggestions", params);
+ }
+
+ RequestData sendDiagnosticGetDiagnostics() {
+ return _send("diagnostic.getDiagnostics", null);
+ }
+
+ RequestData sendEditFormat(
+ String file, int selectionOffset, int selectionLength,
+ {int lineLength}) {
+ var params = new EditFormatParams(file, selectionOffset, selectionLength,
+ lineLength: lineLength)
+ .toJson();
+ return _send("edit.format", params);
+ }
+
+ RequestData sendEditGetAssists(String file, int offset, int length) {
+ var params = new EditGetAssistsParams(file, offset, length).toJson();
+ return _send("edit.getAssists", params);
+ }
+
+ RequestData sendEditGetAvailableRefactorings(
+ String file, int offset, int length) {
+ var params =
+ new EditGetAvailableRefactoringsParams(file, offset, length).toJson();
+ return _send("edit.getAvailableRefactorings", params);
+ }
+
+ RequestData sendEditGetFixes(String file, int offset) {
+ var params = new EditGetFixesParams(file, offset).toJson();
+ return _send("edit.getFixes", params);
+ }
+
+ RequestData sendEditGetRefactoring(RefactoringKind kind, String file,
+ int offset, int length, bool validateOnly,
+ {RefactoringOptions options}) {
+ var params = new EditGetRefactoringParams(
+ kind, file, offset, length, validateOnly,
+ options: options)
+ .toJson();
+ return _send("edit.getRefactoring", params);
+ }
+
+ RequestData sendEditOrganizeDirectives(String file) {
+ var params = new EditOrganizeDirectivesParams(file).toJson();
+ return _send("edit.organizeDirectives", params);
+ }
+
+ RequestData sendEditSortMembers(String file) {
+ var params = new EditSortMembersParams(file).toJson();
+ return _send("edit.sortMembers", params);
+ }
+
+ RequestData sendExecutionCreateContext(String contextRoot) {
+ var params = new ExecutionCreateContextParams(contextRoot).toJson();
+ return _send("execution.createContext", params);
+ }
+
+ RequestData sendExecutionDeleteContext(String id) {
+ var params = new ExecutionDeleteContextParams(id).toJson();
+ return _send("execution.deleteContext", params);
+ }
+
+ RequestData sendExecutionMapUri(String id, {String file, String uri}) {
+ var params = new ExecutionMapUriParams(id, file: file, uri: uri).toJson();
+ return _send("execution.mapUri", params);
+ }
+
+ RequestData sendExecutionSetSubscriptions(
+ List<ExecutionService> subscriptions) {
+ var params = new ExecutionSetSubscriptionsParams(subscriptions).toJson();
+ return _send("execution.setSubscriptions", params);
+ }
+
+ void sendSearchFindElementReferences(
+ String file, int offset, bool includePotential) {
+ var params =
+ new SearchFindElementReferencesParams(file, offset, includePotential)
+ .toJson();
+ _send("search.findElementReferences", params);
+ }
+
+ void sendSearchFindMemberDeclarations(String name) {
+ var params = new SearchFindMemberDeclarationsParams(name).toJson();
+ _send("search.findMemberDeclarations", params);
+ }
+
+ void sendSearchFindMemberReferences(String name) {
+ var params = new SearchFindMemberReferencesParams(name).toJson();
+ _send("search.findMemberReferences", params);
+ }
+
+ void sendSearchFindTopLevelDeclarations(String pattern) {
+ var params = new SearchFindTopLevelDeclarationsParams(pattern).toJson();
+ _send("search.findTopLevelDeclarations", params);
+ }
+
+ void sendSearchGetTypeHierarchy(String file, int offset, {bool superOnly}) {
+ var params =
+ new SearchGetTypeHierarchyParams(file, offset, superOnly: superOnly)
+ .toJson();
+ _send("search.getTypeHierarchy", params);
+ }
+
+ RequestData sendServerGetVersion() {
+ return _send("server.getVersion", null);
+ }
+
+ void sendServerSetSubscriptions(List<ServerService> subscriptions) {
+ var params = new ServerSetSubscriptionsParams(subscriptions).toJson();
+ _send("server.setSubscriptions", params);
+ }
+
+ void sendServerShutdown() {
+ _send("server.shutdown", null);
+ }
+
+ /**
+ * Start the server and listen for communications from it.
+ *
+ * If [checked] is `true`, the server's VM will be running in checked mode.
+ *
+ * If [debugServer] is `true`, the server will be started with "--debug",
+ * allowing a debugger to be attached.
+ *
+ * If [diagnosticPort] is not `null`, the server will serve status pages to
+ * the specified port.
+ *
+ * If [enableNewAnalysisDriver] is `true`, the server will use the new
+ * analysis driver.
+ *
+ * If [profileServer] is `true`, the server will be started with "--observe"
+ * and "--pause-isolates-on-exit", allowing the observatory to be used.
+ *
+ * If [useAnalysisHighlight2] is `true`, the server will use the new highlight
+ * APIs.
+ */
+ Future<Null> start(
+ {bool checked: true,
+ bool debugServer: false,
+ int diagnosticPort,
+ bool enableNewAnalysisDriver: false,
+ bool profileServer: false,
+ String sdkPath,
+ int servicesPort,
+ bool useAnalysisHighlight2: false}) async {
+ if (_process != null) {
+ throw new Exception('Process already started');
+ }
+ String dartBinary = Platform.executable;
+ String rootDir =
+ _findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
+ String serverPath =
+ path.normalize(path.join(rootDir, 'bin', 'server.dart'));
+ List<String> arguments = [];
+ //
+ // Add VM arguments.
+ //
+ if (debugServer) {
+ arguments.add('--debug');
+ }
+ if (profileServer) {
+ if (servicesPort == null) {
+ arguments.add('--observe');
+ } else {
+ arguments.add('--observe=$servicesPort');
+ }
+ arguments.add('--pause-isolates-on-exit');
+ } else if (servicesPort != null) {
+ arguments.add('--enable-vm-service=$servicesPort');
+ }
+ if (Platform.packageRoot != null) {
+ arguments.add('--package-root=${Platform.packageRoot}');
+ }
+ if (Platform.packageConfig != null) {
+ arguments.add('--packages=${Platform.packageConfig}');
+ }
+ if (checked) {
+ arguments.add('--checked');
+ }
+ //
+ // Add the server executable.
+ //
+ arguments.add(serverPath);
+ //
+ // Add server arguments.
+ //
+ if (diagnosticPort != null) {
+ arguments.add('--port');
+ arguments.add(diagnosticPort.toString());
+ }
+ if (sdkPath != null) {
+ arguments.add('--sdk=$sdkPath');
+ }
+ if (useAnalysisHighlight2) {
+ arguments.add('--useAnalysisHighlight2');
+ }
+ if (enableNewAnalysisDriver) {
+ arguments.add('--enable-new-analysis-driver');
+ }
+// stdout.writeln('Launching $serverPath');
+// stdout.writeln('$dartBinary ${arguments.join(' ')}');
+ _process = await Process.start(dartBinary, arguments);
+ _process.exitCode.then((int code) {
+ if (code != 0) {
+ throw new StateError('Server terminated with exit code $code');
+ }
+ });
+ _listenToOutput();
+ _serverConnectedCompleter = new Completer();
+ return _serverConnectedCompleter.future;
+ }
+
+ /**
+ * Find the root directory of the analysis_server package by proceeding
+ * upward to the 'test' dir, and then going up one more directory.
+ */
+ String _findRoot(String pathname) {
+ while (!['benchmark', 'test'].contains(path.basename(pathname))) {
+ String parent = path.dirname(pathname);
+ if (parent.length >= pathname.length) {
+ throw new Exception("Can't find root directory");
+ }
+ pathname = parent;
+ }
+ return path.dirname(pathname);
}
/**
- * Record the errors in the given [params].
+ * Handle a [notification] received from the server.
*/
- void _recordErrors(AnalysisErrorsParams params) {
- _errorMap[params.file] = params.errors;
+ void _handleNotification(Notification notification) {
+ switch (notification.event) {
+ case "server.connected":
+// new ServerConnectedParams.fromNotification(notification);
+ _serverConnectedCompleter.complete(null);
+ break;
+ case "server.error":
+// new ServerErrorParams.fromNotification(notification);
+ throw new StateError('Server error: ${notification.toJson()}');
+ break;
+ case "server.status":
+ if (_analysisFinishedCompleter != null) {
+ ServerStatusParams params =
+ new ServerStatusParams.fromNotification(notification);
+ var analysis = params.analysis;
+ if (analysis != null && !analysis.isAnalyzing) {
+ _analysisFinishedCompleter.complete(null);
+ }
+ }
+ break;
+ case "analysis.analyzedFiles":
+ AnalysisAnalyzedFilesParams params =
+ new AnalysisAnalyzedFilesParams.fromNotification(notification);
+ _analyzedFiles = params.directories;
+ break;
+ case "analysis.errors":
+ AnalysisErrorsParams params =
+ new AnalysisErrorsParams.fromNotification(notification);
+ _errorMap.pathMap[params.file] = params.errors;
+ break;
+ case "analysis.flushResults":
+// new AnalysisFlushResultsParams.fromNotification(notification);
+ _errorMap.pathMap.clear();
+ break;
+ case "analysis.folding":
+// new AnalysisFoldingParams.fromNotification(notification);
+ break;
+ case "analysis.highlights":
+// new AnalysisHighlightsParams.fromNotification(notification);
+ break;
+ case "analysis.implemented":
+// new AnalysisImplementedParams.fromNotification(notification);
+ break;
+ case "analysis.invalidate":
+// new AnalysisInvalidateParams.fromNotification(notification);
+ break;
+ case "analysis.navigation":
+// new AnalysisNavigationParams.fromNotification(notification);
+ break;
+ case "analysis.occurrences":
+// new AnalysisOccurrencesParams.fromNotification(notification);
+ break;
+ case "analysis.outline":
+// new AnalysisOutlineParams.fromNotification(notification);
+ break;
+ case "analysis.overrides":
+// new AnalysisOverridesParams.fromNotification(notification);
+ break;
+ case "completion.results":
+// new CompletionResultsParams.fromNotification(notification);
+ break;
+ case "search.results":
+// new SearchResultsParams.fromNotification(notification);
+ break;
+ case "execution.launchData":
+// new ExecutionLaunchDataParams.fromNotification(notification);
+ break;
+ default:
+ throw new StateError(
+ 'Unhandled notification: ${notification.toJson()}');
+ }
+ }
+
+ /**
+ * Handle a [response] received from the server.
+ */
+ void _handleResponse(Response response) {
+ String id = response.id.toString();
+ RequestData requestData = _requestDataMap[id];
+ requestData.recordResponse(response);
+// switch (requestData.method) {
+// case "analysis.getErrors":
+// break;
+// case "analysis.getHover":
+// break;
+// case "analysis.getLibraryDependencies":
+// break;
+// case "analysis.getNavigation":
+// break;
+// case "analysis.getReachableSources":
+// break;
+// case "analysis.reanalyze":
+// break;
+// case "analysis.setAnalysisRoots":
+// break;
+// case "analysis.setGeneralSubscriptions":
+// break;
+// case "analysis.setPriorityFiles":
+// break;
+// case "analysis.setSubscriptions":
+// break;
+// case 'analysis.updateContent':
+// break;
+// case "analysis.updateOptions":
+// break;
+// case "completion.getSuggestions":
+// break;
+// case "diagnostic.getDiagnostics":
+// break;
+// case "edit.format":
+// break;
+// case "edit.getAssists":
+// break;
+// case "edit.getAvailableRefactorings":
+// break;
+// case "edit.getFixes":
+// break;
+// case "edit.getRefactoring":
+// break;
+// case "edit.organizeDirectives":
+// break;
+// case "edit.sortMembers":
+// break;
+// case "execution.createContext":
+// break;
+// case "execution.deleteContext":
+// break;
+// case "execution.mapUri":
+// break;
+// case "execution.setSubscriptions":
+// break;
+// case "search.findElementReferences":
+// break;
+// case "search.findMemberDeclarations":
+// break;
+// case "search.findMemberReferences":
+// break;
+// case "search.findTopLevelDeclarations":
+// break;
+// case "search.getTypeHierarchy":
+// break;
+// case "server.getVersion":
+// break;
+// case "server.setSubscriptions":
+// break;
+// case "server.shutdown":
+// break;
+// default:
+// throw new StateError('Unhandled response: ${response.toJson()}');
+// }
+ }
+
+ /**
+ * Handle a [line] of input read from stderr.
+ */
+ void _handleStdErr(String line) {
+ String trimmedLine = line.trim();
+ logger?.log(fromStderr, '$trimmedLine');
+ throw new StateError('Message received on stderr: "$trimmedLine"');
+ }
+
+ /**
+ * Handle a [line] of input read from stdout.
+ */
+ void _handleStdOut(String line) {
+ /**
+ * Cast the given [value] to a Map, or throw an [ArgumentError] if the value
+ * cannot be cast.
+ */
+ Map asMap(Object value) {
+ if (value is Map) {
+ return value;
+ }
+ throw new ArgumentError('Expected a Map, found a ${value.runtimeType}');
+ }
+
+ String trimmedLine = line.trim();
+ if (trimmedLine.isEmpty ||
+ trimmedLine.startsWith('Observatory listening on ')) {
+ return;
+ }
+ logger?.log(fromServer, '$trimmedLine');
+ Map message = asMap(JSON.decoder.convert(trimmedLine));
+ if (message.containsKey('id')) {
+ // The message is a response.
+ Response response = new Response.fromJson(message);
+ _handleResponse(response);
+ } else {
+ // The message is a notification.
+ Notification notification = new Notification.fromJson(message);
+ String event = notification.event;
+ _notificationCountMap[event] = (_notificationCountMap[event] ?? 0) + 1;
+ _handleNotification(notification);
+ }
+ }
+
+ /**
+ * Start listening to output from the server.
+ */
+ void _listenToOutput() {
+ /**
+ * Install the given [handler] to listen to transformed output from the
+ * given [stream].
+ */
+ void installHandler(Stream<List<int>> stream, handler(String line)) {
+ stream
+ .transform((new Utf8Codec()).decoder)
+ .transform(new LineSplitter())
+ .listen(handler);
+ }
+
+ installHandler(_process.stdout, _handleStdOut);
+ installHandler(_process.stderr, _handleStdErr);
+ }
+
+ /**
+ * Send a command to the server. An 'id' will be automatically assigned.
+ */
+ RequestData _send(String method, Map<String, dynamic> params,
+ {void onResponse(Response response)}) {
+ String id = '${_nextId++}';
+ RequestData requestData = new RequestData(id, method, params, currentTime);
+ _requestDataMap[id] = requestData;
+ Map<String, dynamic> command = <String, dynamic>{
+ 'id': id,
+ 'method': method
+ };
+ if (params != null) {
+ command['params'] = params;
+ }
+ String line = JSON.encode(command);
+ _process.stdin.add(UTF8.encoder.convert('$line\n'));
+ logger?.log(fromClient, '$line');
+ return requestData;
}
}
@@ -284,6 +1094,6 @@ class _ErrorComparator {
buffer.writeln(filePath);
_writeErrors(' Expected ', expectedErrors);
buffer.writeln();
- _writeErrors(' Found ', expectedErrors);
+ _writeErrors(' Found ', actualErrors);
}
}
« 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