| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library browser; | 4 library browser; |
| 5 | 5 |
| 6 import "dart:async"; | 6 import "dart:async"; |
| 7 import "dart:convert" show UTF8, JSON; | 7 import "dart:convert" show UTF8, JSON; |
| 8 import "dart:core"; | 8 import "dart:core"; |
| 9 import "dart:io"; | 9 import "dart:io"; |
| 10 import "dart:math" show min; | 10 import "dart:math" show min; |
| 11 | 11 |
| 12 import 'android.dart'; | 12 import 'android.dart'; |
| 13 import 'http_server.dart'; | 13 import 'http_server.dart'; |
| 14 import 'path.dart'; | 14 import 'path.dart'; |
| 15 import 'utils.dart'; | 15 import 'utils.dart'; |
| 16 | 16 |
| 17 import 'reset_safari.dart' show killAndResetSafari; | 17 import 'reset_safari.dart' show killAndResetSafari; |
| 18 | 18 |
| 19 typedef void BrowserDoneCallback(BrowserTestOutput output); |
| 20 typedef void TestChangedCallback(String browserId, String output, int testId); |
| 21 typedef BrowserTest NextTestCallback(String browserId); |
| 22 |
| 19 class BrowserOutput { | 23 class BrowserOutput { |
| 20 final StringBuffer stdout = new StringBuffer(); | 24 final StringBuffer stdout = new StringBuffer(); |
| 21 final StringBuffer stderr = new StringBuffer(); | 25 final StringBuffer stderr = new StringBuffer(); |
| 22 final StringBuffer eventLog = new StringBuffer(); | 26 final StringBuffer eventLog = new StringBuffer(); |
| 23 } | 27 } |
| 24 | 28 |
| 25 /** Class describing the interface for communicating with browsers. */ | 29 /** Class describing the interface for communicating with browsers. */ |
| 26 abstract class Browser { | 30 abstract class Browser { |
| 27 BrowserOutput _allBrowserOutput = new BrowserOutput(); | 31 BrowserOutput _allBrowserOutput = new BrowserOutput(); |
| 28 BrowserOutput _testBrowserOutput = new BrowserOutput(); | 32 BrowserOutput _testBrowserOutput = new BrowserOutput(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 bool debugPrint = false; | 68 bool debugPrint = false; |
| 65 | 69 |
| 66 // This future returns when the process exits. It is also the return value | 70 // This future returns when the process exits. It is also the return value |
| 67 // of close() | 71 // of close() |
| 68 Future done; | 72 Future done; |
| 69 | 73 |
| 70 Browser(); | 74 Browser(); |
| 71 | 75 |
| 72 factory Browser.byName(String name, String executablePath, | 76 factory Browser.byName(String name, String executablePath, |
| 73 [bool checkedMode = false]) { | 77 [bool checkedMode = false]) { |
| 74 var browser; | 78 Browser browser; |
| 75 if (name == 'firefox') { | 79 if (name == 'firefox') { |
| 76 browser = new Firefox(); | 80 browser = new Firefox(); |
| 77 } else if (name == 'chrome') { | 81 } else if (name == 'chrome') { |
| 78 browser = new Chrome(); | 82 browser = new Chrome(); |
| 79 } else if (name == 'dartium') { | 83 } else if (name == 'dartium') { |
| 80 browser = new Dartium(checkedMode); | 84 browser = new Dartium(checkedMode); |
| 81 } else if (name == 'safari') { | 85 } else if (name == 'safari') { |
| 82 browser = new Safari(); | 86 browser = new Safari(); |
| 83 } else if (name == 'safarimobilesim') { | 87 } else if (name == 'safarimobilesim') { |
| 84 browser = new SafariMobileSimulator(); | 88 browser = new SafariMobileSimulator(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 */ | 169 */ |
| 166 Future<bool> startBrowserProcess(String command, List<String> arguments, | 170 Future<bool> startBrowserProcess(String command, List<String> arguments, |
| 167 {Map<String, String> environment}) { | 171 {Map<String, String> environment}) { |
| 168 return Process | 172 return Process |
| 169 .start(command, arguments, environment: environment) | 173 .start(command, arguments, environment: environment) |
| 170 .then((startedProcess) { | 174 .then((startedProcess) { |
| 171 _logEvent("Started browser using $command ${arguments.join(' ')}"); | 175 _logEvent("Started browser using $command ${arguments.join(' ')}"); |
| 172 process = startedProcess; | 176 process = startedProcess; |
| 173 // Used to notify when exiting, and as a return value on calls to | 177 // Used to notify when exiting, and as a return value on calls to |
| 174 // close(). | 178 // close(). |
| 175 var doneCompleter = new Completer(); | 179 var doneCompleter = new Completer<bool>(); |
| 176 done = doneCompleter.future; | 180 done = doneCompleter.future; |
| 177 | 181 |
| 178 Completer stdoutDone = new Completer(); | 182 Completer stdoutDone = new Completer<Null>(); |
| 179 Completer stderrDone = new Completer(); | 183 Completer stderrDone = new Completer<Null>(); |
| 180 | 184 |
| 181 bool stdoutIsDone = false; | 185 bool stdoutIsDone = false; |
| 182 bool stderrIsDone = false; | 186 bool stderrIsDone = false; |
| 183 StreamSubscription stdoutSubscription; | 187 StreamSubscription stdoutSubscription; |
| 184 StreamSubscription stderrSubscription; | 188 StreamSubscription stderrSubscription; |
| 185 | 189 |
| 186 // This timer is used to close stdio to the subprocess once we got | 190 // This timer is used to close stdio to the subprocess once we got |
| 187 // the exitCode. Sometimes descendants of the subprocess keep stdio | 191 // the exitCode. Sometimes descendants of the subprocess keep stdio |
| 188 // handles alive even though the direct subprocess is dead. | 192 // handles alive even though the direct subprocess is dead. |
| 189 Timer watchdogTimer; | 193 Timer watchdogTimer; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 static const String versionFile = | 300 static const String versionFile = |
| 297 "/Applications/Safari.app/Contents/version.plist"; | 301 "/Applications/Safari.app/Contents/version.plist"; |
| 298 | 302 |
| 299 static const String safariBundleLocation = "/Applications/Safari.app/"; | 303 static const String safariBundleLocation = "/Applications/Safari.app/"; |
| 300 | 304 |
| 301 // Clears the cache if the static resetBrowserConfiguration flag is set. | 305 // Clears the cache if the static resetBrowserConfiguration flag is set. |
| 302 // Returns false if the command to actually clear the cache did not complete. | 306 // Returns false if the command to actually clear the cache did not complete. |
| 303 Future<bool> resetConfiguration() async { | 307 Future<bool> resetConfiguration() async { |
| 304 if (!Browser.resetBrowserConfiguration) return true; | 308 if (!Browser.resetBrowserConfiguration) return true; |
| 305 | 309 |
| 306 Completer completer = new Completer(); | 310 var completer = new Completer<Null>(); |
| 307 handleUncaughtError(error, StackTrace stackTrace) { | 311 handleUncaughtError(error, StackTrace stackTrace) { |
| 308 if (!completer.isCompleted) { | 312 if (!completer.isCompleted) { |
| 309 completer.completeError(error, stackTrace); | 313 completer.completeError(error, stackTrace); |
| 310 } else { | 314 } else { |
| 311 throw new AsyncError(error, stackTrace); | 315 throw new AsyncError(error, stackTrace); |
| 312 } | 316 } |
| 313 } | 317 } |
| 314 | 318 |
| 315 Zone parent = Zone.current; | 319 Zone parent = Zone.current; |
| 316 ZoneSpecification specification = new ZoneSpecification( | 320 ZoneSpecification specification = new ZoneSpecification( |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 for (var line in content) { | 370 for (var line in content) { |
| 367 if (versionOnNextLine) return line; | 371 if (versionOnNextLine) return line; |
| 368 if (line.contains("CFBundleShortVersionString")) { | 372 if (line.contains("CFBundleShortVersionString")) { |
| 369 versionOnNextLine = true; | 373 versionOnNextLine = true; |
| 370 } | 374 } |
| 371 } | 375 } |
| 372 return null; | 376 return null; |
| 373 }); | 377 }); |
| 374 } | 378 } |
| 375 | 379 |
| 376 Future<Null> _createLaunchHTML(var path, var url) async { | 380 Future<Null> _createLaunchHTML(String path, String url) async { |
| 377 var file = new File("${path}/launch.html"); | 381 var file = new File("$path/launch.html"); |
| 378 var randomFile = await file.open(mode: FileMode.WRITE); | 382 var randomFile = await file.open(mode: FileMode.WRITE); |
| 379 var content = '<script language="JavaScript">location = "$url"</script>'; | 383 var content = '<script language="JavaScript">location = "$url"</script>'; |
| 380 await randomFile.writeString(content); | 384 await randomFile.writeString(content); |
| 381 await randomFile.close(); | 385 await randomFile.close(); |
| 382 } | 386 } |
| 383 | 387 |
| 384 Future<bool> start(String url) async { | 388 Future<bool> start(String url) async { |
| 385 _logEvent("Starting Safari browser on: $url"); | 389 _logEvent("Starting Safari browser on: $url"); |
| 386 if (!await resetConfiguration()) { | 390 if (!await resetConfiguration()) { |
| 387 _logEvent("Could not clear cache"); | 391 _logEvent("Could not clear cache"); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 'android.intent.action.VIEW'); | 666 'android.intent.action.VIEW'); |
| 663 | 667 |
| 664 final dartiumOnAndroidConfig = new AndroidBrowserConfig('DartiumOnAndroid', | 668 final dartiumOnAndroidConfig = new AndroidBrowserConfig('DartiumOnAndroid', |
| 665 'com.google.android.apps.chrome', '.Main', 'android.intent.action.VIEW'); | 669 'com.google.android.apps.chrome', '.Main', 'android.intent.action.VIEW'); |
| 666 | 670 |
| 667 class AndroidBrowser extends Browser { | 671 class AndroidBrowser extends Browser { |
| 668 final bool checkedMode; | 672 final bool checkedMode; |
| 669 AdbDevice _adbDevice; | 673 AdbDevice _adbDevice; |
| 670 AndroidBrowserConfig _config; | 674 AndroidBrowserConfig _config; |
| 671 | 675 |
| 672 AndroidBrowser(this._adbDevice, this._config, this.checkedMode, apkPath) { | 676 AndroidBrowser( |
| 677 this._adbDevice, this._config, this.checkedMode, String apkPath) { |
| 673 _binary = apkPath; | 678 _binary = apkPath; |
| 674 } | 679 } |
| 675 | 680 |
| 676 Future<bool> start(String url) { | 681 Future<bool> start(String url) { |
| 677 var intent = | 682 var intent = |
| 678 new Intent(_config.action, _config.package, _config.activity, url); | 683 new Intent(_config.action, _config.package, _config.activity, url); |
| 679 return _adbDevice.waitForBootCompleted().then((_) { | 684 return _adbDevice.waitForBootCompleted().then((_) { |
| 680 return _adbDevice.forceStop(_config.package); | 685 return _adbDevice.forceStop(_config.package); |
| 681 }).then((_) { | 686 }).then((_) { |
| 682 return _adbDevice.killAll(); | 687 return _adbDevice.killAll(); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 } | 792 } |
| 788 | 793 |
| 789 class Firefox extends Browser { | 794 class Firefox extends Browser { |
| 790 static const String enablePopUp = | 795 static const String enablePopUp = |
| 791 'user_pref("dom.disable_open_during_load", false);'; | 796 'user_pref("dom.disable_open_during_load", false);'; |
| 792 static const String disableDefaultCheck = | 797 static const String disableDefaultCheck = |
| 793 'user_pref("browser.shell.checkDefaultBrowser", false);'; | 798 'user_pref("browser.shell.checkDefaultBrowser", false);'; |
| 794 static const String disableScriptTimeLimit = | 799 static const String disableScriptTimeLimit = |
| 795 'user_pref("dom.max_script_run_time", 0);'; | 800 'user_pref("dom.max_script_run_time", 0);'; |
| 796 | 801 |
| 797 void _createPreferenceFile(var path) { | 802 void _createPreferenceFile(String path) { |
| 798 var file = new File("${path.toString()}/user.js"); | 803 var file = new File("$path/user.js"); |
| 799 var randomFile = file.openSync(mode: FileMode.WRITE); | 804 var randomFile = file.openSync(mode: FileMode.WRITE); |
| 800 randomFile.writeStringSync(enablePopUp); | 805 randomFile.writeStringSync(enablePopUp); |
| 801 randomFile.writeStringSync(disableDefaultCheck); | 806 randomFile.writeStringSync(disableDefaultCheck); |
| 802 randomFile.writeStringSync(disableScriptTimeLimit); | 807 randomFile.writeStringSync(disableScriptTimeLimit); |
| 803 randomFile.close(); | 808 randomFile.close(); |
| 804 } | 809 } |
| 805 | 810 |
| 806 Future<bool> start(String url) { | 811 Future<bool> start(String url) { |
| 807 _logEvent("Starting firefox browser on: $url"); | 812 _logEvent("Starting firefox browser on: $url"); |
| 808 // Get the version and log that. | 813 // Get the version and log that. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 Stopwatch timeSinceRestart = new Stopwatch()..start(); | 861 Stopwatch timeSinceRestart = new Stopwatch()..start(); |
| 857 | 862 |
| 858 BrowserStatus(Browser this.browser); | 863 BrowserStatus(Browser this.browser); |
| 859 } | 864 } |
| 860 | 865 |
| 861 /** | 866 /** |
| 862 * Describes a single test to be run in the browser. | 867 * Describes a single test to be run in the browser. |
| 863 */ | 868 */ |
| 864 class BrowserTest { | 869 class BrowserTest { |
| 865 // TODO(ricow): Add timeout callback instead of the string passing hack. | 870 // TODO(ricow): Add timeout callback instead of the string passing hack. |
| 866 Function doneCallback; | 871 BrowserDoneCallback doneCallback; |
| 867 String url; | 872 String url; |
| 868 int timeout; | 873 int timeout; |
| 869 String lastKnownMessage = ''; | 874 String lastKnownMessage = ''; |
| 870 Stopwatch stopwatch; | 875 Stopwatch stopwatch; |
| 871 | 876 |
| 872 // This might be null | 877 // This might be null |
| 873 Duration delayUntilTestStarted; | 878 Duration delayUntilTestStarted; |
| 874 | 879 |
| 875 // We store this here for easy access when tests time out (instead of | 880 // We store this here for easy access when tests time out (instead of |
| 876 // capturing this in a closure) | 881 // capturing this in a closure) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 887 | 892 |
| 888 String toJSON() => JSON.encode({'url': url, 'id': id, 'isHtmlTest': false}); | 893 String toJSON() => JSON.encode({'url': url, 'id': id, 'isHtmlTest': false}); |
| 889 } | 894 } |
| 890 | 895 |
| 891 /** | 896 /** |
| 892 * Describes a test with a custom HTML page to be run in the browser. | 897 * Describes a test with a custom HTML page to be run in the browser. |
| 893 */ | 898 */ |
| 894 class HtmlTest extends BrowserTest { | 899 class HtmlTest extends BrowserTest { |
| 895 List<String> expectedMessages; | 900 List<String> expectedMessages; |
| 896 | 901 |
| 897 HtmlTest(url, doneCallback, timeout, this.expectedMessages) | 902 HtmlTest(String url, BrowserDoneCallback doneCallback, int timeout, |
| 903 this.expectedMessages) |
| 898 : super(url, doneCallback, timeout) {} | 904 : super(url, doneCallback, timeout) {} |
| 899 | 905 |
| 900 String toJSON() => JSON.encode({ | 906 String toJSON() => JSON.encode({ |
| 901 'url': url, | 907 'url': url, |
| 902 'id': id, | 908 'id': id, |
| 903 'isHtmlTest': true, | 909 'isHtmlTest': true, |
| 904 'expectedMessages': expectedMessages | 910 'expectedMessages': expectedMessages |
| 905 }); | 911 }); |
| 906 } | 912 } |
| 907 | 913 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 930 /// driver page to the browsers, serves tests, and receives results and | 936 /// driver page to the browsers, serves tests, and receives results and |
| 931 /// requests back from the browsers. | 937 /// requests back from the browsers. |
| 932 class BrowserTestRunner { | 938 class BrowserTestRunner { |
| 933 static const int MAX_NEXT_TEST_TIMEOUTS = 10; | 939 static const int MAX_NEXT_TEST_TIMEOUTS = 10; |
| 934 static const Duration NEXT_TEST_TIMEOUT = const Duration(seconds: 120); | 940 static const Duration NEXT_TEST_TIMEOUT = const Duration(seconds: 120); |
| 935 static const Duration RESTART_BROWSER_INTERVAL = const Duration(seconds: 60); | 941 static const Duration RESTART_BROWSER_INTERVAL = const Duration(seconds: 60); |
| 936 | 942 |
| 937 /// If the queue was recently empty, don't start another browser. | 943 /// If the queue was recently empty, don't start another browser. |
| 938 static const Duration MIN_NONEMPTY_QUEUE_TIME = const Duration(seconds: 1); | 944 static const Duration MIN_NONEMPTY_QUEUE_TIME = const Duration(seconds: 1); |
| 939 | 945 |
| 940 final Map configuration; | 946 final Map<String, String> configuration; |
| 941 final BrowserTestingServer testingServer; | 947 final BrowserTestingServer testingServer; |
| 942 | 948 |
| 943 final String localIp; | 949 final String localIp; |
| 944 final String browserName; | 950 final String browserName; |
| 945 int maxNumBrowsers; | 951 int maxNumBrowsers; |
| 946 final bool checkedMode; | 952 final bool checkedMode; |
| 947 int numBrowsers = 0; | 953 int numBrowsers = 0; |
| 948 // Used to send back logs from the browser (start, stop etc) | 954 // Used to send back logs from the browser (start, stop etc) |
| 949 Function logger; | 955 Function logger; |
| 950 | 956 |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1260 } | 1266 } |
| 1261 | 1267 |
| 1262 /// Creates a timer that is active while no test is running on the | 1268 /// Creates a timer that is active while no test is running on the |
| 1263 /// browser. It has finished one test, and it has not requested a new test. | 1269 /// browser. It has finished one test, and it has not requested a new test. |
| 1264 Timer createNextTestTimer(BrowserStatus status) { | 1270 Timer createNextTestTimer(BrowserStatus status) { |
| 1265 return new Timer(BrowserTestRunner.NEXT_TEST_TIMEOUT, () { | 1271 return new Timer(BrowserTestRunner.NEXT_TEST_TIMEOUT, () { |
| 1266 handleNextTestTimeout(status); | 1272 handleNextTestTimeout(status); |
| 1267 }); | 1273 }); |
| 1268 } | 1274 } |
| 1269 | 1275 |
| 1270 void handleNextTestTimeout(status) { | 1276 void handleNextTestTimeout(BrowserStatus status) { |
| 1271 DebugLogger | 1277 DebugLogger |
| 1272 .warning("Browser timed out before getting next test. Restarting"); | 1278 .warning("Browser timed out before getting next test. Restarting"); |
| 1273 if (status.timeout) return; | 1279 if (status.timeout) return; |
| 1274 numBrowserGetTestTimeouts++; | 1280 numBrowserGetTestTimeouts++; |
| 1275 if (numBrowserGetTestTimeouts >= MAX_NEXT_TEST_TIMEOUTS) { | 1281 if (numBrowserGetTestTimeouts >= MAX_NEXT_TEST_TIMEOUTS) { |
| 1276 DebugLogger.error( | 1282 DebugLogger.error( |
| 1277 "Too many browser timeouts before getting next test. Terminating"); | 1283 "Too many browser timeouts before getting next test. Terminating"); |
| 1278 terminate().then((_) => exit(1)); | 1284 terminate().then((_) => exit(1)); |
| 1279 } else { | 1285 } else { |
| 1280 status.timeout = true; | 1286 status.timeout = true; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1306 DebugLogger.warning("${testCache[id]}, output: "); | 1312 DebugLogger.warning("${testCache[id]}, output: "); |
| 1307 DebugLogger.warning("${doubleReportingOutputs[id]}"); | 1313 DebugLogger.warning("${doubleReportingOutputs[id]}"); |
| 1308 DebugLogger.warning(""); | 1314 DebugLogger.warning(""); |
| 1309 DebugLogger.warning(""); | 1315 DebugLogger.warning(""); |
| 1310 } | 1316 } |
| 1311 } | 1317 } |
| 1312 | 1318 |
| 1313 // TODO(26191): Call a unified fatalError(), that shuts down all subprocesses. | 1319 // TODO(26191): Call a unified fatalError(), that shuts down all subprocesses. |
| 1314 // This just kills the browsers in this BrowserTestRunner instance. | 1320 // This just kills the browsers in this BrowserTestRunner instance. |
| 1315 Future terminate() async { | 1321 Future terminate() async { |
| 1316 var browsers = []; | 1322 var browsers = <Browser>[]; |
| 1317 underTermination = true; | 1323 underTermination = true; |
| 1318 testingServer.underTermination = true; | 1324 testingServer.underTermination = true; |
| 1319 for (BrowserStatus status in browserStatus.values) { | 1325 for (BrowserStatus status in browserStatus.values) { |
| 1320 browsers.add(status.browser); | 1326 browsers.add(status.browser); |
| 1321 if (status.nextTestTimeout != null) { | 1327 if (status.nextTestTimeout != null) { |
| 1322 status.nextTestTimeout.cancel(); | 1328 status.nextTestTimeout.cancel(); |
| 1323 status.nextTestTimeout = null; | 1329 status.nextTestTimeout = null; |
| 1324 } | 1330 } |
| 1325 } | 1331 } |
| 1326 for (Browser b in browsers) { | 1332 |
| 1327 await b.close(); | 1333 for (var browser in browsers) { |
| 1334 await browser.close(); |
| 1328 } | 1335 } |
| 1336 |
| 1329 testingServer.errorReportingServer.close(); | 1337 testingServer.errorReportingServer.close(); |
| 1330 printDoubleReportingTests(); | 1338 printDoubleReportingTests(); |
| 1331 } | 1339 } |
| 1332 } | 1340 } |
| 1333 | 1341 |
| 1334 class BrowserTestingServer { | 1342 class BrowserTestingServer { |
| 1335 final Map configuration; | 1343 final Map configuration; |
| 1336 | 1344 |
| 1337 /// Interface of the testing server: | 1345 /// Interface of the testing server: |
| 1338 /// | 1346 /// |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1353 | 1361 |
| 1354 static const String driverPath = "/driver"; | 1362 static const String driverPath = "/driver"; |
| 1355 static const String nextTestPath = "/next_test"; | 1363 static const String nextTestPath = "/next_test"; |
| 1356 static const String reportPath = "/report"; | 1364 static const String reportPath = "/report"; |
| 1357 static const String statusUpdatePath = "/status_update"; | 1365 static const String statusUpdatePath = "/status_update"; |
| 1358 static const String startedPath = "/started"; | 1366 static const String startedPath = "/started"; |
| 1359 static const String waitSignal = "WAIT"; | 1367 static const String waitSignal = "WAIT"; |
| 1360 static const String terminateSignal = "TERMINATE"; | 1368 static const String terminateSignal = "TERMINATE"; |
| 1361 | 1369 |
| 1362 var testCount = 0; | 1370 var testCount = 0; |
| 1363 var errorReportingServer; | 1371 HttpServer errorReportingServer; |
| 1364 bool underTermination = false; | 1372 bool underTermination = false; |
| 1365 | 1373 |
| 1366 Function testDoneCallBack; | 1374 TestChangedCallback testDoneCallBack; |
| 1367 Function testStatusUpdateCallBack; | 1375 TestChangedCallback testStatusUpdateCallBack; |
| 1368 Function testStartedCallBack; | 1376 TestChangedCallback testStartedCallBack; |
| 1369 Function nextTestCallBack; | 1377 NextTestCallback nextTestCallBack; |
| 1370 | 1378 |
| 1371 BrowserTestingServer( | 1379 BrowserTestingServer( |
| 1372 this.configuration, this.localIp, this.useIframe, this.requiresFocus); | 1380 this.configuration, this.localIp, this.useIframe, this.requiresFocus); |
| 1373 | 1381 |
| 1374 Future start() { | 1382 Future start() { |
| 1375 var test_driver_error_port = configuration['test_driver_error_port']; | 1383 var testDriverErrorPort = configuration['test_driver_error_port']; |
| 1376 return HttpServer | 1384 return HttpServer |
| 1377 .bind(localIp, test_driver_error_port) | 1385 .bind(localIp, testDriverErrorPort) |
| 1378 .then(setupErrorServer) | 1386 .then(setupErrorServer) |
| 1379 .then(setupDispatchingServer); | 1387 .then(setupDispatchingServer); |
| 1380 } | 1388 } |
| 1381 | 1389 |
| 1382 void setupErrorServer(HttpServer server) { | 1390 void setupErrorServer(HttpServer server) { |
| 1383 errorReportingServer = server; | 1391 errorReportingServer = server; |
| 1384 void errorReportingHandler(HttpRequest request) { | 1392 void errorReportingHandler(HttpRequest request) { |
| 1385 StringBuffer buffer = new StringBuffer(); | 1393 StringBuffer buffer = new StringBuffer(); |
| 1386 request.transform(UTF8.decoder).listen((data) { | 1394 request.transform(UTF8.decoder).listen((data) { |
| 1387 buffer.write(data); | 1395 buffer.write(data); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1402 | 1410 |
| 1403 void errorHandler(e) { | 1411 void errorHandler(e) { |
| 1404 if (!underTermination) print("Error occured in httpserver: $e"); | 1412 if (!underTermination) print("Error occured in httpserver: $e"); |
| 1405 } | 1413 } |
| 1406 | 1414 |
| 1407 errorReportingServer.listen(errorReportingHandler, onError: errorHandler); | 1415 errorReportingServer.listen(errorReportingHandler, onError: errorHandler); |
| 1408 } | 1416 } |
| 1409 | 1417 |
| 1410 void setupDispatchingServer(_) { | 1418 void setupDispatchingServer(_) { |
| 1411 DispatchingServer server = configuration['_servers_'].server; | 1419 DispatchingServer server = configuration['_servers_'].server; |
| 1412 void noCache(request) { | 1420 void noCache(HttpRequest request) { |
| 1413 request.response.headers | 1421 request.response.headers |
| 1414 .set("Cache-Control", "no-cache, no-store, must-revalidate"); | 1422 .set("Cache-Control", "no-cache, no-store, must-revalidate"); |
| 1415 } | 1423 } |
| 1416 | 1424 |
| 1417 int testId(request) => int.parse(request.uri.queryParameters["id"]); | 1425 int testId(HttpRequest request) => |
| 1418 String browserId(request, prefix) => | 1426 int.parse(request.uri.queryParameters["id"]); |
| 1427 String browserId(HttpRequest request, String prefix) => |
| 1419 request.uri.path.substring(prefix.length + 1); | 1428 request.uri.path.substring(prefix.length + 1); |
| 1420 | 1429 |
| 1421 server.addHandler(reportPath, (HttpRequest request) { | 1430 server.addHandler(reportPath, (HttpRequest request) { |
| 1422 noCache(request); | 1431 noCache(request); |
| 1423 handleReport(request, browserId(request, reportPath), testId(request), | 1432 handleReport(request, browserId(request, reportPath), testId(request), |
| 1424 isStatusUpdate: false); | 1433 isStatusUpdate: false); |
| 1425 }); | 1434 }); |
| 1426 server.addHandler(statusUpdatePath, (HttpRequest request) { | 1435 server.addHandler(statusUpdatePath, (HttpRequest request) { |
| 1427 noCache(request); | 1436 noCache(request); |
| 1428 handleReport( | 1437 handleReport( |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 // Ignoring the returned closure as it returns the 'done' future | 1473 // Ignoring the returned closure as it returns the 'done' future |
| 1465 // which already has catchError installed above. | 1474 // which already has catchError installed above. |
| 1466 request.response.close(); | 1475 request.response.close(); |
| 1467 }); | 1476 }); |
| 1468 } | 1477 } |
| 1469 | 1478 |
| 1470 server.addHandler(driverPath, sendPageHandler); | 1479 server.addHandler(driverPath, sendPageHandler); |
| 1471 server.addHandler(nextTestPath, sendPageHandler); | 1480 server.addHandler(nextTestPath, sendPageHandler); |
| 1472 } | 1481 } |
| 1473 | 1482 |
| 1474 void handleReport(HttpRequest request, String browserId, var testId, | 1483 void handleReport(HttpRequest request, String browserId, int testId, |
| 1475 {bool isStatusUpdate}) { | 1484 {bool isStatusUpdate}) { |
| 1476 StringBuffer buffer = new StringBuffer(); | 1485 StringBuffer buffer = new StringBuffer(); |
| 1477 request.transform(UTF8.decoder).listen((data) { | 1486 request.transform(UTF8.decoder).listen((data) { |
| 1478 buffer.write(data); | 1487 buffer.write(data); |
| 1479 }, onDone: () { | 1488 }, onDone: () { |
| 1480 String back = buffer.toString(); | 1489 String back = buffer.toString(); |
| 1481 request.response.close(); | 1490 request.response.close(); |
| 1482 if (isStatusUpdate) { | 1491 if (isStatusUpdate) { |
| 1483 testStatusUpdateCallBack(browserId, back, testId); | 1492 testStatusUpdateCallBack(browserId, back, testId); |
| 1484 } else { | 1493 } else { |
| 1485 testDoneCallBack(browserId, back, testId); | 1494 testDoneCallBack(browserId, back, testId); |
| 1486 } | 1495 } |
| 1487 // TODO(ricow): We should do something smart if we get an error here. | 1496 // TODO(ricow): We should do something smart if we get an error here. |
| 1488 }, onError: (error) { | 1497 }, onError: (error) { |
| 1489 DebugLogger.error("$error"); | 1498 DebugLogger.error("$error"); |
| 1490 }); | 1499 }); |
| 1491 } | 1500 } |
| 1492 | 1501 |
| 1493 void handleStarted(HttpRequest request, String browserId, var testId) { | 1502 void handleStarted(HttpRequest request, String browserId, int testId) { |
| 1494 StringBuffer buffer = new StringBuffer(); | 1503 StringBuffer buffer = new StringBuffer(); |
| 1495 // If an error occurs while receiving the data from the request stream, | 1504 // If an error occurs while receiving the data from the request stream, |
| 1496 // we don't handle it specially. We can safely ignore it, since the started | 1505 // we don't handle it specially. We can safely ignore it, since the started |
| 1497 // events are not crucial. | 1506 // events are not crucial. |
| 1498 request.transform(UTF8.decoder).listen((data) { | 1507 request.transform(UTF8.decoder).listen((data) { |
| 1499 buffer.write(data); | 1508 buffer.write(data); |
| 1500 }, onDone: () { | 1509 }, onDone: () { |
| 1501 String back = buffer.toString(); | 1510 String back = buffer.toString(); |
| 1502 request.response.close(); | 1511 request.response.close(); |
| 1503 testStartedCallBack(browserId, back, testId); | 1512 testStartedCallBack(browserId, back, testId); |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1937 'exit code: ${result.exitCode}\n' | 1946 'exit code: ${result.exitCode}\n' |
| 1938 'stdout: ${result.stdout}\n' | 1947 'stdout: ${result.stdout}\n' |
| 1939 'stderr: ${result.stderr}'); | 1948 'stderr: ${result.stderr}'); |
| 1940 } else { | 1949 } else { |
| 1941 print('[$message] Successfully uploaded screenshot to $storageUrl'); | 1950 print('[$message] Successfully uploaded screenshot to $storageUrl'); |
| 1942 } | 1951 } |
| 1943 new File(screenshotFile).deleteSync(); | 1952 new File(screenshotFile).deleteSync(); |
| 1944 } | 1953 } |
| 1945 print('--------------------------------------------------------------------'); | 1954 print('--------------------------------------------------------------------'); |
| 1946 } | 1955 } |
| OLD | NEW |