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

Side by Side Diff: lib/src/runner/browser/browser_manager.dart

Issue 1206033004: Only load a certain number of test suites at once. (Closed) Base URL: git@github.com:dart-lang/test@master
Patch Set: Created 5 years, 6 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
OLDNEW
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.browser_manager; 5 library test.runner.browser.browser_manager;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:convert'; 8 import 'dart:convert';
9 9
10 import 'package:http_parser/http_parser.dart'; 10 import 'package:http_parser/http_parser.dart';
(...skipping 24 matching lines...) Expand all
35 35
36 /// A pool that ensures that limits the number of initial connections the 36 /// A pool that ensures that limits the number of initial connections the
37 /// manager will wait for at once. 37 /// manager will wait for at once.
38 /// 38 ///
39 /// This isn't the *total* number of connections; any number of iframes may be 39 /// This isn't the *total* number of connections; any number of iframes may be
40 /// loaded in the same browser. However, the browser can only load so many at 40 /// loaded in the same browser. However, the browser can only load so many at
41 /// once, and we want a timeout in case they fail so we only wait for so many 41 /// once, and we want a timeout in case they fail so we only wait for so many
42 /// at once. 42 /// at once.
43 final _pool = new Pool(8); 43 final _pool = new Pool(8);
44 44
45 /// The ID of the next suite to be loaded.
46 ///
47 /// This is used to ensure that the suites can be referred to consistently
48 /// across the client and server.
49 int _suiteId = 0;
50
45 /// Creates a new BrowserManager that communicates with [browser] over 51 /// Creates a new BrowserManager that communicates with [browser] over
46 /// [webSocket]. 52 /// [webSocket].
47 BrowserManager(this.browser, CompatibleWebSocket webSocket) 53 BrowserManager(this.browser, CompatibleWebSocket webSocket)
48 : _channel = new MultiChannel( 54 : _channel = new MultiChannel(
49 webSocket.map(JSON.decode), 55 webSocket.map(JSON.decode),
50 mapSink(webSocket, JSON.encode)); 56 mapSink(webSocket, JSON.encode));
51 57
52 /// Tells the browser the load a test suite from the URL [url]. 58 /// Tells the browser the load a test suite from the URL [url].
53 /// 59 ///
54 /// [url] should be an HTML page with a reference to the JS-compiled test 60 /// [url] should be an HTML page with a reference to the JS-compiled test
55 /// suite. [path] is the path of the original test suite file, which is used 61 /// suite. [path] is the path of the original test suite file, which is used
56 /// for reporting. [metadata] is the parsed metadata for the test suite. 62 /// for reporting. [metadata] is the parsed metadata for the test suite.
57 /// 63 ///
58 /// If [mapper] is passed, it's used to map stack traces for errors coming 64 /// If [mapper] is passed, it's used to map stack traces for errors coming
59 /// from this test suite. 65 /// from this test suite.
60 Future<Suite> loadSuite(String path, Uri url, Metadata metadata, 66 Future<Suite> loadSuite(String path, Uri url, Metadata metadata,
61 {StackTraceMapper mapper}) async { 67 {StackTraceMapper mapper}) async {
62 url = url.replace(fragment: Uri.encodeFull(JSON.encode({ 68 url = url.replace(fragment: Uri.encodeFull(JSON.encode({
63 "metadata": metadata.serialize(), 69 "metadata": metadata.serialize(),
64 "browser": browser.identifier 70 "browser": browser.identifier
65 }))); 71 })));
66 72
67 // The stream may close before emitting a value if the browser is killed 73 // The stream may close before emitting a value if the browser is killed
68 // prematurely (e.g. via Control-C). 74 // prematurely (e.g. via Control-C).
69 var suiteChannel = _channel.virtualChannel(); 75 var suiteVirtualChannel = _channel.virtualChannel();
76 var suiteId = _suiteId++;
77 var suiteChannel;
78
79 closeIframe() {
80 suiteChannel.sink.close();
81 _channel.sink.add({
82 "command": "closeSuite",
83 "id": suiteId
84 });
85 }
86
70 var response = await _pool.withResource(() { 87 var response = await _pool.withResource(() {
71 _channel.sink.add({ 88 _channel.sink.add({
72 "command": "loadSuite", 89 "command": "loadSuite",
73 "url": url.toString(), 90 "url": url.toString(),
74 "channel": suiteChannel.id 91 "id": _suiteId++,
92 "channel": suiteVirtualChannel.id
75 }); 93 });
76 94
77 // Create a nested MultiChannel because the iframe will be using a channel 95 // Create a nested MultiChannel because the iframe will be using a channel
78 // wrapped within the host's channel. 96 // wrapped within the host's channel.
79 suiteChannel = new MultiChannel(suiteChannel.stream, suiteChannel.sink); 97 suiteChannel = new MultiChannel(
98 suiteVirtualChannel.stream, suiteVirtualChannel.sink);
80 99
81 var completer = new Completer(); 100 var completer = new Completer();
82 suiteChannel.stream.listen((response) { 101 suiteChannel.stream.listen((response) {
83 if (response["type"] == "print") { 102 if (response["type"] == "print") {
84 print(response["line"]); 103 print(response["line"]);
85 } else { 104 } else {
86 completer.complete(response); 105 completer.complete(response);
87 } 106 }
88 }, onDone: () { 107 }, onDone: () {
89 if (!completer.isCompleted) completer.complete(); 108 if (!completer.isCompleted) completer.complete();
90 }); 109 });
91 110
92 return completer.future.timeout(new Duration(seconds: 15), onTimeout: () { 111 return completer.future.timeout(new Duration(seconds: 15), onTimeout: () {
93 throw new LoadException( 112 throw new LoadException(
94 path, 113 path,
95 "Timed out waiting for the test suite to connect on " 114 "Timed out waiting for the test suite to connect on "
96 "${browser.name}."); 115 "${browser.name}.");
97 }); 116 });
98 }); 117 });
99 118
100 if (response == null) return null; 119 if (response == null) {
120 closeIframe();
121 return null;
122 }
101 123
102 if (response["type"] == "loadException") { 124 if (response["type"] == "loadException") {
125 closeIframe();
103 throw new LoadException(path, response["message"]); 126 throw new LoadException(path, response["message"]);
104 } 127 }
105 128
106 if (response["type"] == "error") { 129 if (response["type"] == "error") {
130 closeIframe();
107 var asyncError = RemoteException.deserialize(response["error"]); 131 var asyncError = RemoteException.deserialize(response["error"]);
108 await new Future.error( 132 await new Future.error(
109 new LoadException(path, asyncError.error), 133 new LoadException(path, asyncError.error),
110 asyncError.stackTrace); 134 asyncError.stackTrace);
111 } 135 }
112 136
113 return new Suite(response["tests"].map((test) { 137 return new Suite(response["tests"].map((test) {
114 var testMetadata = new Metadata.deserialize(test['metadata']); 138 var testMetadata = new Metadata.deserialize(test['metadata']);
115 var testChannel = suiteChannel.virtualChannel(test['channel']); 139 var testChannel = suiteChannel.virtualChannel(test['channel']);
116 return new IframeTest(test['name'], testMetadata, testChannel, 140 return new IframeTest(test['name'], testMetadata, testChannel,
117 mapper: mapper); 141 mapper: mapper);
118 }), metadata: metadata, path: path); 142 }), metadata: metadata, path: path, onClose: () => closeIframe());
119 } 143 }
120 } 144 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698