Chromium Code Reviews| 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 |