| Index: pkg/analysis_server/test/performance/operation.dart
|
| diff --git a/pkg/analysis_server/test/performance/operation.dart b/pkg/analysis_server/test/performance/operation.dart
|
| index 595225244b636982102ef20653b7c51a78d24838..641cf31544b1343a1278e665930c33e90ff1f957 100644
|
| --- a/pkg/analysis_server/test/performance/operation.dart
|
| +++ b/pkg/analysis_server/test/performance/operation.dart
|
| @@ -13,6 +13,53 @@ import 'driver.dart';
|
| import 'input_converter.dart';
|
|
|
| /**
|
| + * A [CompletionRequestOperation] tracks response time along with
|
| + * the first and last completion notifications.
|
| + */
|
| +class CompletionRequestOperation extends RequestOperation {
|
| + Driver driver;
|
| + StreamSubscription<CompletionResultsParams> subscription;
|
| + String notificationId;
|
| + Stopwatch stopwatch;
|
| + bool firstNotification = true;
|
| +
|
| + CompletionRequestOperation(
|
| + CommonInputConverter converter, Map<String, dynamic> json)
|
| + : super(converter, json);
|
| +
|
| + @override
|
| + Future perform(Driver driver) {
|
| + this.driver = driver;
|
| + subscription = driver.onCompletionResults.listen(processNotification);
|
| + return super.perform(driver);
|
| + }
|
| +
|
| + void processNotification(CompletionResultsParams event) {
|
| + if (event.id == notificationId) {
|
| + Duration elapsed = stopwatch.elapsed;
|
| + if (firstNotification) {
|
| + firstNotification = false;
|
| + driver.results.record('completion notification first', elapsed,
|
| + notification: true);
|
| + }
|
| + if (event.isLast) {
|
| + subscription.cancel();
|
| + driver.results.record('completion notification last', elapsed,
|
| + notification: true);
|
| + }
|
| + }
|
| + }
|
| +
|
| + @override
|
| + void processResult(
|
| + String id, Map<String, dynamic> result, Stopwatch stopwatch) {
|
| + notificationId = result['id'];
|
| + this.stopwatch = stopwatch;
|
| + super.processResult(id, result, stopwatch);
|
| + }
|
| +}
|
| +
|
| +/**
|
| * An [Operation] represents an action such as sending a request to the server.
|
| */
|
| abstract class Operation {
|
| @@ -31,24 +78,103 @@ class RequestOperation extends Operation {
|
| @override
|
| Future perform(Driver driver) {
|
| Stopwatch stopwatch = new Stopwatch();
|
| + String originalId = json['id'];
|
| String method = json['method'];
|
| driver.logger.log(Level.FINE, 'Sending request: $method\n $json');
|
| stopwatch.start();
|
| - void recordResponse(bool success, response) {
|
| - stopwatch.stop();
|
| +
|
| + void recordResult(bool success, result) {
|
| Duration elapsed = stopwatch.elapsed;
|
| driver.results.record(method, elapsed, success: success);
|
| driver.logger.log(
|
| - Level.FINE, 'Response received: $method : $elapsed\n $response');
|
| + Level.FINE, 'Response received: $method : $elapsed\n $result');
|
| }
|
| - driver.send(method, json['params']).then((response) {
|
| - recordResponse(true, response);
|
| - }).catchError((e, s) {
|
| - recordResponse(false, e);
|
| - converter.recordErrorResponse(json, e);
|
| +
|
| + driver.send(method, json['params']).then((Map<String, dynamic> result) {
|
| + recordResult(true, result);
|
| + processResult(originalId, result, stopwatch);
|
| + }).catchError((exception) {
|
| + recordResult(false, exception);
|
| + converter.processErrorResponse(originalId, exception);
|
| });
|
| return null;
|
| }
|
| +
|
| + void processResult(
|
| + String id, Map<String, dynamic> result, Stopwatch stopwatch) {
|
| + converter.processResponseResult(id, result);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A [ResponseOperation] waits for a [JSON] response from the server.
|
| + */
|
| +class ResponseOperation extends Operation {
|
| + static final Duration responseTimeout = new Duration(seconds: 5);
|
| + final CommonInputConverter converter;
|
| + final Map<String, dynamic> requestJson;
|
| + final Map<String, dynamic> responseJson;
|
| + final Completer completer = new Completer();
|
| + Driver driver;
|
| +
|
| + ResponseOperation(this.converter, this.requestJson, this.responseJson) {
|
| + completer.future.then(_processResult).timeout(responseTimeout);
|
| + }
|
| +
|
| + @override
|
| + Future perform(Driver driver) {
|
| + this.driver = driver;
|
| + return converter.processExpectedResponse(responseJson['id'], completer);
|
| + }
|
| +
|
| + bool _equal(expectedResult, actualResult) {
|
| + if (expectedResult is Map && actualResult is Map) {
|
| + if (expectedResult.length == actualResult.length) {
|
| + return expectedResult.keys.every((String key) {
|
| + return key ==
|
| + 'fileStamp' || // fileStamp values will not be the same across runs
|
| + _equal(expectedResult[key], actualResult[key]);
|
| + });
|
| + }
|
| + } else if (expectedResult is List && actualResult is List) {
|
| + if (expectedResult.length == actualResult.length) {
|
| + for (int i = 0; i < expectedResult.length; ++i) {
|
| + if (!_equal(expectedResult[i], actualResult[i])) {
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| + }
|
| + return expectedResult == actualResult;
|
| + }
|
| +
|
| + /**
|
| + * Compare the expected and actual server response result.
|
| + */
|
| + void _processResult(actualResult) {
|
| + var expectedResult = responseJson['result'];
|
| + if (!_equal(expectedResult, actualResult)) {
|
| + var expectedError = responseJson['error'];
|
| + String format(value) {
|
| + String text = '\n$value';
|
| + if (text.endsWith('\n')) {
|
| + text = text.substring(0, text.length - 1);
|
| + }
|
| + return text.replaceAll('\n', '\n ');
|
| + }
|
| + String message = 'Request:${format(requestJson)}\n'
|
| + 'expected result:${format(expectedResult)}\n'
|
| + 'expected error:${format(expectedError)}\n'
|
| + 'but received:${format(actualResult)}';
|
| + driver.results.recordUnexpectedResults(requestJson['method']);
|
| + if (expectedError == null) {
|
| + converter.logger.log(Level.SEVERE, message);
|
| + } else {
|
| + throw message;
|
| + }
|
| + }
|
| + }
|
| }
|
|
|
| class StartServerOperation extends Operation {
|
| @@ -79,7 +205,7 @@ class WaitForAnalysisCompleteOperation extends Operation {
|
| Duration delta = end.difference(start);
|
| driver.logger.log(Level.FINE, 'analysis complete after $delta');
|
| completer.complete();
|
| - driver.results.record('analysis complete', delta);
|
| + driver.results.record('analysis complete', delta, notification: true);
|
| }
|
| }
|
| });
|
|
|