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

Side by Side Diff: tools/testing/dart/browser_controller.dart

Issue 1859523002: Start browsers sequentially in testing scripts, as needed. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix problems Created 4 years, 8 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
« no previous file with comments | « no previous file | tools/testing/dart/test_runner.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 LineSplitter, UTF8, JSON; 7 import "dart:convert" show LineSplitter, UTF8, JSON;
8 import "dart:core"; 8 import "dart:core";
9 import "dart:io"; 9 import "dart:io";
10 import "dart:math" show max, min;
10 11
11 import 'android.dart'; 12 import 'android.dart';
12 import 'http_server.dart'; 13 import 'http_server.dart';
13 import 'path.dart'; 14 import 'path.dart';
14 import 'utils.dart'; 15 import 'utils.dart';
15 16
16 class BrowserOutput { 17 class BrowserOutput {
17 final StringBuffer stdout = new StringBuffer(); 18 final StringBuffer stdout = new StringBuffer();
18 final StringBuffer stderr = new StringBuffer(); 19 final StringBuffer stderr = new StringBuffer();
19 final StringBuffer eventLog = new StringBuffer(); 20 final StringBuffer eventLog = new StringBuffer();
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 class BrowserTestingStatus { 766 class BrowserTestingStatus {
766 Browser browser; 767 Browser browser;
767 BrowserTest currentTest; 768 BrowserTest currentTest;
768 769
769 // This is currently not used for anything except for error reporting. 770 // This is currently not used for anything except for error reporting.
770 // Given the usefulness of this in debugging issues this should not be 771 // Given the usefulness of this in debugging issues this should not be
771 // removed even when we have a really stable system. 772 // removed even when we have a really stable system.
772 BrowserTest lastTest; 773 BrowserTest lastTest;
773 bool timeout = false; 774 bool timeout = false;
774 Timer nextTestTimeout; 775 Timer nextTestTimeout;
775 Stopwatch timeSinceRestart = new Stopwatch(); 776 Stopwatch timeSinceRestart = new Stopwatch()..start();
776 777
777 BrowserTestingStatus(Browser this.browser); 778 BrowserTestingStatus(Browser this.browser);
778 } 779 }
779 780
780 781
781 /** 782 /**
782 * Describes a single test to be run in the browser. 783 * Describes a single test to be run in the browser.
783 */ 784 */
784 class BrowserTest { 785 class BrowserTest {
785 // TODO(ricow): Add timeout callback instead of the string passing hack. 786 // TODO(ricow): Add timeout callback instead of the string passing hack.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 /** 846 /**
846 * Encapsulates all the functionality for running tests in browsers. 847 * Encapsulates all the functionality for running tests in browsers.
847 * The interface is rather simple. After starting, the runner tests 848 * The interface is rather simple. After starting, the runner tests
848 * are simply added to the queue and a the supplied callbacks are called 849 * are simply added to the queue and a the supplied callbacks are called
849 * whenever a test completes. 850 * whenever a test completes.
850 */ 851 */
851 class BrowserTestRunner { 852 class BrowserTestRunner {
852 static const int MAX_NEXT_TEST_TIMEOUTS = 10; 853 static const int MAX_NEXT_TEST_TIMEOUTS = 10;
853 static const Duration NEXT_TEST_TIMEOUT = const Duration(seconds: 60); 854 static const Duration NEXT_TEST_TIMEOUT = const Duration(seconds: 60);
854 static const Duration RESTART_BROWSER_INTERVAL = const Duration(seconds: 60); 855 static const Duration RESTART_BROWSER_INTERVAL = const Duration(seconds: 60);
856 // If the test has been empty within this period, don't start another browser.
ahe 2016/04/05 13:19:41 Add newline before comment to make it obvious wher
Bill Hesse 2016/04/05 14:51:22 Done.
857 static const Duration MIN_NONEMPTY_QUEUE_TIME = const Duration(seconds: 1);
855 858
856 final Map configuration; 859 final Map configuration;
857 860
858 final String localIp; 861 final String localIp;
859 String browserName; 862 String browserName;
860 final int maxNumBrowsers; 863 int maxNumBrowsers;
861 bool checkedMode; 864 bool checkedMode;
862 // Used to send back logs from the browser (start, stop etc) 865 // Used to send back logs from the browser (start, stop etc)
863 Function logger; 866 Function logger;
864 int browserIdCount = 0; 867 int browserIdCounter = 0;
ahe 2016/04/05 13:19:42 Isn't this a count, not a counter. A counter is so
Bill Hesse 2016/04/05 14:51:22 This is a counter, that ticks up, just to give a n
865 868
869 bool testServerStarted = false;
866 bool underTermination = false; 870 bool underTermination = false;
867 int numBrowserGetTestTimeouts = 0; 871 int numBrowserGetTestTimeouts = 0;
868 872
873 // We will start a new browser when the test queue hasn't been empty
874 // recently, we have fewer than maxNumBrowsers browsers, and there is
875 // no browser currently starting up.
876 DateTime lastEmptyTestQueueTime = new DateTime.now();
877 int numBrowsers = 0;
878 String startingBrowserId;
879
869 List<BrowserTest> testQueue = new List<BrowserTest>(); 880 List<BrowserTest> testQueue = new List<BrowserTest>();
870 Map<String, BrowserTestingStatus> browserStatus = 881 Map<String, BrowserTestingStatus> browserStatus =
871 new Map<String, BrowserTestingStatus>(); 882 new Map<String, BrowserTestingStatus>();
872 883
873 var adbDeviceMapping = new Map<String, AdbDevice>(); 884 var adbDeviceMapping = new Map<String, AdbDevice>();
885 List<AdbDevice> idleAdbDevices;
874 // This cache is used to guarantee that we never see double reporting. 886 // This cache is used to guarantee that we never see double reporting.
875 // If we do we need to provide developers with this information. 887 // If we do we need to provide developers with this information.
876 // We don't add urls to the cache until we have run it. 888 // We don't add urls to the cache until we have run it.
877 Map<int, String> testCache = new Map<int, String>(); 889 Map<int, String> testCache = new Map<int, String>();
878 Map<int, String> doubleReportingOutputs = new Map<int, String>(); 890 Map<int, String> doubleReportingOutputs = new Map<int, String>();
879 891
880 BrowserTestingServer testingServer; 892 BrowserTestingServer testingServer;
893 // If [browserName] doesn't support opening new windows, we use new iframes
894 // instead.
895 bool get useIframe =>
896 !Browser.BROWSERS_WITH_WINDOW_SUPPORT.contains(browserName);
881 897
882 /** 898 /**
883 * The TestRunner takes the testingServer in as a constructor parameter in 899 * The TestRunner takes the testingServer in as a constructor parameter in
884 * case we wish to have a testing server with different behavior (such as the 900 * case we wish to have a testing server with different behavior (such as the
885 * case for performance testing. 901 * case for performance testing. Note that the testingServer handlers are
902 * overwritten with handlers for this specific configuration, in that case.
886 */ 903 */
887 BrowserTestRunner(this.configuration, 904 BrowserTestRunner(this.configuration,
888 this.localIp, 905 this.localIp,
889 this.browserName, 906 this.browserName,
890 this.maxNumBrowsers, 907 this.maxNumBrowsers,
891 {BrowserTestingServer this.testingServer}) { 908 {BrowserTestingServer this.testingServer}) {
892 checkedMode = configuration['checked']; 909 checkedMode = configuration['checked'];
910 if (browserName == 'ff') browserName = 'firefox';
893 } 911 }
894 912
895 Future<bool> start() { 913 Future start() async {
896 // If [browserName] doesn't support opening new windows, we use new iframes
897 // instead.
898 bool useIframe =
899 !Browser.BROWSERS_WITH_WINDOW_SUPPORT.contains(browserName);
900 if (testingServer == null) { 914 if (testingServer == null) {
901 testingServer = new BrowserTestingServer( 915 testingServer = new BrowserTestingServer(
902 configuration, localIp, useIframe); 916 configuration, localIp, useIframe);
903 } 917 }
904 return testingServer.start().then((_) { 918 await testingServer.start();
905 testingServer.testDoneCallBack = handleResults; 919 testingServer
906 testingServer.testStatusUpdateCallBack = handleStatusUpdate; 920 ..testDoneCallBack = handleResults
907 testingServer.testStartedCallBack = handleStarted; 921 ..testStatusUpdateCallBack = handleStatusUpdate
908 testingServer.nextTestCallBack = getNextTest; 922 ..testStartedCallBack = handleStarted
909 return getBrowsers().then((browsers) { 923 ..nextTestCallBack = getNextTest;
910 var futures = []; 924 if (browserName == 'chromeOnAndroid') {
911 for (var browser in browsers) { 925 var idbNames = await AdbHelper.listDevices();
912 var url = testingServer.getDriverUrl(browser.id); 926 idleAdbDevices = new List.from(idbNames.map((id) => new AdbDevice(id)));
913 var future = browser.start(url).then((success) { 927 maxNumBrowsers = min(maxNumBrowsers, idleAdbDevices.length);
914 if (success) { 928 }
915 var status = new BrowserTestingStatus(browser); 929 testServerStarted = true;
916 browserStatus[browser.id] = status; 930 requestBrowser();
917 status.nextTestTimeout = createNextTestTimer(status);
918 status.timeSinceRestart.start();
919 }
920 return success;
921 });
922 futures.add(future);
923 }
924 return Future.wait(futures).then((values) {
925 return !values.contains(false);
926 });
927 });
928 });
929 } 931 }
930 932
931 Future<List<Browser>> getBrowsers() { 933 void requestBrowser() {
ahe 2016/04/05 13:19:41 Who calls this method? Why and when?
Bill Hesse 2016/04/05 14:51:22 Added doc comment.
932 // TODO(kustermann): This is a hackisch way to accomplish it and should 934 if (!testServerStarted) return;
ahe 2016/04/05 13:19:41 Why is it OK to not start a browser if the test se
Bill Hesse 2016/04/05 14:51:22 Because 4 lines above, when the test server is fin
933 // be encapsulated 935 if (underTermination) return;
ahe 2016/04/05 13:19:41 Who would be requesting a browser during terminati
Bill Hesse 2016/04/05 14:51:22 Another browser that is requesting a new test. If
934 var browsersCompleter = new Completer(); 936 if (numBrowsers == maxNumBrowsers) return;
935 var androidBrowserCreationMapping = { 937 if (startingBrowserId != null) return;
ahe 2016/04/05 13:19:42 What does it mean if startingBrowserId is null?
Bill Hesse 2016/04/05 14:51:22 It means no browser is currently starting. I cons
936 'chromeOnAndroid' : (AdbDevice device) => new AndroidChrome(device), 938 if (numBrowsers > 0 &&
937 'ContentShellOnAndroid' : (AdbDevice device) => new AndroidBrowser( 939 (testQueue.isEmpty ||
938 device, 940 lastEmptyTestQueueTime.add(MIN_NONEMPTY_QUEUE_TIME)
939 contentShellOnAndroidConfig, 941 .isAfter(new DateTime.now()))) return;
940 checkedMode, 942 startBrowser();
941 configuration['drt']), 943 }
942 'DartiumOnAndroid' : (AdbDevice device) => new AndroidBrowser( 944
943 device, 945 void startBrowser() {
ahe 2016/04/05 13:19:42 How is this different from Browser.startBrowser? C
Bill Hesse 2016/04/05 14:51:22 Browser.startBrowser is a bad name for that functi
944 dartiumOnAndroidConfig, 946 final id = "BROWSER$browserIdCounter";
945 checkedMode, 947 print("startBrowser called: $id");
ahe 2016/04/05 13:19:42 Debug message?
Bill Hesse 2016/04/05 14:51:22 Done.
946 configuration['dartium']), 948 ++browserIdCounter;
947 }; 949 final url = testingServer.getDriverUrl(id);
948 if (androidBrowserCreationMapping.containsKey(browserName)) { 950 Browser browser;
949 AdbHelper.listDevices().then((deviceIds) { 951 if (browserName == 'chromeOnAndroid') {
950 if (deviceIds.length > 0) { 952 AdbDevice device = idleAdbDevices.removeLast();
951 var browsers = []; 953 adbDeviceMapping[id] = device;
952 for (int i = 0; i < deviceIds.length; i++) { 954 browser = new AndroidChrome(device);
953 var id = "BROWSER$i";
954 var device = new AdbDevice(deviceIds[i]);
955 adbDeviceMapping[id] = device;
956 var browser = androidBrowserCreationMapping[browserName](device);
957 browsers.add(browser);
958 // We store this in case we need to kill the browser.
959 browser.id = id;
960 }
961 browsersCompleter.complete(browsers);
962 } else {
963 throw new StateError("No android devices found.");
964 }
965 });
966 } else { 955 } else {
967 var browsers = []; 956 var path = Locations.getBrowserLocation(browserName, configuration);
968 for (int i = 0; i < maxNumBrowsers; i++) { 957 browser = new Browser.byName(browserName, path, checkedMode);
969 var id = "BROWSER$browserIdCount"; 958 browser.logger = logger;
970 browserIdCount++;
971 var browser = getInstance();
972 browsers.add(browser);
973 // We store this in case we need to kill the browser.
974 browser.id = id;
975 }
976 browsersCompleter.complete(browsers);
977 } 959 }
978 return browsersCompleter.future; 960 browser.id = id;
961 startingBrowserId = id;
962 final status = new BrowserTestingStatus(browser);
963 browserStatus[id] = status;
964 numBrowsers++;
965 print("Started $id $numBrowsers");
ahe 2016/04/05 13:19:42 Debug?
Bill Hesse 2016/04/05 14:51:22 Done.
966 status.nextTestTimeout = createNextTestTimer(status);
ahe 2016/04/05 13:19:42 What does this do?
Bill Hesse 2016/04/05 14:51:22 Added a doc comment to createNextTestTimer and cre
967 browser.start(url);
979 } 968 }
980 969
981 var timedOut = []; 970 var timedOut = [];
982 971
983 void handleResults(String browserId, String output, int testId) { 972 void handleResults(String browserId, String output, int testId) {
984 var status = browserStatus[browserId]; 973 var status = browserStatus[browserId];
985 if (testCache.containsKey(testId)) { 974 if (testCache.containsKey(testId)) {
986 doubleReportingOutputs[testId] = output; 975 doubleReportingOutputs[testId] = output;
987 return; 976 return;
988 } 977 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 status.currentTest.stopwatch.elapsed, 1066 status.currentTest.stopwatch.elapsed,
1078 lastKnownMessage, 1067 lastKnownMessage,
1079 status.browser.testBrowserOutput, 1068 status.browser.testBrowserOutput,
1080 didTimeout: true); 1069 didTimeout: true);
1081 status.currentTest.doneCallback(browserTestOutput); 1070 status.currentTest.doneCallback(browserTestOutput);
1082 status.lastTest = status.currentTest; 1071 status.lastTest = status.currentTest;
1083 status.currentTest = null; 1072 status.currentTest = null;
1084 1073
1085 // We don't want to start a new browser if we are terminating. 1074 // We don't want to start a new browser if we are terminating.
1086 if (underTermination) return; 1075 if (underTermination) return;
1087 restartBrowser(id); 1076 removeBrowser(id);
1088 }); 1077 });
1089 } 1078 }
1090 1079
1091 void restartBrowser(String id) { 1080 void removeBrowser(String id) {
ahe 2016/04/05 13:19:42 This is confusing: remove browser seems to add a b
Bill Hesse 2016/04/05 14:51:22 Remove the entries for that browserID from our dat
1092 if (browserName.contains('OnAndroid')) { 1081 if (browserName == 'chromeOnAndroid') {
1093 DebugLogger.info("Restarting browser $id"); 1082 idleAdbDevices.add(adbDeviceMapping.remove(id));
1094 } 1083 }
1095 var browser; 1084 if (startingBrowserId == id) startingBrowserId = null;
ahe 2016/04/05 13:19:41 What does this mean?
Bill Hesse 2016/04/05 14:51:22 startingBrowserId == null when there is no browser
1096 var new_id = id; 1085 browserStatus.remove(id);
1097 if (browserName == 'chromeOnAndroid') { 1086 --numBrowsers;
1098 browser = new AndroidChrome(adbDeviceMapping[id]); 1087 requestBrowser();
1099 } else if (browserName == 'ContentShellOnAndroid') {
1100 browser = new AndroidBrowser(adbDeviceMapping[id],
1101 contentShellOnAndroidConfig,
1102 checkedMode,
1103 configuration['drt']);
1104 } else if (browserName == 'DartiumOnAndroid') {
1105 browser = new AndroidBrowser(adbDeviceMapping[id],
1106 dartiumOnAndroidConfig,
1107 checkedMode,
1108 configuration['dartium']);
1109 } else {
1110 browserStatus.remove(id);
1111 browser = getInstance();
1112 new_id = "BROWSER$browserIdCount";
1113 browserIdCount++;
1114 }
1115 browser.id = new_id;
1116 var status = new BrowserTestingStatus(browser);
1117 browserStatus[new_id] = status;
1118 status.nextTestTimeout = createNextTestTimer(status);
1119 status.timeSinceRestart.start();
1120 browser.start(testingServer.getDriverUrl(new_id)).then((success) {
1121 // We may have started terminating in the mean time.
1122 if (underTermination) {
1123 if (status.nextTestTimeout != null) {
1124 status.nextTestTimeout.cancel();
1125 status.nextTestTimeout = null;
1126 }
1127 browser.close().then((success) {
1128 // We should never hit this, print it out.
1129 if (!success) {
1130 print("Could not kill browser ($id) started due to timeout");
1131 }
1132 });
1133 return;
1134 }
1135 if (!success) {
1136 // TODO(ricow): Handle this better.
1137 print("This is bad, should never happen, could not start browser");
1138 exit(1);
1139 }
1140 });
1141 } 1088 }
1142 1089
1143 BrowserTest getNextTest(String browserId) { 1090 BrowserTest getNextTest(String browserId) {
1091 if (startingBrowserId == browserId) startingBrowserId = null;
1144 var status = browserStatus[browserId]; 1092 var status = browserStatus[browserId];
1145 if (status == null) return null; 1093 if (status == null) return null;
1146 if (status.nextTestTimeout != null) { 1094 if (status.nextTestTimeout != null) {
1147 status.nextTestTimeout.cancel(); 1095 status.nextTestTimeout.cancel();
1148 status.nextTestTimeout = null; 1096 status.nextTestTimeout = null;
1149 } 1097 }
1150 if (testQueue.isEmpty) return null; 1098 if (testQueue.isEmpty) return null;
1151 1099
1152 // We are currently terminating this browser, don't start a new test. 1100 // We are currently terminating this browser, don't start a new test.
1153 if (status.timeout) return null; 1101 if (status.timeout) return null;
1154 1102
1155 // Restart content_shell and dartium on Android if they have been 1103 // Restart Internet Explorer if it has been
1156 // running for longer than RESTART_BROWSER_INTERVAL. The tests have 1104 // running for longer than RESTART_BROWSER_INTERVAL. The tests have
1157 // had flaky timeouts, and this may help. 1105 // had flaky timeouts, and this may help.
1158 if ((browserName == 'ContentShellOnAndroid' || 1106 if ((browserName == 'ie10' ||
1159 browserName == 'DartiumOnAndroid' ||
1160 browserName == 'ie10' ||
1161 browserName == 'ie11') && 1107 browserName == 'ie11') &&
1162 status.timeSinceRestart.elapsed > RESTART_BROWSER_INTERVAL) { 1108 status.timeSinceRestart.elapsed > RESTART_BROWSER_INTERVAL) {
1163 var id = status.browser.id; 1109 var id = status.browser.id;
1164 // Reset stopwatch so we don't trigger again before restarting. 1110 // Reset stopwatch so we don't trigger again before restarting.
1165 status.timeout = true; 1111 status.timeout = true;
1166 status.browser.close().then((_) { 1112 status.browser.close().then((_) {
1167 // We don't want to start a new browser if we are terminating. 1113 // We don't want to start a new browser if we are terminating.
1168 if (underTermination) return; 1114 if (underTermination) return;
1169 restartBrowser(id); 1115 removeBrowser(id);
1170 }); 1116 });
1171 // Don't send a test to the browser we are restarting. 1117 // Don't send a test to the browser we are restarting.
1172 return null; 1118 return null;
1173 } 1119 }
1174 1120
1175 BrowserTest test = testQueue.removeLast(); 1121 BrowserTest test = testQueue.removeLast();
1122 // If our queue isn't empty, try starting more browsers
1123 if (testQueue.isEmpty) {
1124 lastEmptyTestQueueTime = new DateTime.now();
1125 } else {
1126 requestBrowser();
1127 }
1176 if (status.currentTest == null) { 1128 if (status.currentTest == null) {
1177 status.currentTest = test; 1129 status.currentTest = test;
1178 status.currentTest.lastKnownMessage = ''; 1130 status.currentTest.lastKnownMessage = '';
1179 } else { 1131 } else {
1180 // TODO(ricow): Handle this better. 1132 // TODO(ricow): Handle this better.
1181 print("Browser requested next test before reporting previous result"); 1133 print("Browser requested next test before reporting previous result");
1182 print("This happened for browser $browserId"); 1134 print("This happened for browser $browserId");
1183 print("Old test was: ${status.currentTest.url}"); 1135 print("Old test was: ${status.currentTest.url}");
1184 print("The test before that was: ${status.lastTest.url}"); 1136 print("The test before that was: ${status.lastTest.url}");
1185 print("Timed out tests:"); 1137 print("Timed out tests:");
1186 for (var v in timedOut) { 1138 for (var v in timedOut) {
1187 print(" $v"); 1139 print(" $v");
1188 } 1140 }
1189 exit(1); 1141 exit(1);
1190 } 1142 }
1191 1143
1192 status.currentTest.timeoutTimer = createTimeoutTimer(test, status); 1144 status.currentTest.timeoutTimer = createTimeoutTimer(test, status);
1193 status.currentTest.stopwatch = new Stopwatch()..start(); 1145 status.currentTest.stopwatch = new Stopwatch()..start();
1194 1146
1195 // Reset the test specific output information (stdout, stderr) on the 1147 // Reset the test specific output information (stdout, stderr) on the
1196 // browser, since a new test is being started. 1148 // browser, since a new test is being started.
1197 status.browser.resetTestBrowserOutput(); 1149 status.browser.resetTestBrowserOutput();
1198 status.browser.logBrowserInfoToTestBrowserOutput(); 1150 status.browser.logBrowserInfoToTestBrowserOutput();
1199 if (browserName.contains('OnAndroid')) {
1200 DebugLogger.info("Browser $browserId getting test ${test.url}");
1201 }
1202
1203 return test; 1151 return test;
1204 } 1152 }
1205 1153
1206 Timer createTimeoutTimer(BrowserTest test, BrowserTestingStatus status) { 1154 Timer createTimeoutTimer(BrowserTest test, BrowserTestingStatus status) {
1207 return new Timer(new Duration(seconds: test.timeout), 1155 return new Timer(new Duration(seconds: test.timeout),
1208 () { handleTimeout(status); }); 1156 () { handleTimeout(status); });
1209 } 1157 }
1210 1158
1211 Timer createNextTestTimer(BrowserTestingStatus status) { 1159 Timer createNextTestTimer(BrowserTestingStatus status) {
1212 return new Timer(BrowserTestRunner.NEXT_TEST_TIMEOUT, 1160 return new Timer(BrowserTestRunner.NEXT_TEST_TIMEOUT,
1213 () { handleNextTestTimeout(status); }); 1161 () { handleNextTestTimeout(status); });
1214 } 1162 }
1215 1163
1216 void handleNextTestTimeout(status) { 1164 void handleNextTestTimeout(status) {
1217 DebugLogger.warning( 1165 DebugLogger.warning(
1218 "Browser timed out before getting next test. Restarting"); 1166 "Browser timed out before getting next test. Restarting");
1167 if (startingBrowserId == status.browser.id) startingBrowserId = null;
ahe 2016/04/05 13:19:41 ?
Bill Hesse 2016/04/05 14:51:22 This is covered by the call to removeBrowser below
1219 if (status.timeout) return; 1168 if (status.timeout) return;
1220 numBrowserGetTestTimeouts++; 1169 numBrowserGetTestTimeouts++;
1221 if (numBrowserGetTestTimeouts >= MAX_NEXT_TEST_TIMEOUTS) { 1170 if (numBrowserGetTestTimeouts >= MAX_NEXT_TEST_TIMEOUTS) {
1222 DebugLogger.error( 1171 DebugLogger.error(
1223 "Too many browser timeouts before getting next test. Terminating"); 1172 "Too many browser timeouts before getting next test. Terminating");
1224 terminate().then((_) => exit(1)); 1173 terminate().then((_) => exit(1));
1225 } else { 1174 } else {
1226 status.timeout = true; 1175 status.timeout = true;
1227 status.browser.close().then((_) => restartBrowser(status.browser.id)); 1176 status.browser.close().then((_) => removeBrowser(status.browser.id));
1228 } 1177 }
1229 } 1178 }
1230 1179
1231 void queueTest(BrowserTest test) { 1180 void queueTest(BrowserTest test) {
1232 testQueue.add(test); 1181 testQueue.add(test);
1182 requestBrowser();
1233 } 1183 }
1234 1184
1235 void printDoubleReportingTests() { 1185 void printDoubleReportingTests() {
1236 if (doubleReportingOutputs.length == 0) return; 1186 if (doubleReportingOutputs.length == 0) return;
1237 // TODO(ricow): die on double reporting. 1187 // TODO(ricow): die on double reporting.
1238 // Currently we just report this here, we could have a callback to the 1188 // Currently we just report this here, we could have a callback to the
1239 // encapsulating environment. 1189 // encapsulating environment.
1240 print(""); 1190 print("");
1241 print("Double reporting tests"); 1191 print("Double reporting tests");
1242 for (var id in doubleReportingOutputs.keys) { 1192 for (var id in doubleReportingOutputs.keys) {
1243 print(" ${testCache[id]}"); 1193 print(" ${testCache[id]}");
1244 } 1194 }
1245 1195
1246 DebugLogger.warning("Double reporting tests:"); 1196 DebugLogger.warning("Double reporting tests:");
1247 for (var id in doubleReportingOutputs.keys) { 1197 for (var id in doubleReportingOutputs.keys) {
1248 DebugLogger.warning("${testCache[id]}, output: "); 1198 DebugLogger.warning("${testCache[id]}, output: ");
1249 DebugLogger.warning("${doubleReportingOutputs[id]}"); 1199 DebugLogger.warning("${doubleReportingOutputs[id]}");
1250 DebugLogger.warning(""); 1200 DebugLogger.warning("");
1251 DebugLogger.warning(""); 1201 DebugLogger.warning("");
1252 } 1202 }
1253 } 1203 }
1254 1204
1255 Future<bool> terminate() { 1205 // TODO(26191): Call a unified fatalError(), that shuts down all subprocesses.
1206 // This just kills the browsers in this BrowserTestRunner instance.
1207 Future terminate() async {
1256 var browsers = []; 1208 var browsers = [];
1257 underTermination = true; 1209 underTermination = true;
1258 testingServer.underTermination = true; 1210 testingServer.underTermination = true;
1259 for (BrowserTestingStatus status in browserStatus.values) { 1211 for (BrowserTestingStatus status in browserStatus.values) {
1260 browsers.add(status.browser); 1212 browsers.add(status.browser);
1261 if (status.nextTestTimeout != null) { 1213 if (status.nextTestTimeout != null) {
1262 status.nextTestTimeout.cancel(); 1214 status.nextTestTimeout.cancel();
1263 status.nextTestTimeout = null; 1215 status.nextTestTimeout = null;
1264 } 1216 }
1265 } 1217 }
1266 // Success if all the browsers closed successfully. 1218 for (Browser b in browsers) {
1267 bool success = true; 1219 await b.close();
1268 Future closeBrowser(Browser b) {
1269 return b.close().then((bool closeSucceeded) {
1270 if (!closeSucceeded) {
1271 success = false;
1272 }
1273 });
1274 } 1220 }
1275 return Future.forEach(browsers, closeBrowser).then((_) { 1221 testingServer.errorReportingServer.close();
1276 testingServer.errorReportingServer.close(); 1222 printDoubleReportingTests();
1277 printDoubleReportingTests();
1278 return success;
1279 });
1280 }
1281
1282 Browser getInstance() {
1283 if (browserName == 'ff') browserName = 'firefox';
1284 var path = Locations.getBrowserLocation(browserName, configuration);
1285 var browser = new Browser.byName(browserName, path, checkedMode);
1286 browser.logger = logger;
1287 return browser;
1288 } 1223 }
1289 } 1224 }
1290 1225
1291 class BrowserTestingServer { 1226 class BrowserTestingServer {
1292 final Map configuration; 1227 final Map configuration;
1293 /// Interface of the testing server: 1228 /// Interface of the testing server:
1294 /// 1229 ///
1295 /// GET /driver/BROWSER_ID -- This will get the driver page to fetch 1230 /// GET /driver/BROWSER_ID -- This will get the driver page to fetch
1296 /// and run tests ... 1231 /// and run tests ...
1297 /// GET /next_test/BROWSER_ID -- returns "WAIT" "TERMINATE" or "url#id" 1232 /// GET /next_test/BROWSER_ID -- returns "WAIT" "TERMINATE" or "url#id"
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
1796 </div> 1731 </div>
1797 <div id="embedded_iframe_div" class="test box"> 1732 <div id="embedded_iframe_div" class="test box">
1798 <iframe style="width:100%;height:100%;" id="embedded_iframe"></iframe> 1733 <iframe style="width:100%;height:100%;" id="embedded_iframe"></iframe>
1799 </div> 1734 </div>
1800 </body> 1735 </body>
1801 </html> 1736 </html>
1802 """; 1737 """;
1803 return driverContent; 1738 return driverContent;
1804 } 1739 }
1805 } 1740 }
OLDNEW
« no previous file with comments | « no previous file | tools/testing/dart/test_runner.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698