| 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 |