Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file |
| 3 | # for details. All rights reserved. Use of this source code is governed by a |
| 4 | # BSD-style license that can be found in the LICENSE file. |
| 5 | |
| 6 | # Run all internal tests, archive result to cloud storage. |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 7 | # In the continuous operation flow we have a tester continuously checking |
| 8 | # a specific cloud storage location for a file with a git hash. |
| 9 | # If the file is there, the tester will remove the file, and add another |
| 10 | # file stating that this is now being run. After successfully running, |
| 11 | # the tester will add yet another file, and remove the last one. |
| 12 | # Complete flow with states: |
| 13 | # 1: |
| 14 | # BOT: |
| 15 | # Add file READY_FOR_TESTING (contains git hash) |
| 16 | # Wait until file TESTING_COMPLETE exists (contains git hash) |
| 17 | # Timeout if no progress for RUN_TIMEOUT |
| 18 | # Cleanup READY_FOR_TESTING and TESTING |
| 19 | # 2: |
| 20 | # TESTER: |
| 21 | # Replace file READY_FOR_TESTING by TESTING (contains git hash) |
| 22 | # Run tests for git hash |
| 23 | # Upload commit specific logs if failures |
| 24 | # Upload git specific overall status file (failed or succeeded) |
| 25 | # Replace file TESTING by TESTING_COMPLETE (contains git hash) |
| 26 | # 3: |
| 27 | # BOT: |
| 28 | # Read overall status |
| 29 | # Delete TESTING_COMPLETE |
| 30 | # Exit based on status |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 31 | |
Rico Wind | ba63dc8 | 2019-03-29 14:33:47 +0100 | [diff] [blame] | 32 | import gradle |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 33 | import optparse |
| 34 | import os |
| 35 | import subprocess |
| 36 | import sys |
| 37 | import time |
| 38 | import utils |
Morten Krogh-Jespersen | f241230 | 2019-10-22 10:18:04 +0200 | [diff] [blame] | 39 | import run_on_app |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 40 | |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 41 | import chrome_data |
| 42 | import iosched_data |
| 43 | import r8_data |
Christoffer Quist Adamsen | 4380de3 | 2021-04-23 06:24:31 +0200 | [diff] [blame] | 44 | import youtube_data |
| 45 | |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 46 | # How often the bot/tester should check state |
| 47 | PULL_DELAY = 30 |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 48 | TEST_RESULT_DIR = 'internal' |
| 49 | |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 50 | # Magic files |
| 51 | READY_FOR_TESTING = 'READY_FOR_TESTING' |
| 52 | TESTING = 'TESTING' |
| 53 | TESTING_COMPLETE = 'TESTING_COMPLETE' |
| 54 | |
| 55 | ALL_MAGIC = [READY_FOR_TESTING, TESTING, TESTING_COMPLETE] |
| 56 | |
| 57 | # Log file names |
| 58 | STDERR = 'stderr' |
| 59 | STDOUT = 'stdout' |
| 60 | EXITCODE = 'exitcode' |
| 61 | TIMED_OUT = 'timed_out' |
| 62 | |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 63 | BENCHMARK_APPS = [chrome_data, iosched_data, r8_data, youtube_data] |
Morten Krogh-Jespersen | 6cd9f1d | 2019-10-09 14:01:04 +0200 | [diff] [blame] | 64 | |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 65 | def find_min_xmx_command(app_data): |
| 66 | record = app_data.GetMemoryData(app_data.GetLatestVersion()) |
Jinseong Jeon | d28cb58 | 2019-10-15 00:01:40 -0700 | [diff] [blame] | 67 | assert record['find-xmx-min'] < record['find-xmx-max'] |
| 68 | assert record['find-xmx-range'] < record['find-xmx-max'] - record['find-xmx-min'] |
Morten Krogh-Jespersen | 6cd9f1d | 2019-10-09 14:01:04 +0200 | [diff] [blame] | 69 | return [ |
| 70 | 'tools/run_on_app.py', |
| 71 | '--compiler=r8', |
| 72 | '--compiler-build=lib', |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 73 | '--app=%s' % app_data.GetName(), |
| 74 | '--version=%s' % app_data.GetLatestVersion(), |
Morten Krogh-Jespersen | 6cd9f1d | 2019-10-09 14:01:04 +0200 | [diff] [blame] | 75 | '--no-debug', |
| 76 | '--no-build', |
| 77 | '--find-min-xmx', |
| 78 | '--find-min-xmx-min-memory=%s' % record['find-xmx-min'], |
| 79 | '--find-min-xmx-max-memory=%s' % record['find-xmx-max'], |
| 80 | '--find-min-xmx-range-size=%s' % record['find-xmx-range'], |
| 81 | '--find-min-xmx-archive'] |
| 82 | |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 83 | def compile_with_memory_max_command(app_data): |
Morten Krogh-Jespersen | a0cc49f | 2020-04-17 08:39:59 +0200 | [diff] [blame] | 84 | # TODO(b/152939233): Remove this special handling when fixed. |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 85 | factor = 1.25 if app_data.GetName() == 'chrome' else 1.15 |
| 86 | record = app_data.GetMemoryData(app_data.GetLatestVersion()) |
Morten Krogh-Jespersen | b042c97 | 2019-11-04 08:57:59 +0100 | [diff] [blame] | 87 | return [] if 'skip-find-xmx-max' in record else [ |
Morten Krogh-Jespersen | 3793dc9 | 2019-10-09 14:48:48 +0200 | [diff] [blame] | 88 | 'tools/run_on_app.py', |
| 89 | '--compiler=r8', |
| 90 | '--compiler-build=lib', |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 91 | '--app=%s' % app_data.GetName(), |
| 92 | '--version=%s' % app_data.GetLatestVersion(), |
Morten Krogh-Jespersen | 3793dc9 | 2019-10-09 14:48:48 +0200 | [diff] [blame] | 93 | '--no-debug', |
| 94 | '--no-build', |
Morten Krogh-Jespersen | a0cc49f | 2020-04-17 08:39:59 +0200 | [diff] [blame] | 95 | '--max-memory=%s' % int(record['oom-threshold'] * factor) |
Morten Krogh-Jespersen | 3793dc9 | 2019-10-09 14:48:48 +0200 | [diff] [blame] | 96 | ] |
| 97 | |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 98 | def compile_with_memory_min_command(app_data): |
| 99 | record = app_data.GetMemoryData(app_data.GetLatestVersion()) |
Morten Krogh-Jespersen | 3793dc9 | 2019-10-09 14:48:48 +0200 | [diff] [blame] | 100 | return [ |
| 101 | 'tools/run_on_app.py', |
| 102 | '--compiler=r8', |
| 103 | '--compiler-build=lib', |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 104 | '--app=%s' % app_data.GetName(), |
| 105 | '--version=%s' % app_data.GetLatestVersion(), |
Morten Krogh-Jespersen | 3793dc9 | 2019-10-09 14:48:48 +0200 | [diff] [blame] | 106 | '--no-debug', |
| 107 | '--no-build', |
| 108 | '--expect-oom', |
Morten Krogh-Jespersen | 092e971 | 2019-10-24 14:06:32 +0200 | [diff] [blame] | 109 | '--max-memory=%s' % int(record['oom-threshold'] * 0.85) |
Morten Krogh-Jespersen | 3793dc9 | 2019-10-09 14:48:48 +0200 | [diff] [blame] | 110 | ] |
| 111 | |
Rico Wind | 6847d13 | 2018-09-26 08:18:48 +0200 | [diff] [blame] | 112 | TEST_COMMANDS = [ |
Morten Krogh-Jespersen | 2243b16 | 2019-01-14 08:40:53 +0100 | [diff] [blame] | 113 | # Run test.py internal testing. |
Rico Wind | e623bf3 | 2019-08-28 09:28:00 +0200 | [diff] [blame] | 114 | ['tools/test.py', '--only_internal', '--slow_tests', |
Rico Wind | 97b0a99 | 2019-08-30 11:09:15 +0200 | [diff] [blame] | 115 | '--java_max_memory_size=8G'], |
Morten Krogh-Jespersen | 2243b16 | 2019-01-14 08:40:53 +0100 | [diff] [blame] | 116 | # Ensure that all internal apps compile. |
Morten Krogh-Jespersen | 82bde82 | 2019-10-09 14:50:35 +0200 | [diff] [blame] | 117 | ['tools/run_on_app.py', '--run-all', '--out=out'], |
Morten Krogh-Jespersen | 6cd9f1d | 2019-10-09 14:01:04 +0200 | [diff] [blame] | 118 | # Find min xmx for selected benchmark apps |
| 119 | ['tools/gradle.py', 'r8lib'], |
Morten Krogh-Jespersen | 561a2e9 | 2019-10-10 11:11:30 +0200 | [diff] [blame] | 120 | ] + (map(find_min_xmx_command, BENCHMARK_APPS) |
| 121 | + map(compile_with_memory_max_command, BENCHMARK_APPS) |
| 122 | + map(compile_with_memory_min_command, BENCHMARK_APPS)) |
Morten Krogh-Jespersen | 3793dc9 | 2019-10-09 14:48:48 +0200 | [diff] [blame] | 123 | |
Rico Wind | 6847d13 | 2018-09-26 08:18:48 +0200 | [diff] [blame] | 124 | # Command timeout, in seconds. |
Rico Wind | f77c5b9 | 2019-06-11 08:50:41 +0200 | [diff] [blame] | 125 | RUN_TIMEOUT = 3600 * 6 |
Rico Wind | f021d83 | 2018-12-13 11:29:22 +0100 | [diff] [blame] | 126 | BOT_RUN_TIMEOUT = RUN_TIMEOUT * len(TEST_COMMANDS) |
Rico Wind | 6847d13 | 2018-09-26 08:18:48 +0200 | [diff] [blame] | 127 | |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 128 | def log(str): |
Rico Wind | ffccab1 | 2018-09-26 12:39:42 +0200 | [diff] [blame] | 129 | print("%s: %s" % (time.strftime("%c"), str)) |
Rico Wind | 1b09c56 | 2019-01-17 08:53:09 +0100 | [diff] [blame] | 130 | sys.stdout.flush() |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 131 | |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 132 | def ParseOptions(): |
| 133 | result = optparse.OptionParser() |
| 134 | result.add_option('--continuous', |
| 135 | help='Continuously run internal tests and post results to GCS.', |
| 136 | default=False, action='store_true') |
Rico Wind | 4fd2dda | 2018-09-26 17:41:45 +0200 | [diff] [blame] | 137 | result.add_option('--print_logs', |
| 138 | help='Fetch logs from gcs and print them, takes the commit to print for.', |
| 139 | default=None) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 140 | result.add_option('--bot', |
| 141 | help='Run in bot mode, i.e., scheduling runs.', |
| 142 | default=False, action='store_true') |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 143 | result.add_option('--archive', |
| 144 | help='Post result to GCS, implied by --continuous', |
| 145 | default=False, action='store_true') |
| 146 | return result.parse_args() |
| 147 | |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 148 | def get_file_contents(): |
| 149 | contents = [] |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 150 | with open(sys.argv[0], 'r') as us: |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 151 | contents.append(us.read()) |
| 152 | for app_data in BENCHMARK_APPS: |
| 153 | with open(app_data.__file__, 'r') as us: |
| 154 | contents.append(us.read()) |
| 155 | return contents |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 156 | |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 157 | def restart_if_new_version(original_contents): |
| 158 | new_contents = get_file_contents() |
| 159 | log('Lengths %s %s' % ( |
| 160 | [len(data) for data in original_contents], |
| 161 | [len(data) for data in new_contents])) |
Rico Wind | 1b52acf | 2021-03-21 12:36:55 +0100 | [diff] [blame] | 162 | log('is main %s ' % utils.is_main()) |
Rico Wind | 1b09c56 | 2019-01-17 08:53:09 +0100 | [diff] [blame] | 163 | # Restart if the script got updated. |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 164 | if new_contents != original_contents: |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 165 | log('Restarting tools/internal_test.py, content changed') |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 166 | os.execv(sys.argv[0], sys.argv) |
| 167 | |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 168 | def ensure_git_clean(): |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 169 | # Ensure clean git repo. |
| 170 | diff = subprocess.check_output(['git', 'diff']) |
| 171 | if len(diff) > 0: |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 172 | log('Local modifications to the git repo, exiting') |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 173 | sys.exit(1) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 174 | |
| 175 | def git_pull(): |
| 176 | ensure_git_clean() |
Rico Wind | 1b52acf | 2021-03-21 12:36:55 +0100 | [diff] [blame] | 177 | subprocess.check_call(['git', 'checkout', 'main']) |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 178 | subprocess.check_call(['git', 'pull']) |
| 179 | return utils.get_HEAD_sha1() |
| 180 | |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 181 | def git_checkout(git_hash): |
| 182 | ensure_git_clean() |
| 183 | # Ensure that we are up to date to get the commit. |
| 184 | git_pull() |
Rico Wind | d7d9106 | 2019-04-29 09:24:10 +0200 | [diff] [blame] | 185 | exitcode = subprocess.call(['git', 'checkout', git_hash]) |
| 186 | if exitcode != 0: |
| 187 | return None |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 188 | return utils.get_HEAD_sha1() |
| 189 | |
| 190 | def get_test_result_dir(): |
Morten Krogh-Jespersen | 0981b72 | 2019-10-09 10:00:33 +0200 | [diff] [blame] | 191 | return os.path.join(utils.R8_TEST_RESULTS_BUCKET, TEST_RESULT_DIR) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 192 | |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 193 | def get_sha_destination(sha): |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 194 | return os.path.join(get_test_result_dir(), sha) |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 195 | |
| 196 | def archive_status(failed): |
| 197 | gs_destination = 'gs://%s' % get_sha_destination(utils.get_HEAD_sha1()) |
Morten Krogh-Jespersen | 0981b72 | 2019-10-09 10:00:33 +0200 | [diff] [blame] | 198 | utils.archive_value('status', gs_destination, failed) |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 199 | |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 200 | def get_status(sha): |
| 201 | gs_destination = 'gs://%s/status' % get_sha_destination(sha) |
| 202 | return utils.cat_file_on_cloud_storage(gs_destination) |
| 203 | |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 204 | def archive_log(stdout, stderr, exitcode, timed_out, cmd): |
| 205 | sha = utils.get_HEAD_sha1() |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 206 | cmd_dir = cmd.replace(' ', '_').replace('/', '_') |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 207 | destination = os.path.join(get_sha_destination(sha), cmd_dir) |
| 208 | gs_destination = 'gs://%s' % destination |
| 209 | url = 'https://storage.cloud.google.com/%s' % destination |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 210 | log('Archiving logs to: %s' % gs_destination) |
Morten Krogh-Jespersen | 0981b72 | 2019-10-09 10:00:33 +0200 | [diff] [blame] | 211 | utils.archive_value(EXITCODE, gs_destination, exitcode) |
| 212 | utils.archive_value(TIMED_OUT, gs_destination, timed_out) |
| 213 | utils.archive_file(STDOUT, gs_destination, stdout) |
| 214 | utils.archive_file(STDERR, gs_destination, stderr) |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 215 | log('Logs available at: %s' % url) |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 216 | |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 217 | def get_magic_file_base_path(): |
| 218 | return 'gs://%s/magic' % get_test_result_dir() |
| 219 | |
| 220 | def get_magic_file_gs_path(name): |
| 221 | return '%s/%s' % (get_magic_file_base_path(), name) |
| 222 | |
| 223 | def get_magic_file_exists(name): |
| 224 | return utils.file_exists_on_cloud_storage(get_magic_file_gs_path(name)) |
| 225 | |
| 226 | def delete_magic_file(name): |
| 227 | utils.delete_file_from_cloud_storage(get_magic_file_gs_path(name)) |
| 228 | |
| 229 | def put_magic_file(name, sha): |
Morten Krogh-Jespersen | 0981b72 | 2019-10-09 10:00:33 +0200 | [diff] [blame] | 230 | utils.archive_value(name, get_magic_file_base_path(), sha) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 231 | |
| 232 | def get_magic_file_content(name, ignore_errors=False): |
| 233 | return utils.cat_file_on_cloud_storage(get_magic_file_gs_path(name), |
| 234 | ignore_errors=ignore_errors) |
| 235 | |
| 236 | def print_magic_file_state(): |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 237 | log('Magic file status:') |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 238 | for magic in ALL_MAGIC: |
| 239 | if get_magic_file_exists(magic): |
| 240 | content = get_magic_file_content(magic, ignore_errors=True) |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 241 | log('%s content: %s' % (magic, content)) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 242 | |
Rico Wind | 4fd2dda | 2018-09-26 17:41:45 +0200 | [diff] [blame] | 243 | def fetch_and_print_logs(hash): |
| 244 | gs_base = 'gs://%s' % get_sha_destination(hash) |
| 245 | listing = utils.ls_files_on_cloud_storage(gs_base).strip().split('\n') |
| 246 | for entry in listing: |
| 247 | if not entry.endswith('/status'): # Ignore the overall status file |
| 248 | for to_print in [EXITCODE, TIMED_OUT, STDERR, STDOUT]: |
| 249 | gs_location = '%s%s' % (entry, to_print) |
| 250 | value = utils.cat_file_on_cloud_storage(gs_location) |
| 251 | print('\n\n%s had value:\n%s' % (to_print, value)) |
Morten Krogh-Jespersen | f241230 | 2019-10-22 10:18:04 +0200 | [diff] [blame] | 252 | print("\n\nPrinting find-min-xmx ranges for apps") |
| 253 | run_on_app.print_min_xmx_ranges_for_hash(hash, 'r8', 'lib') |
Rico Wind | 4fd2dda | 2018-09-26 17:41:45 +0200 | [diff] [blame] | 254 | |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 255 | def run_bot(): |
| 256 | print_magic_file_state() |
| 257 | # Ensure that there is nothing currently scheduled (broken/stopped run) |
| 258 | for magic in ALL_MAGIC: |
| 259 | if get_magic_file_exists(magic): |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 260 | log('ERROR: Synchronizing file %s exists, cleaning up' % magic) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 261 | delete_magic_file(magic) |
| 262 | print_magic_file_state() |
| 263 | assert not get_magic_file_exists(READY_FOR_TESTING) |
| 264 | git_hash = utils.get_HEAD_sha1() |
| 265 | put_magic_file(READY_FOR_TESTING, git_hash) |
| 266 | begin = time.time() |
| 267 | while True: |
| 268 | if time.time() - begin > BOT_RUN_TIMEOUT: |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 269 | log('Timeout exceeded: http://go/internal-r8-doc') |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 270 | raise Exception('Bot timeout') |
| 271 | if get_magic_file_exists(TESTING_COMPLETE): |
| 272 | if get_magic_file_content(TESTING_COMPLETE) == git_hash: |
| 273 | break |
| 274 | else: |
| 275 | raise Exception('Non matching git hashes %s and %s' % ( |
| 276 | get_magic_file_content(TESTING_COMPLETE), git_hash)) |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 277 | log('Still waiting for test result') |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 278 | print_magic_file_state() |
| 279 | time.sleep(PULL_DELAY) |
| 280 | total_time = time.time()-begin |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 281 | log('Done running test for %s in %ss' % (git_hash, total_time)) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 282 | test_status = get_status(git_hash) |
| 283 | delete_magic_file(TESTING_COMPLETE) |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 284 | log('Test status is: %s' % test_status) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 285 | if test_status != '0': |
Rico Wind | 9e9449e | 2019-04-04 14:42:29 +0200 | [diff] [blame] | 286 | print('Tests failed, you can print the logs by running(googlers only):') |
Rico Wind | 1cb65e1 | 2019-04-26 08:54:17 +0200 | [diff] [blame] | 287 | print(' tools/internal_test.py --print_logs %s' % git_hash) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 288 | return 1 |
| 289 | |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 290 | def run_continuously(): |
| 291 | # If this script changes, we will restart ourselves |
Christoffer Quist Adamsen | 81d4150 | 2021-06-25 09:33:43 +0200 | [diff] [blame] | 292 | own_content = get_file_contents() |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 293 | while True: |
| 294 | restart_if_new_version(own_content) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 295 | print_magic_file_state() |
| 296 | if get_magic_file_exists(READY_FOR_TESTING): |
| 297 | git_hash = get_magic_file_content(READY_FOR_TESTING) |
| 298 | checked_out = git_checkout(git_hash) |
Rico Wind | d7d9106 | 2019-04-29 09:24:10 +0200 | [diff] [blame] | 299 | if not checked_out: |
| 300 | # Gerrit change, we don't run these on internal. |
| 301 | archive_status(0) |
| 302 | put_magic_file(TESTING_COMPLETE, git_hash) |
| 303 | delete_magic_file(READY_FOR_TESTING) |
| 304 | continue |
Rico Wind | 9519a15 | 2019-01-23 13:34:20 +0100 | [diff] [blame] | 305 | # If the script changed, we need to restart now to get correct commands |
| 306 | # Note that we have not removed the READY_FOR_TESTING yet, so if we |
| 307 | # execv we will pick up the same version. |
| 308 | restart_if_new_version(own_content) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 309 | # Sanity check, if this does not succeed stop. |
| 310 | if checked_out != git_hash: |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 311 | log('Inconsistent state: %s %s' % (git_hash, checked_out)) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 312 | sys.exit(1) |
| 313 | put_magic_file(TESTING, git_hash) |
| 314 | delete_magic_file(READY_FOR_TESTING) |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 315 | log('Running with hash: %s' % git_hash) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 316 | exitcode = run_once(archive=True) |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 317 | log('Running finished with exit code %s' % exitcode) |
Rico Wind | f5175ae | 2020-01-24 08:12:05 +0100 | [diff] [blame] | 318 | # If the bot timed out or something else triggered the bot to fail, don't |
| 319 | # put up the result (it will not be displayed anywhere, and we can't |
| 320 | # remove the magic file if the bot cleaned up). |
| 321 | if get_magic_file_exists(TESTING): |
| 322 | put_magic_file(TESTING_COMPLETE, git_hash) |
| 323 | # There is still a potential race here (we check, bot deletes, we try to |
| 324 | # delete) - this is unlikely and we ignore it (restart if it happens). |
| 325 | delete_magic_file(TESTING) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 326 | time.sleep(PULL_DELAY) |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 327 | |
| 328 | def handle_output(archive, stderr, stdout, exitcode, timed_out, cmd): |
| 329 | if archive: |
| 330 | archive_log(stdout, stderr, exitcode, timed_out, cmd) |
| 331 | else: |
| 332 | print 'Execution of %s resulted in:' % cmd |
| 333 | print 'exit code: %s ' % exitcode |
| 334 | print 'timeout: %s ' % timed_out |
| 335 | with open(stderr, 'r') as f: |
| 336 | print 'stderr: %s' % f.read() |
| 337 | with open(stdout, 'r') as f: |
| 338 | print 'stdout: %s' % f.read() |
| 339 | |
Rico Wind | 6e2205d | 2018-10-25 13:27:13 +0200 | [diff] [blame] | 340 | def execute(cmd, archive, env=None): |
Morten Krogh-Jespersen | b042c97 | 2019-11-04 08:57:59 +0100 | [diff] [blame] | 341 | if cmd == []: |
| 342 | return |
| 343 | |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 344 | utils.PrintCmd(cmd) |
| 345 | with utils.TempDir() as temp: |
| 346 | try: |
| 347 | stderr_fd = None |
| 348 | stdout_fd = None |
| 349 | exitcode = 0 |
| 350 | stderr = os.path.join(temp, 'stderr') |
| 351 | stderr_fd = open(stderr, 'w') |
| 352 | stdout = os.path.join(temp, 'stdout') |
| 353 | stdout_fd = open(stdout, 'w') |
| 354 | popen = subprocess.Popen(cmd, |
| 355 | bufsize=1024*1024*10, |
| 356 | stdout=stdout_fd, |
Rico Wind | 6e2205d | 2018-10-25 13:27:13 +0200 | [diff] [blame] | 357 | stderr=stderr_fd, |
| 358 | env=env) |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 359 | begin = time.time() |
| 360 | timed_out = False |
| 361 | while popen.poll() == None: |
| 362 | if time.time() - begin > RUN_TIMEOUT: |
| 363 | popen.terminate() |
| 364 | timed_out = True |
| 365 | time.sleep(2) |
| 366 | exitcode = popen.returncode |
| 367 | finally: |
| 368 | if stderr_fd: |
| 369 | stderr_fd.close() |
| 370 | if stdout_fd: |
| 371 | stdout_fd.close() |
Morten Krogh-Jespersen | 4df02ad | 2019-10-08 14:58:39 +0000 | [diff] [blame] | 372 | if exitcode != 0: |
| 373 | handle_output(archive, stderr, stdout, popen.returncode, |
| 374 | timed_out, ' '.join(cmd)) |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 375 | return exitcode |
| 376 | |
| 377 | def run_once(archive): |
| 378 | failed = False |
| 379 | git_hash = utils.get_HEAD_sha1() |
Rico Wind | 1200f51 | 2018-09-26 08:48:37 +0200 | [diff] [blame] | 380 | log('Running once with hash %s' % git_hash) |
Rico Wind | 6e2205d | 2018-10-25 13:27:13 +0200 | [diff] [blame] | 381 | env = os.environ.copy() |
| 382 | # Bot does not have a lot of memory. |
Rico Wind | 3defc8d | 2019-03-27 08:07:31 +0100 | [diff] [blame] | 383 | env['R8_GRADLE_CORES_PER_FORK'] = '16' |
Morten Krogh-Jespersen | 2243b16 | 2019-01-14 08:40:53 +0100 | [diff] [blame] | 384 | failed = any([execute(cmd, archive, env) for cmd in TEST_COMMANDS]) |
Rico Wind | ba63dc8 | 2019-03-29 14:33:47 +0100 | [diff] [blame] | 385 | # Gradle daemon occasionally leaks memory, stop it. |
Rico Wind | 7423300 | 2019-04-04 08:28:58 +0200 | [diff] [blame] | 386 | gradle.RunGradle(['--stop']) |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 387 | archive_status(1 if failed else 0) |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 388 | return failed |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 389 | |
| 390 | def Main(): |
| 391 | (options, args) = ParseOptions() |
| 392 | if options.continuous: |
| 393 | run_continuously() |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 394 | elif options.bot: |
| 395 | return run_bot() |
Rico Wind | 4fd2dda | 2018-09-26 17:41:45 +0200 | [diff] [blame] | 396 | elif options.print_logs: |
| 397 | return fetch_and_print_logs(options.print_logs) |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 398 | else: |
Rico Wind | 139eece | 2018-09-25 09:42:09 +0200 | [diff] [blame] | 399 | return run_once(options.archive) |
Rico Wind | 800fd71 | 2018-09-24 11:29:33 +0200 | [diff] [blame] | 400 | |
| 401 | if __name__ == '__main__': |
| 402 | sys.exit(Main()) |