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

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

Issue 218683009: test.dart: Add timeout for browsers that are started but do not fetch tests. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add null check. Created 6 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 | Annotate | Revision Log
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; 7 import "dart:convert" show LineSplitter, UTF8;
8 import "dart:core"; 8 import "dart:core";
9 import "dart:io"; 9 import "dart:io";
10 10
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 624
625 625
626 class Firefox extends Browser { 626 class Firefox extends Browser {
627 static const String enablePopUp = 627 static const String enablePopUp =
628 'user_pref("dom.disable_open_during_load", false);'; 628 'user_pref("dom.disable_open_during_load", false);';
629 static const String disableDefaultCheck = 629 static const String disableDefaultCheck =
630 'user_pref("browser.shell.checkDefaultBrowser", false);'; 630 'user_pref("browser.shell.checkDefaultBrowser", false);';
631 static const String disableScriptTimeLimit = 631 static const String disableScriptTimeLimit =
632 'user_pref("dom.max_script_run_time", 0);'; 632 'user_pref("dom.max_script_run_time", 0);';
633 633
634 Future _createPreferenceFile(var path) { 634 void _createPreferenceFile(var path) {
635 var file = new File("${path.toString()}/user.js"); 635 var file = new File("${path.toString()}/user.js");
636 var randomFile = file.openSync(mode: FileMode.WRITE); 636 var randomFile = file.openSync(mode: FileMode.WRITE);
637 randomFile.writeStringSync(enablePopUp); 637 randomFile.writeStringSync(enablePopUp);
638 randomFile.writeStringSync(disableDefaultCheck); 638 randomFile.writeStringSync(disableDefaultCheck);
639 randomFile.writeStringSync(disableScriptTimeLimit); 639 randomFile.writeStringSync(disableScriptTimeLimit);
640 randomFile.close(); 640 randomFile.close();
641 } 641 }
642 642
643 Future<bool> start(String url) { 643 Future<bool> start(String url) {
644 _logEvent("Starting firefox browser on: $url"); 644 _logEvent("Starting firefox browser on: $url");
(...skipping 30 matching lines...) Expand all
675 */ 675 */
676 class BrowserTestingStatus { 676 class BrowserTestingStatus {
677 Browser browser; 677 Browser browser;
678 BrowserTest currentTest; 678 BrowserTest currentTest;
679 679
680 // This is currently not used for anything except for error reporting. 680 // This is currently not used for anything except for error reporting.
681 // Given the usefulness of this in debugging issues this should not be 681 // Given the usefulness of this in debugging issues this should not be
682 // removed even when we have really stable system. 682 // removed even when we have really stable system.
683 BrowserTest lastTest; 683 BrowserTest lastTest;
684 bool timeout = false; 684 bool timeout = false;
685 Timer nextTestTimeout;
686
685 BrowserTestingStatus(Browser this.browser); 687 BrowserTestingStatus(Browser this.browser);
686 } 688 }
687 689
688 690
689 /** 691 /**
690 * Describes a single test to be run int the browser. 692 * Describes a single test to be run int the browser.
691 */ 693 */
692 class BrowserTest { 694 class BrowserTest {
693 // TODO(ricow): Add timeout callback instead of the string passing hack. 695 // TODO(ricow): Add timeout callback instead of the string passing hack.
694 Function doneCallback; 696 Function doneCallback;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 this.browserOutput, {this.didTimeout: false}); 731 this.browserOutput, {this.didTimeout: false});
730 } 732 }
731 733
732 /** 734 /**
733 * Encapsulates all the functionality for running tests in browsers. 735 * Encapsulates all the functionality for running tests in browsers.
734 * The interface is rather simple. After starting, the runner tests 736 * The interface is rather simple. After starting, the runner tests
735 * are simply added to the queue and a the supplied callbacks are called 737 * are simply added to the queue and a the supplied callbacks are called
736 * whenever a test completes. 738 * whenever a test completes.
737 */ 739 */
738 class BrowserTestRunner { 740 class BrowserTestRunner {
741 static const int MAX_NEXT_TEST_TIMEOUTS = 10;
742 static const Duration NEXT_TEST_TIMEOUT = const Duration(seconds: 60);
743
739 final Map globalConfiguration; 744 final Map globalConfiguration;
740 final bool checkedMode; // needed for dartium 745 final bool checkedMode; // needed for dartium
741 746
742 String localIp; 747 String localIp;
743 String browserName; 748 String browserName;
744 int maxNumBrowsers; 749 int maxNumBrowsers;
745 // Used to send back logs from the browser (start, stop etc) 750 // Used to send back logs from the browser (start, stop etc)
746 Function logger; 751 Function logger;
747 int browserIdCount = 0; 752 int browserIdCount = 0;
748 753
749 bool underTermination = false; 754 bool underTermination = false;
755 int numBrowserGetTestTimeouts = 0;
750 756
751 List<BrowserTest> testQueue = new List<BrowserTest>(); 757 List<BrowserTest> testQueue = new List<BrowserTest>();
752 Map<String, BrowserTestingStatus> browserStatus = 758 Map<String, BrowserTestingStatus> browserStatus =
753 new Map<String, BrowserTestingStatus>(); 759 new Map<String, BrowserTestingStatus>();
754 760
755 var adbDeviceMapping = new Map<String, AdbDevice>(); 761 var adbDeviceMapping = new Map<String, AdbDevice>();
756 // This cache is used to guarantee that we never see double reporting. 762 // This cache is used to guarantee that we never see double reporting.
757 // If we do we need to provide developers with this information. 763 // If we do we need to provide developers with this information.
758 // We don't add urls to the cache until we have run it. 764 // We don't add urls to the cache until we have run it.
759 Map<int, String> testCache = new Map<int, String>(); 765 Map<int, String> testCache = new Map<int, String>();
(...skipping 26 matching lines...) Expand all
786 testingServer.testDoneCallBack = handleResults; 792 testingServer.testDoneCallBack = handleResults;
787 testingServer.testStatusUpdateCallBack = handleStatusUpdate; 793 testingServer.testStatusUpdateCallBack = handleStatusUpdate;
788 testingServer.testStartedCallBack = handleStarted; 794 testingServer.testStartedCallBack = handleStarted;
789 testingServer.nextTestCallBack = getNextTest; 795 testingServer.nextTestCallBack = getNextTest;
790 return getBrowsers().then((browsers) { 796 return getBrowsers().then((browsers) {
791 var futures = []; 797 var futures = [];
792 for (var browser in browsers) { 798 for (var browser in browsers) {
793 var url = testingServer.getDriverUrl(browser.id); 799 var url = testingServer.getDriverUrl(browser.id);
794 var future = browser.start(url).then((success) { 800 var future = browser.start(url).then((success) {
795 if (success) { 801 if (success) {
796 browserStatus[browser.id] = new BrowserTestingStatus(browser); 802 var status = new BrowserTestingStatus(browser);
803 browserStatus[browser.id] = status;
804 status.nextTestTimeout = createNextTestTimer(status);
797 } 805 }
798 return success; 806 return success;
799 }); 807 });
800 futures.add(future); 808 futures.add(future);
801 } 809 }
802 return Future.wait(futures).then((values) { 810 return Future.wait(futures).then((values) {
803 return !values.contains(false); 811 return !values.contains(false);
804 }); 812 });
805 }); 813 });
806 }); 814 });
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
869 877
870 if (status.currentTest.id != testId) { 878 if (status.currentTest.id != testId) {
871 print("Expected test id ${status.currentTest.id} for" 879 print("Expected test id ${status.currentTest.id} for"
872 "${status.currentTest.url}"); 880 "${status.currentTest.url}");
873 print("Got test id ${testId}"); 881 print("Got test id ${testId}");
874 print("Last test id was ${status.lastTest.id} for " 882 print("Last test id was ${status.lastTest.id} for "
875 "${status.currentTest.url}"); 883 "${status.currentTest.url}");
876 throw("This should never happen, wrong test id"); 884 throw("This should never happen, wrong test id");
877 } 885 }
878 testCache[testId] = status.currentTest.url; 886 testCache[testId] = status.currentTest.url;
879 Stopwatch watch = new Stopwatch()..start();
880 887
881 // Report that the test is finished now 888 // Report that the test is finished now
882 var browserTestOutput = new BrowserTestOutput( 889 var browserTestOutput = new BrowserTestOutput(
883 status.currentTest.delayUntilTestStarted, 890 status.currentTest.delayUntilTestStarted,
884 status.currentTest.stopwatch.elapsed, 891 status.currentTest.stopwatch.elapsed,
885 output, 892 output,
886 status.browser.testBrowserOutput); 893 status.browser.testBrowserOutput);
887 status.currentTest.doneCallback(browserTestOutput); 894 status.currentTest.doneCallback(browserTestOutput);
888 895
889 watch.stop();
890 status.lastTest = status.currentTest; 896 status.lastTest = status.currentTest;
891 status.currentTest = null; 897 status.currentTest = null;
898 status.nextTestTimeout = createNextTestTimer(status);
892 } else { 899 } else {
893 print("\nThis is bad, should never happen, handleResult no test"); 900 print("\nThis is bad, should never happen, handleResult no test");
894 print("URL: ${status.lastTest.url}"); 901 print("URL: ${status.lastTest.url}");
895 print(output); 902 print(output);
896 terminate().then((_) { 903 terminate().then((_) {
897 exit(1); 904 exit(1);
898 }); 905 });
899 } 906 }
900 } 907 }
901 908
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
944 status.currentTest.delayUntilTestStarted, 951 status.currentTest.delayUntilTestStarted,
945 status.currentTest.stopwatch.elapsed, 952 status.currentTest.stopwatch.elapsed,
946 lastKnownMessage, 953 lastKnownMessage,
947 status.browser.testBrowserOutput, 954 status.browser.testBrowserOutput,
948 didTimeout: true); 955 didTimeout: true);
949 status.currentTest.doneCallback(browserTestOutput); 956 status.currentTest.doneCallback(browserTestOutput);
950 status.currentTest = null; 957 status.currentTest = null;
951 958
952 // We don't want to start a new browser if we are terminating. 959 // We don't want to start a new browser if we are terminating.
953 if (underTermination) return; 960 if (underTermination) return;
954 var browser; 961 restartBrowser(id);
955 var new_id = id; 962 });
956 if (browserName == 'chromeOnAndroid') { 963 }
957 browser = new AndroidChrome(adbDeviceMapping[id]); 964
958 } else if (browserName == 'ContentShellOnAndroid') { 965 void restartBrowser(String id) {
959 browser = new AndroidBrowser(adbDeviceMapping[id], 966 var browser;
960 contentShellOnAndroidConfig, 967 var new_id = id;
961 checkedMode); 968 if (browserName == 'chromeOnAndroid') {
962 } else if (browserName == 'DartiumOnAndroid') { 969 browser = new AndroidChrome(adbDeviceMapping[id]);
963 browser = new AndroidBrowser(adbDeviceMapping[id], 970 } else if (browserName == 'ContentShellOnAndroid') {
964 dartiumOnAndroidConfig, 971 browser = new AndroidBrowser(adbDeviceMapping[id],
965 checkedMode); 972 contentShellOnAndroidConfig,
966 } else { 973 checkedMode);
967 browserStatus.remove(id); 974 } else if (browserName == 'DartiumOnAndroid') {
968 browser = getInstance(); 975 browser = new AndroidBrowser(adbDeviceMapping[id],
969 new_id = "BROWSER$browserIdCount"; 976 dartiumOnAndroidConfig,
970 browserIdCount++; 977 checkedMode);
971 browserStatus[new_id] = new BrowserTestingStatus(browser); 978 } else {
979 browserStatus.remove(id);
980 browser = getInstance();
981 new_id = "BROWSER$browserIdCount";
982 browserIdCount++;
983 }
984 browser.id = new_id;
985 var status = new BrowserTestingStatus(browser);
986 browserStatus[new_id] = status;
987 status.nextTestTimeout = createNextTestTimer(status);
988 browser.start(testingServer.getDriverUrl(new_id)).then((success) {
989 // We may have started terminating in the mean time.
990 if (underTermination) {
991 browser.close().then((success) {
992 if (status.nextTestTimeout != null) {
993 status.nextTestTimeout.cancel();
994 status.nextTestTimeout = null;
995 }
kustermann 2014/04/03 12:18:56 You can move the cancelling before browser.close()
996 // We should never hit this, print it out.
997 if (!success) {
998 print("Could not kill browser ($id) started due to timeout");
999 }
1000 });
1001 return;
972 } 1002 }
973 browser.id = new_id; 1003 if (!success) {
974 browser.start(testingServer.getDriverUrl(new_id)).then((success) { 1004 // TODO(ricow): Handle this better.
975 // We may have started terminating in the mean time. 1005 print("This is bad, should never happen, could not start browser");
976 if (underTermination) { 1006 exit(1);
977 browser.close().then((success) { 1007 }
978 // We should never hit this, print it out.
979 if (!success) {
980 print("Could not kill browser ($id) started due to timeout");
981 }
982 });
983 return;
984 }
985 if (success) {
986 browserStatus[browser.id] = new BrowserTestingStatus(browser);
987 } else {
988 // TODO(ricow): Handle this better.
989 print("This is bad, should never happen, could not start browser");
990 exit(1);
991 }
992 });
993 }); 1008 });
994 } 1009 }
995 1010
996 BrowserTest getNextTest(String browserId) { 1011 BrowserTest getNextTest(String browserId) {
997 if (testQueue.isEmpty) return null;
998 var status = browserStatus[browserId]; 1012 var status = browserStatus[browserId];
999 if (status == null) return null; 1013 if (status == null) return null;
1014 if (status.nextTestTimeout != null) {
1015 status.nextTestTimeout.cancel();
1016 status.nextTestTimeout = null;
1017 }
1018 if (testQueue.isEmpty) return null;
1000 1019
1001 // We are currently terminating this browser, don't start a new test. 1020 // We are currently terminating this browser, don't start a new test.
1002 if (status.timeout) return null; 1021 if (status.timeout) return null;
1003 1022
1004 BrowserTest test = testQueue.removeLast(); 1023 BrowserTest test = testQueue.removeLast();
1005 if (status.currentTest == null) { 1024 if (status.currentTest == null) {
1006 status.currentTest = test; 1025 status.currentTest = test;
1007 status.currentTest.lastKnownMessage = ''; 1026 status.currentTest.lastKnownMessage = '';
1008 } else { 1027 } else {
1009 // TODO(ricow): Handle this better. 1028 // TODO(ricow): Handle this better.
(...skipping 11 matching lines...) Expand all
1021 status.currentTest.stopwatch = new Stopwatch()..start(); 1040 status.currentTest.stopwatch = new Stopwatch()..start();
1022 1041
1023 // Reset the test specific output information (stdout, stderr) on the 1042 // Reset the test specific output information (stdout, stderr) on the
1024 // browser since a new test is begin started. 1043 // browser since a new test is begin started.
1025 status.browser.resetTestBrowserOutput(); 1044 status.browser.resetTestBrowserOutput();
1026 1045
1027 return test; 1046 return test;
1028 } 1047 }
1029 1048
1030 Timer createTimeoutTimer(BrowserTest test, BrowserTestingStatus status) { 1049 Timer createTimeoutTimer(BrowserTest test, BrowserTestingStatus status) {
1031 return new Timer( 1050 return new Timer(new Duration(seconds: test.timeout),
1032 new Duration(seconds: test.timeout), () { handleTimeout(status); }); 1051 () { handleTimeout(status); });
1052 }
1053
1054 Timer createNextTestTimer(BrowserTestingStatus status) {
1055 return new Timer(BrowserTestRunner.NEXT_TEST_TIMEOUT,
1056 () { handleNextTestTimeout(status); });
1057 }
1058
1059 void handleNextTestTimeout(status) {
1060 DebugLogger.warning(
1061 "Browser timed out before getting next test. Restarting");
1062 numBrowserGetTestTimeouts++;
1063 if (numBrowserGetTestTimeouts >= MAX_NEXT_TEST_TIMEOUTS) {
1064 DebugLogger.error(
1065 "Too many browser timeouts before getting next test. Terminating");
1066 terminate().then((_) => exit(1));
1067 } else {
1068 status.browser.close().then((_) => restartBrowser(status.browser.id));
1069 }
1033 } 1070 }
1034 1071
1035 void queueTest(BrowserTest test) { 1072 void queueTest(BrowserTest test) {
1036 testQueue.add(test); 1073 testQueue.add(test);
1037 } 1074 }
1038 1075
1039 void printDoubleReportingTests() { 1076 void printDoubleReportingTests() {
1040 if (doubleReportingOutputs.length == 0) return; 1077 if (doubleReportingOutputs.length == 0) return;
1041 // TODO(ricow): die on double reporting. 1078 // TODO(ricow): die on double reporting.
1042 // Currently we just report this here, we could have a callback to the 1079 // Currently we just report this here, we could have a callback to the
(...skipping 12 matching lines...) Expand all
1055 DebugLogger.warning(""); 1092 DebugLogger.warning("");
1056 } 1093 }
1057 } 1094 }
1058 1095
1059 Future<bool> terminate() { 1096 Future<bool> terminate() {
1060 var futures = []; 1097 var futures = [];
1061 underTermination = true; 1098 underTermination = true;
1062 testingServer.underTermination = true; 1099 testingServer.underTermination = true;
1063 for (BrowserTestingStatus status in browserStatus.values) { 1100 for (BrowserTestingStatus status in browserStatus.values) {
1064 futures.add(status.browser.close()); 1101 futures.add(status.browser.close());
1102 if (status.nextTestTimeout != null) {
1103 status.nextTestTimeout.cancel();
1104 status.nextTestTimeout = null;
1105 }
1065 } 1106 }
1066 return Future.wait(futures).then((values) { 1107 return Future.wait(futures).then((values) {
1067 testingServer.httpServer.close(); 1108 testingServer.httpServer.close();
1068 testingServer.errorReportingServer.close(); 1109 testingServer.errorReportingServer.close();
1069 printDoubleReportingTests(); 1110 printDoubleReportingTests();
1070 return !values.contains(false); 1111 return !values.contains(false);
1071 }); 1112 });
1072 } 1113 }
1073 1114
1074 Browser getInstance() { 1115 Browser getInstance() {
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 Dart test driver, number of tests: <div id="number"></div><br> 1494 Dart test driver, number of tests: <div id="number"></div><br>
1454 Currently executing: <div id="currently_executing"></div><br> 1495 Currently executing: <div id="currently_executing"></div><br>
1455 Unhandled error: <div id="unhandled_error"></div> 1496 Unhandled error: <div id="unhandled_error"></div>
1456 <iframe id="embedded_iframe"></iframe> 1497 <iframe id="embedded_iframe"></iframe>
1457 </body> 1498 </body>
1458 </html> 1499 </html>
1459 """; 1500 """;
1460 return driverContent; 1501 return driverContent;
1461 } 1502 }
1462 } 1503 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698