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 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |