run_reliability_tests.py revision 17f8fa6b24da34724b4497622f374b27f3041e1c
1#!/usr/bin/python2.4 2 3"""Run reliability tests using Android instrumentation. 4 5 A test file consists of list web sites to test is needed as a parameter 6 7 Usage: 8 run_reliability_tests.py path/to/url/list 9""" 10 11import logging 12import optparse 13import os 14import subprocess 15import sys 16import time 17 18TEST_LIST_FILE = "/sdcard/android/reliability_tests_list.txt" 19TEST_STATUS_FILE = "/sdcard/android/reliability_running_test.txt" 20TEST_TIMEOUT_FILE = "/sdcard/android/reliability_timeout_test.txt" 21HTTP_URL_FILE = "urllist_http" 22HTTPS_URL_FILE = "urllist_https" 23NUM_URLS = 25 24 25 26def DumpRenderTreeFinished(adb_cmd): 27 """Check if DumpRenderTree finished running. 28 29 Args: 30 adb_cmd: adb command string 31 32 Returns: 33 True if DumpRenderTree has finished, False otherwise 34 """ 35 36 # pull test status file and look for "#DONE" 37 shell_cmd_str = adb_cmd + " shell cat " + TEST_STATUS_FILE 38 adb_output = subprocess.Popen(shell_cmd_str, 39 shell=True, stdout=subprocess.PIPE, 40 stderr=subprocess.PIPE).communicate()[0] 41 return adb_output.strip() == "#DONE" 42 43 44def RemoveDeviceFile(adb_cmd, file_name): 45 shell_cmd_str = adb_cmd + " shell rm " + file_name 46 subprocess.Popen(shell_cmd_str, 47 shell=True, stdout=subprocess.PIPE, 48 stderr=subprocess.PIPE).communicate() 49 50 51def Bugreport(url, bugreport_dir, adb_cmd): 52 """Pull a bugreport from the device.""" 53 bugreport_filename = "%s/reliability_bugreport_%d.txt" % (bugreport_dir, 54 int(time.time())) 55 56 # prepend the report with url 57 handle = open(bugreport_filename, "w") 58 handle.writelines("Bugreport for crash in url - %s\n\n" % url) 59 handle.close() 60 61 cmd = "%s bugreport >> %s" % (adb_cmd, bugreport_filename) 62 os.system(cmd) 63 64 65def main(options, args): 66 """Send the url list to device and start testing, restart if crashed.""" 67 68 # Set up logging format. 69 log_level = logging.INFO 70 if options.verbose: 71 log_level = logging.DEBUG 72 logging.basicConfig(level=log_level, 73 format="%(message)s") 74 75 # Include all tests if none are specified. 76 if not args: 77 print "Missing URL list file" 78 sys.exit(1) 79 else: 80 path = args[0] 81 82 if not options.crash_file: 83 print "Missing crash file name, use --crash-file to specify" 84 sys.exit(1) 85 else: 86 crashed_file = options.crash_file 87 88 if not options.timeout_file: 89 print "Missing timeout file, use --timeout-file to specify" 90 sys.exit(1) 91 else: 92 timedout_file = options.timeout_file 93 94 if not options.delay: 95 manual_delay = 0 96 else: 97 manual_delay = options.delay 98 99 if not options.bugreport: 100 bugreport_dir = "." 101 else: 102 bugreport_dir = options.bugreport 103 if not os.path.exists(bugreport_dir): 104 os.makedirs(bugreport_dir) 105 if not os.path.isdir(bugreport_dir): 106 logging.error("Cannot create results dir: " + bugreport_dir) 107 sys.exit(1) 108 109 adb_cmd = "adb " 110 if options.adb_options: 111 adb_cmd += options.adb_options + " " 112 113 # push url list to device 114 test_cmd = adb_cmd + " push \"" + path + "\" \"" + TEST_LIST_FILE + "\"" 115 proc = subprocess.Popen(test_cmd, shell=True, 116 stdout=subprocess.PIPE, 117 stderr=subprocess.PIPE) 118 (adb_output, adb_error) = proc.communicate() 119 if proc.returncode != 0: 120 logging.error("failed to push url list to device.") 121 logging.error(adb_output) 122 logging.error(adb_error) 123 sys.exit(1) 124 125 # clean up previous results 126 RemoveDeviceFile(adb_cmd, TEST_STATUS_FILE) 127 RemoveDeviceFile(adb_cmd, TEST_TIMEOUT_FILE) 128 129 logging.info("Running the test ...") 130 131 # Count crashed tests. 132 crashed_tests = [] 133 134 if options.time_out_ms: 135 timeout_ms = options.time_out_ms 136 137 # Run test until it's done 138 test_cmd_prefix = adb_cmd + " shell am instrument" 139 test_cmd_postfix = " -w com.android.dumprendertree/.LayoutTestsAutoRunner" 140 141 # Call ReliabilityTestsAutoTest#startReliabilityTests 142 test_cmd = (test_cmd_prefix + " -e class " 143 "com.android.dumprendertree.ReliabilityTest#" 144 "runReliabilityTest -e timeout %s -e delay %s %s" % 145 (str(timeout_ms), str(manual_delay), test_cmd_postfix)) 146 147 adb_output = subprocess.Popen(test_cmd, shell=True, 148 stdout=subprocess.PIPE, 149 stderr=subprocess.PIPE).communicate()[0] 150 while not DumpRenderTreeFinished(adb_cmd): 151 logging.error("DumpRenderTree exited before all URLs are visited.") 152 shell_cmd_str = adb_cmd + " shell cat " + TEST_STATUS_FILE 153 crashed_test = subprocess.Popen(shell_cmd_str, shell=True, 154 stdout=subprocess.PIPE).communicate()[0] 155 logging.info(crashed_test + " CRASHED") 156 crashed_tests.append(crashed_test) 157 Bugreport(crashed_test, bugreport_dir, adb_cmd) 158 logging.info("Resuming reliability test runner...") 159 160 adb_output = subprocess.Popen(test_cmd, shell=True, stdout=subprocess.PIPE, 161 stderr=subprocess.PIPE).communicate()[0] 162 163 if (adb_output.find("INSTRUMENTATION_FAILED") != -1 or 164 adb_output.find("Process crashed.") != -1): 165 logging.error("Error happened : " + adb_output) 166 sys.exit(1) 167 168 logging.info(adb_output) 169 logging.info("Done\n") 170 171 if crashed_tests: 172 file_handle = open(crashed_file, "w") 173 file_handle.writelines("\n".join(crashed_tests)) 174 logging.info("Crashed URL list stored in: " + crashed_file) 175 file_handle.close() 176 else: 177 logging.info("No crash found.") 178 179 test_cmd = (adb_cmd + "pull \"" + TEST_TIMEOUT_FILE + "\" \"" 180 + timedout_file + "\"") 181 182 subprocess.Popen(test_cmd, shell=True, stdout=subprocess.PIPE, 183 stderr=subprocess.PIPE).communicate() 184 185 186if "__main__" == __name__: 187 option_parser = optparse.OptionParser() 188 option_parser.add_option("-t", "--time-out-ms", 189 default=60000, 190 help="set the timeout for each test") 191 option_parser.add_option("-v", "--verbose", action="store_true", 192 default=False, 193 help="include debug-level logging") 194 option_parser.add_option("-a", "--adb-options", 195 default=None, 196 help="pass options to adb, such as -d -e, etc") 197 option_parser.add_option("-c", "--crash-file", 198 default="reliability_crashed_sites.txt", 199 help="the list of sites that cause browser to crash") 200 option_parser.add_option("-f", "--timeout-file", 201 default="reliability_timedout_sites.txt", 202 help="the list of sites that timedout during test") 203 option_parser.add_option("-d", "--delay", 204 default=0, 205 help="add a manual delay between pages (in ms)") 206 option_parser.add_option("-b", "--bugreport", 207 default=".", 208 help="the directory to store bugreport for crashes") 209 opts, arguments = option_parser.parse_args() 210 main(opts, arguments) 211