1# Copyright 2014 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4"""Utility script to launch browser-tests on the Chromoting bot.""" 5 6import argparse 7import time 8 9from chromoting_test_utilities import CleanupUserProfileDir 10from chromoting_test_utilities import GetJidFromHostLog 11from chromoting_test_utilities import GetJidListFromTestResults 12from chromoting_test_utilities import InitialiseTestMachineForLinux 13from chromoting_test_utilities import MAX_RETRIES 14from chromoting_test_utilities import PrintHostLogContents 15from chromoting_test_utilities import PROD_DIR_ID 16from chromoting_test_utilities import RunCommandInSubProcess 17from chromoting_test_utilities import TestCaseSetup 18from chromoting_test_utilities import TestMachineCleanup 19 20SUCCESS_INDICATOR = 'SUCCESS: all tests passed.' 21BROWSER_NOT_STARTED_ERROR = ( 22 'Still waiting for the following processes to finish') 23TIME_OUT_INDICATOR = '(TIMED OUT)' 24 25 26def LaunchBTCommand(args, command): 27 """Launches the specified browser-test command. 28 29 Retry if the execution failed because a browser-instance was not launched or 30 because the JID used did not match the host-JID. 31 Args: 32 args: Command line args, used for test-case startup tasks. 33 command: Browser-test command line. 34 35 Returns: 36 host_log_file_names: Array of host logs created for this command, including 37 retries. 38 """ 39 host_log_file_names = [] 40 41 retries = 0 42 host_jid_mismatch = False 43 host_jid = None 44 while retries <= MAX_RETRIES: 45 # TestCaseSetup restarts the me2me host, and sets up user-profile dir. 46 # It returns the file-name of the me2me host log. 47 # If we are attempting to run this test because of a JID-mismatch, don't 48 # restart host. 49 if host_jid_mismatch: 50 # Cleanup user-profile directory, but don't restart host. 51 CleanupUserProfileDir(args) 52 else: 53 host_log_file_names.append(TestCaseSetup(args)) 54 # Parse the me2me host log to obtain the JID that the host registered. 55 host_jid = GetJidFromHostLog(host_log_file_names[retries]) 56 57 results = RunCommandInSubProcess(command) 58 59 # Get the JID used by this test to connect a remote-host, if any. 60 jids_used = GetJidListFromTestResults(results) 61 62 # Check for JID mismatch before checking for test success, so that we may 63 # record instances where a test passed despite a JID mismatch. 64 if jids_used and host_jid.rstrip() not in jids_used: 65 host_jid_mismatch = True 66 print('Host JID mismatch. JID in host log = %s.' % host_jid.rstrip()) 67 print('Host JIDs used by test:') 68 for jid in jids_used: 69 print(jid) 70 71 if host_jid_mismatch: 72 # The JID for the remote-host did not match the JID that was used for this 73 # execution of the test. This happens because of a replication delay in 74 # updating all instances of the Chromoting Directory Server. To 75 # work-around this, sleep for 30s, which, based off a recent (08/2015) 76 # query for average replication delay for Chromoting, should be sufficient 77 # for the current JID value to have fully propagated. 78 retries += 1 79 time.sleep(30) 80 continue 81 if jids_used: 82 print('JID used by test matched me2me host JID: %s' % host_jid) 83 else: 84 # There wasn't a mismatch and no JIDs were returned. If no JIDs were 85 # returned, that means the test didn't use any JIDs, so there is nothing 86 # further for us to do. 87 pass 88 89 if SUCCESS_INDICATOR in results: 90 break 91 92 # Sometimes, during execution of browser-tests, a browser instance is 93 # not started and the test times out. See http://crbug/480025. 94 # To work around it, check if this execution failed owing to that 95 # problem and retry. 96 # There are 2 things to look for in the results: 97 # A line saying "Still waiting for the following processes to finish", 98 # and, because sometimes that line gets logged even if the test 99 # eventually passes, we'll also look for "(TIMED OUT)", before retrying. 100 if BROWSER_NOT_STARTED_ERROR in results and TIME_OUT_INDICATOR in results: 101 print('Browser-instance not started (http://crbug/480025). Retrying.') 102 else: 103 print('Test failed for unknown reason. Retrying.') 104 105 retries += 1 106 107 # Check that the test passed. 108 test_failure = False 109 failing_tests = '' 110 if SUCCESS_INDICATOR not in results: 111 test_failure = True 112 # Add this command-line to list of tests that failed. 113 failing_tests = command 114 115 return host_log_file_names, test_failure, failing_tests 116 117 118def run_tests(args): 119 120 InitialiseTestMachineForLinux(args.cfg_file) 121 122 host_log_files = [] 123 have_test_failure = False 124 all_failing_tests = '' 125 with open(args.commands_file) as f: 126 for line in f: 127 # Replace the PROD_DIR value in the command-line with 128 # the passed in value. 129 line = line.replace(PROD_DIR_ID, args.prod_dir) 130 # Launch specified command line for test. 131 log_files, test_failure, failing_tests = LaunchBTCommand(args, line) 132 host_log_files.extend(log_files) 133 have_test_failure = have_test_failure or test_failure 134 all_failing_tests += failing_tests 135 136 # All tests completed. Include host-logs in the test results. 137 PrintHostLogContents(host_log_files) 138 139 return host_log_files, have_test_failure, all_failing_tests 140 141 142def main(): 143 parser = argparse.ArgumentParser() 144 parser.add_argument('-f', 145 '--commands_file', 146 help='path to file listing commands to be launched.') 147 parser.add_argument('-p', 148 '--prod_dir', 149 help='path to folder having product and test binaries.') 150 parser.add_argument('-c', '--cfg_file', help='path to test host config file.') 151 parser.add_argument('--me2me_manifest_file', 152 help='path to me2me host manifest file.') 153 parser.add_argument('--it2me_manifest_file', 154 help='path to it2me host manifest file.') 155 parser.add_argument( 156 '-u', 157 '--user_profile_dir', 158 help='path to user-profile-dir, used by connect-to-host tests.') 159 command_line_args = parser.parse_args() 160 host_logs = '' 161 try: 162 host_logs, had_test_failure, failing_tests = run_tests(command_line_args) 163 if had_test_failure: 164 print('++++++++++AT LEAST 1 TEST FAILED++++++++++') 165 print(failing_tests.rstrip('\n')) 166 print('++++++++++++++++++++++++++++++++++++++++++') 167 raise Exception('At least one test failed.') 168 finally: 169 # Stop host and cleanup user-profile-dir. 170 TestMachineCleanup(command_line_args.user_profile_dir, host_logs) 171 172 173if __name__ == '__main__': 174 main() 175