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

Side by Side Diff: pkg/analysis_server/test/integration/integration_tests.dart

Issue 453603003: Code generate integration test streams for notifications. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 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 | Annotate | Revision Log
OLDNEW
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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 * Data associated with the "server.connected" notification that was received 53 * Data associated with the "server.connected" notification that was received
54 * when the server started up. 54 * when the server started up.
55 */ 55 */
56 var serverConnectedParams; 56 var serverConnectedParams;
57 57
58 /** 58 /**
59 * True if we are currently subscribed to [SERVER_STATUS] updates. 59 * True if we are currently subscribed to [SERVER_STATUS] updates.
60 */ 60 */
61 bool _subscribedToServerStatus = false; 61 bool _subscribedToServerStatus = false;
62 62
63 AbstractAnalysisServerIntegrationTest() {
64 initializeInttestMixin();
65 }
66
63 /** 67 /**
64 * Write a source file with the given absolute [pathname] and [contents]. 68 * Write a source file with the given absolute [pathname] and [contents].
65 * 69 *
66 * If the file didn't previously exist, it is created. If it did, it is 70 * If the file didn't previously exist, it is created. If it did, it is
67 * overwritten. 71 * overwritten.
68 * 72 *
69 * Parent directories are created as necessary. 73 * Parent directories are created as necessary.
70 */ 74 */
71 void writeFile(String pathname, String contents) { 75 void writeFile(String pathname, String contents) {
72 new Directory(dirname(pathname)).createSync(recursive: true); 76 new Directory(dirname(pathname)).createSync(recursive: true);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 * received after this function call. So it is safe to use this getter 109 * 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 110 * multiple times in one test; each time it is used it will wait afresh for
107 * analysis to finish. 111 * analysis to finish.
108 */ 112 */
109 Future get analysisFinished { 113 Future get analysisFinished {
110 Completer completer = new Completer(); 114 Completer completer = new Completer();
111 StreamSubscription subscription; 115 StreamSubscription subscription;
112 // This will only work if the caller has already subscribed to 116 // This will only work if the caller has already subscribed to
113 // SERVER_STATUS (e.g. using sendServerSetSubscriptions(['STATUS'])) 117 // SERVER_STATUS (e.g. using sendServerSetSubscriptions(['STATUS']))
114 expect(_subscribedToServerStatus, isTrue); 118 expect(_subscribedToServerStatus, isTrue);
115 subscription = server.onNotification(SERVER_STATUS).listen((params) { 119 subscription = onServerStatus.listen((params) {
116 bool analysisComplete = false; 120 bool analysisComplete = false;
117 try { 121 try {
118 analysisComplete = !params['analysis']['analyzing']; 122 analysisComplete = !params['analysis']['analyzing'];
119 } catch (_) { 123 } catch (_) {
120 // Status message was mal-formed or missing optional parameters. That's 124 // Status message was mal-formed or missing optional parameters. That's
121 // fine, since we'll detect a mal-formed status message below. 125 // fine, since we'll detect a mal-formed status message below.
122 } 126 }
123 if (analysisComplete) { 127 if (analysisComplete) {
124 completer.complete(params); 128 completer.complete(params);
125 subscription.cancel(); 129 subscription.cancel();
(...skipping 19 matching lines...) Expand all
145 checkTypes); 149 checkTypes);
146 } 150 }
147 151
148 /** 152 /**
149 * The server is automatically started before every test, and a temporary 153 * The server is automatically started before every test, and a temporary
150 * [sourceDirectory] is created. 154 * [sourceDirectory] is created.
151 */ 155 */
152 Future setUp() { 156 Future setUp() {
153 sourceDirectory = Directory.systemTemp.createTempSync('analysisServer'); 157 sourceDirectory = Directory.systemTemp.createTempSync('analysisServer');
154 158
155 server.onNotification(ANALYSIS_ERRORS).listen((params) { 159 onAnalysisErrors.listen((params) {
156 expect(params, isMap);
157 expect(params['file'], isString);
158 currentAnalysisErrors[params['file']] = params['errors']; 160 currentAnalysisErrors[params['file']] = params['errors'];
159 }); 161 });
160 Completer serverConnected = new Completer(); 162 Completer serverConnected = new Completer();
161 server.onNotification(SERVER_CONNECTED).listen((_) { 163 onServerConnected.listen((_) {
162 expect(serverConnected.isCompleted, isFalse); 164 expect(serverConnected.isCompleted, isFalse);
163 serverConnected.complete(); 165 serverConnected.complete();
164 }); 166 });
165 return server.start().then((params) { 167 return server.start(dispatchNotification).then((params) {
166 serverConnectedParams = params; 168 serverConnectedParams = params;
167 server.exitCode.then((_) { 169 server.exitCode.then((_) {
168 skipShutdown = true; 170 skipShutdown = true;
169 }); 171 });
170 return serverConnected.future; 172 return serverConnected.future;
171 }); 173 });
172 } 174 }
173 175
174 /** 176 /**
175 * After every test, the server is stopped and [sourceDirectory] is deleted. 177 * After every test, the server is stopped and [sourceDirectory] is deleted.
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 487
486 @override 488 @override
487 Description describe(Description description) => description.add('Map from ' 489 Description describe(Description description) => description.add('Map from '
488 ).addDescriptionOf(keyMatcher).add(' to ').addDescriptionOf(valueMatcher); 490 ).addDescriptionOf(keyMatcher).add(' to ').addDescriptionOf(valueMatcher);
489 } 491 }
490 492
491 Matcher isMapOf(Matcher keyMatcher, Matcher valueMatcher) => new _MapOf( 493 Matcher isMapOf(Matcher keyMatcher, Matcher valueMatcher) => new _MapOf(
492 keyMatcher, valueMatcher); 494 keyMatcher, valueMatcher);
493 495
494 /** 496 /**
497 * Type of callbacks used to process notifications.
498 */
499 typedef void NotificationProcessor(String event, params);
500
501 /**
495 * Instances of the class [Server] manage a connection to a server process, and 502 * Instances of the class [Server] manage a connection to a server process, and
496 * facilitate communication to and from the server. 503 * facilitate communication to and from the server.
497 */ 504 */
498 class Server { 505 class Server {
499 /** 506 /**
500 * Server process object, or null if server hasn't been started yet. 507 * Server process object, or null if server hasn't been started yet.
501 */ 508 */
502 Process _process = null; 509 Process _process = null;
503 510
504 /** 511 /**
505 * Commands that have been sent to the server but not yet acknowledged, and 512 * Commands that have been sent to the server but not yet acknowledged, and
506 * the [Completer] objects which should be completed when acknowledgement is 513 * the [Completer] objects which should be completed when acknowledgement is
507 * received. 514 * received.
508 */ 515 */
509 final HashMap<String, Completer> _pendingCommands = <String, Completer> {}; 516 final HashMap<String, Completer> _pendingCommands = <String, Completer> {};
510 517
511 /** 518 /**
512 * Number which should be used to compute the 'id' to send in the next command 519 * Number which should be used to compute the 'id' to send in the next command
513 * sent to the server. 520 * sent to the server.
514 */ 521 */
515 int _nextId = 0; 522 int _nextId = 0;
516 523
517 /** 524 /**
518 * [StreamController]s to which notifications should be sent, organized by 525 * [StreamController] to which notifications will be sent.
519 * event type.
520 */ 526 */
521 final HashMap<String, StreamController> _notificationControllers = 527 final StreamController _notifications = new StreamController();
522 new HashMap<String, StreamController>();
523
524 /**
525 * [Stream]s associated with the controllers in [_notificationControllers],
526 * but converted to broadcast streams.
527 */
528 final HashMap<String, Stream> _notificationStreams = new HashMap<String,
529 Stream>();
530 528
531 /** 529 /**
532 * Messages which have been exchanged with the server; we buffer these 530 * Messages which have been exchanged with the server; we buffer these
533 * up until the test finishes, so that they can be examined in the debugger 531 * up until the test finishes, so that they can be examined in the debugger
534 * or printed out in response to a call to [debugStdio]. 532 * or printed out in response to a call to [debugStdio].
535 */ 533 */
536 final List<String> _recordedStdio = <String>[]; 534 final List<String> _recordedStdio = <String>[];
537 535
538 /** 536 /**
539 * True if we are currently printing out messages exchanged with the server. 537 * True if we are currently printing out messages exchanged with the server.
540 */ 538 */
541 bool _debuggingStdio = false; 539 bool _debuggingStdio = false;
542 540
543 /** 541 /**
544 * True if we've received bad data from the server, and we are aborting the 542 * True if we've received bad data from the server, and we are aborting the
545 * test. 543 * test.
546 */ 544 */
547 bool _receivedBadDataFromServer = false; 545 bool _receivedBadDataFromServer = false;
548 546
549 /** 547 /**
550 * Stopwatch that we use to generate timing information for debug output. 548 * Stopwatch that we use to generate timing information for debug output.
551 */ 549 */
552 Stopwatch _time = new Stopwatch(); 550 Stopwatch _time = new Stopwatch();
553 551
554 /** 552 /**
555 * Get a stream which will receive notifications of the given event type.
556 * The values delivered to the stream will be the contents of the 'params'
557 * field of the notification message.
558 */
559 Stream onNotification(String event) {
560 Stream notificationStream = _notificationStreams[event];
561 if (notificationStream == null) {
562 StreamController notificationController = new StreamController();
563 _notificationControllers[event] = notificationController;
564 notificationStream = notificationController.stream.asBroadcastStream();
565 _notificationStreams[event] = notificationStream;
566 }
567 return notificationStream;
568 }
569
570 /**
571 * Start the server. If [debugServer] is true, the server will be started 553 * Start the server. If [debugServer] is true, the server will be started
572 * with "--debug", allowing a debugger to be attached. 554 * with "--debug", allowing a debugger to be attached.
573 */ 555 */
574 Future start({bool debugServer: false}) { 556 Future start(NotificationProcessor notificationProcessor, {bool debugServer:
557 false}) {
575 if (_process != null) { 558 if (_process != null) {
576 throw new Exception('Process already started'); 559 throw new Exception('Process already started');
577 } 560 }
578 _time.start(); 561 _time.start();
579 // TODO(paulberry): move the logic for finding the script, the dart 562 // TODO(paulberry): move the logic for finding the script, the dart
580 // executable, and the package root into a shell script. 563 // executable, and the package root into a shell script.
581 String dartBinary = Platform.executable; 564 String dartBinary = Platform.executable;
582 String scriptDir = dirname(Platform.script.toFilePath(windows: 565 String scriptDir = dirname(Platform.script.toFilePath(windows:
583 Platform.isWindows)); 566 Platform.isWindows));
584 String serverPath = normalize(join(scriptDir, '..', '..', 'bin', 567 String serverPath = normalize(join(scriptDir, '..', '..', 'bin',
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 } 608 }
626 // Check that the message is well-formed. We do this after calling 609 // Check that the message is well-formed. We do this after calling
627 // completer.complete() or completer.completeError() so that we don't 610 // completer.complete() or completer.completeError() so that we don't
628 // stall the test in the event of an error. 611 // stall the test in the event of an error.
629 expect(message, isResponse); 612 expect(message, isResponse);
630 } else { 613 } else {
631 // Message is a notification. It should have an event and possibly 614 // Message is a notification. It should have an event and possibly
632 // params. 615 // params.
633 expect(messageAsMap, contains('event')); 616 expect(messageAsMap, contains('event'));
634 expect(messageAsMap['event'], isString); 617 expect(messageAsMap['event'], isString);
635 String event = messageAsMap['event']; 618 notificationProcessor(messageAsMap['event'], messageAsMap['params']);
636 StreamController notificationController =
637 _notificationControllers[event];
638 if (notificationController != null) {
639 notificationController.add(messageAsMap['params']);
640 }
641 // Check that the message is well-formed. We do this after calling 619 // Check that the message is well-formed. We do this after calling
642 // notificationController.add() so that we don't stall the test in the 620 // notificationController.add() so that we don't stall the test in the
643 // event of an error. 621 // event of an error.
644 expect(message, isNotification); 622 expect(message, isNotification);
645 } 623 }
646 }); 624 });
647 process.stderr.transform((new Utf8Codec()).decoder).transform( 625 process.stderr.transform((new Utf8Codec()).decoder).transform(
648 new LineSplitter()).listen((String line) { 626 new LineSplitter()).listen((String line) {
649 String trimmedLine = line.trim(); 627 String trimmedLine = line.trim();
650 _recordStdio('ERR: $trimmedLine'); 628 _recordStdio('ERR: $trimmedLine');
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 */ 717 */
740 void _recordStdio(String line) { 718 void _recordStdio(String line) {
741 double elapsedTime = _time.elapsedTicks / _time.frequency; 719 double elapsedTime = _time.elapsedTicks / _time.frequency;
742 line = "$elapsedTime: $line"; 720 line = "$elapsedTime: $line";
743 if (_debuggingStdio) { 721 if (_debuggingStdio) {
744 print(line); 722 print(line);
745 } 723 }
746 _recordedStdio.add(line); 724 _recordedStdio.add(line);
747 } 725 }
748 } 726 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698