OLD | NEW |
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 library test.runner.browser.dartium; | 5 library test.runner.browser.dartium; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 | 10 |
11 import 'package:async/async.dart'; | 11 import 'package:async/async.dart'; |
12 import 'package:path/path.dart' as p; | 12 import 'package:path/path.dart' as p; |
13 | 13 |
14 import '../../util/cancelable_future.dart'; | |
15 import '../../util/io.dart'; | 14 import '../../util/io.dart'; |
16 import '../../utils.dart'; | 15 import '../../utils.dart'; |
17 import 'browser.dart'; | 16 import 'browser.dart'; |
18 | 17 |
19 final _observatoryRegExp = new RegExp(r"^Observatory listening on ([^ ]+)"); | 18 final _observatoryRegExp = new RegExp(r"^Observatory listening on ([^ ]+)"); |
20 | 19 |
21 /// A class for running an instance of Dartium. | 20 /// A class for running an instance of Dartium. |
22 /// | 21 /// |
23 /// Most of the communication with the browser is expected to happen via HTTP, | 22 /// Most of the communication with the browser is expected to happen via HTTP, |
24 /// so this exposes a bare-bones API. The browser starts as soon as the class is | 23 /// so this exposes a bare-bones API. The browser starts as soon as the class is |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 /// ordering isn't guaranteed, so we need to figure out which one is correct. | 113 /// ordering isn't guaranteed, so we need to figure out which one is correct. |
115 /// We do so by connecting to the VM service via WebSockets and looking for | 114 /// We do so by connecting to the VM service via WebSockets and looking for |
116 /// the Observatory instance that actually contains an isolate, and returning | 115 /// the Observatory instance that actually contains an isolate, and returning |
117 /// the corresponding URI. | 116 /// the corresponding URI. |
118 static Future<Uri> _getObservatoryUrl(Stream<List<int>> stdout) async { | 117 static Future<Uri> _getObservatoryUrl(Stream<List<int>> stdout) async { |
119 var urlQueue = new StreamQueue(lineSplitter.bind(stdout).map((line) { | 118 var urlQueue = new StreamQueue(lineSplitter.bind(stdout).map((line) { |
120 var match = _observatoryRegExp.firstMatch(line); | 119 var match = _observatoryRegExp.firstMatch(line); |
121 return match == null ? null : Uri.parse(match[1]); | 120 return match == null ? null : Uri.parse(match[1]); |
122 }).where((line) => line != null)); | 121 }).where((line) => line != null)); |
123 | 122 |
124 var futures = [ | 123 var operations = [ |
125 urlQueue.next, | 124 urlQueue.next, |
126 urlQueue.next, | 125 urlQueue.next, |
127 urlQueue.next | 126 urlQueue.next |
128 ].map(_checkObservatoryUrl); | 127 ].map(_checkObservatoryUrl); |
129 | 128 |
130 urlQueue.cancel(); | 129 urlQueue.cancel(); |
131 | 130 |
132 /// Dartium will print three possible observatory URLs. For each one, we | 131 /// Dartium will print three possible observatory URLs. For each one, we |
133 /// check whether it's actually connected to an isolate, indicating that | 132 /// check whether it's actually connected to an isolate, indicating that |
134 /// it's the observatory for the main page. Once we find the one that is, we | 133 /// it's the observatory for the main page. Once we find the one that is, we |
135 /// cancel the other requests and return it. | 134 /// cancel the other requests and return it. |
136 return inCompletionOrder(futures) | 135 return inCompletionOrder(operations) |
137 .firstWhere((url) => url != null, defaultValue: () => null); | 136 .firstWhere((url) => url != null, defaultValue: () => null); |
138 } | 137 } |
139 | 138 |
140 /// If the URL returned by [future] corresponds to the correct Observatory | 139 /// If the URL returned by [future] corresponds to the correct Observatory |
141 /// instance, returns it. Otherwise, returns `null`. | 140 /// instance, returns it. Otherwise, returns `null`. |
142 /// | 141 /// |
143 /// If the returned future is canceled before it fires, the WebSocket | 142 /// If the returned operation is canceled before it fires, the WebSocket |
144 /// connection with the given Observatory will be closed immediately. | 143 /// connection with the given Observatory will be closed immediately. |
145 static CancelableFuture<Uri> _checkObservatoryUrl(Future<Uri> future) { | 144 static CancelableOperation<Uri> _checkObservatoryUrl(Future<Uri> future) { |
146 var webSocket; | 145 var webSocket; |
147 var canceled = false; | 146 var canceled = false; |
148 var completer = new CancelableCompleter(() { | 147 var completer = new CancelableCompleter(onCancel: () { |
149 canceled = true; | 148 canceled = true; |
150 if (webSocket != null) webSocket.close(); | 149 if (webSocket != null) webSocket.close(); |
151 }); | 150 }); |
152 | 151 |
153 // We've encountered a format we don't understand. Close the web socket and | 152 // We've encountered a format we don't understand. Close the web socket and |
154 // complete to null. | 153 // complete to null. |
155 giveUp() { | 154 giveUp() { |
156 webSocket.close(); | 155 webSocket.close(); |
157 if (!completer.isCompleted) completer.complete(); | 156 if (!completer.isCompleted) completer.complete(); |
158 } | 157 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 }); | 240 }); |
242 } on IOException catch (_) { | 241 } on IOException catch (_) { |
243 // IO exceptions are probably caused by connecting to an | 242 // IO exceptions are probably caused by connecting to an |
244 // incorrect WebSocket that already closed. | 243 // incorrect WebSocket that already closed. |
245 return null; | 244 return null; |
246 } | 245 } |
247 }).catchError((error, stackTrace) { | 246 }).catchError((error, stackTrace) { |
248 if (!completer.isCompleted) completer.completeError(error, stackTrace); | 247 if (!completer.isCompleted) completer.completeError(error, stackTrace); |
249 }); | 248 }); |
250 | 249 |
251 return completer.future; | 250 return completer.operation; |
252 } | 251 } |
253 } | 252 } |
OLD | NEW |