blob: ce89a156956876d6e2553c6040f6091a438fdb85 [file] [log] [blame]
Aviv Keshet021c19f2013-02-22 13:19:43 -08001#!/usr/bin/python
2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import argparse
Aviv Keshet15782de2013-07-31 11:40:41 -07007import errno
Aviv Keshet0e5d5252013-04-26 16:01:36 -07008import os
Aviv Keshetd4a04302013-04-30 15:48:30 -07009import re
Aviv Keshet1d991ea2013-06-12 17:24:23 -070010import signal
Aviv Keshet0e5d5252013-04-26 16:01:36 -070011import subprocess
Aviv Keshet021c19f2013-02-22 13:19:43 -080012import sys
Aviv Keshetd4a04302013-04-30 15:48:30 -070013import tempfile
Aviv Keshet1d991ea2013-06-12 17:24:23 -070014import threading
Aviv Keshet021c19f2013-02-22 13:19:43 -080015
Aviv Keshete43bccf2013-08-14 14:11:59 -070016import logging
17# Turn the logging level to INFO before importing other autotest
18# code, to avoid having failed import logging messages confuse the
19# test_that user.
20logging.basicConfig(level=logging.INFO)
21
Aviv Keshet021c19f2013-02-22 13:19:43 -080022import common
Aviv Keshet1d991ea2013-06-12 17:24:23 -070023from autotest_lib.client.common_lib.cros import dev_server, retry
Aviv Keshete43bccf2013-08-14 14:11:59 -070024from autotest_lib.client.common_lib import logging_manager
Aviv Keshetd4a04302013-04-30 15:48:30 -070025from autotest_lib.server.cros.dynamic_suite import suite
26from autotest_lib.server.cros.dynamic_suite import constants
27from autotest_lib.server import autoserv_utils
Aviv Keshete43bccf2013-08-14 14:11:59 -070028from autotest_lib.server import server_logging_config
29
Aviv Keshetd4a04302013-04-30 15:48:30 -070030
Aviv Keshet0e5d5252013-04-26 16:01:36 -070031try:
32 from chromite.lib import cros_build_lib
33except ImportError:
34 print 'Unable to import chromite.'
35 print 'This script must be either:'
36 print ' - Be run in the chroot.'
37 print ' - (not yet supported) be run after running '
38 print ' ../utils/build_externals.py'
Aviv Keshet021c19f2013-02-22 13:19:43 -080039
Aviv Keshet1d991ea2013-06-12 17:24:23 -070040_autoserv_proc = None
41_sigint_handler_lock = threading.Lock()
42
43_AUTOSERV_SIGINT_TIMEOUT_SECONDS = 5
Alex Millera0913072013-06-12 10:01:51 -070044_NO_BOARD = 'ad_hoc_board'
Aviv Keshet10711962013-06-24 12:20:33 -070045_NO_BUILD = 'ad_hoc_build'
Aviv Keshet1d991ea2013-06-12 17:24:23 -070046
Aviv Keshet2dc98932013-06-17 15:22:10 -070047_QUICKMERGE_SCRIPTNAME = '/mnt/host/source/chromite/bin/autotest_quickmerge'
48
Aviv Keshetba4992a2013-07-02 14:09:23 -070049_TEST_REPORT_SCRIPTNAME = '/usr/bin/generate_test_report'
50
Aviv Keshetc9e74622013-07-18 10:11:11 -070051_LATEST_RESULTS_DIRECTORY = '/tmp/test_that_latest'
52
Aviv Keshetd4a04302013-04-30 15:48:30 -070053
Aviv Keshet10711962013-06-24 12:20:33 -070054def schedule_local_suite(autotest_path, suite_name, afe, build=_NO_BUILD,
Aviv Keshete9170d92013-07-19 11:20:45 -070055 board=_NO_BOARD, results_directory=None,
56 no_experimental=False):
Aviv Keshetd4a04302013-04-30 15:48:30 -070057 """
58 Schedule a suite against a mock afe object, for a local suite run.
59 @param autotest_path: Absolute path to autotest (in sysroot).
60 @param suite_name: Name of suite to schedule.
61 @param afe: afe object to schedule against (typically a directAFE)
62 @param build: Build to schedule suite for.
Aviv Keshet10711962013-06-24 12:20:33 -070063 @param board: Board to schedule suite for.
Aviv Keshetba4992a2013-07-02 14:09:23 -070064 @param results_directory: Absolute path of directory to store results in.
65 (results will be stored in subdirectory of this).
Aviv Keshete9170d92013-07-19 11:20:45 -070066 @param no_experimental: Skip experimental tests when scheduling a suite.
Aviv Keshet69ebb6c2013-06-11 13:58:44 -070067 @returns: The number of tests scheduled.
Aviv Keshetd4a04302013-04-30 15:48:30 -070068 """
69 fs_getter = suite.Suite.create_fs_getter(autotest_path)
70 devserver = dev_server.ImageServer('')
Aviv Keshet10711962013-06-24 12:20:33 -070071 my_suite = suite.Suite.create_from_name(suite_name, build, board,
Aviv Keshetba4992a2013-07-02 14:09:23 -070072 devserver, fs_getter, afe=afe, ignore_deps=True,
73 results_dir=results_directory)
Aviv Keshetd4a04302013-04-30 15:48:30 -070074 if len(my_suite.tests) == 0:
75 raise ValueError('Suite named %s does not exist, or contains no '
76 'tests.' % suite_name)
Aviv Keshete9170d92013-07-19 11:20:45 -070077 # Schedule tests, discard record calls.
78 return my_suite.schedule(lambda x: None,
79 add_experimental=not no_experimental)
Aviv Keshet021c19f2013-02-22 13:19:43 -080080
81
Aviv Keshet10711962013-06-24 12:20:33 -070082def schedule_local_test(autotest_path, test_name, afe, build=_NO_BUILD,
Aviv Keshetba4992a2013-07-02 14:09:23 -070083 board=_NO_BOARD, results_directory=None):
Aviv Keshetd4a04302013-04-30 15:48:30 -070084 #temporarily disabling pylint
85 #pylint: disable-msg=C0111
86 """
87 Schedule an individual test against a mock afe object, for a local run.
Aviv Keshet69ebb6c2013-06-11 13:58:44 -070088 @param autotest_path: Absolute path to autotest (in sysroot).
89 @param test_name: Name of test to schedule.
90 @param afe: afe object to schedule against (typically a directAFE)
91 @param build: Build to schedule suite for.
Aviv Keshet10711962013-06-24 12:20:33 -070092 @param board: Board to schedule suite for.
Aviv Keshetba4992a2013-07-02 14:09:23 -070093 @param results_directory: Absolute path of directory to store results in.
94 (results will be stored in subdirectory of this).
Aviv Keshet69ebb6c2013-06-11 13:58:44 -070095 @returns: The number of tests scheduled (may be >1 if there are
96 multiple tests with the same name).
Aviv Keshetd4a04302013-04-30 15:48:30 -070097 """
Aviv Keshet69ebb6c2013-06-11 13:58:44 -070098 fs_getter = suite.Suite.create_fs_getter(autotest_path)
99 devserver = dev_server.ImageServer('')
100 predicates = [suite.Suite.test_name_equals_predicate(test_name)]
101 suite_name = 'suite_' + test_name
Aviv Keshet10711962013-06-24 12:20:33 -0700102 my_suite = suite.Suite.create_from_predicates(predicates, build, board,
Aviv Keshetba4992a2013-07-02 14:09:23 -0700103 devserver, fs_getter, afe=afe, name=suite_name, ignore_deps=True,
104 results_dir=results_directory)
Aviv Keshet69ebb6c2013-06-11 13:58:44 -0700105 if len(my_suite.tests) == 0:
106 raise ValueError('No tests named %s.' % test_name)
Aviv Keshete9170d92013-07-19 11:20:45 -0700107 # Schedule tests, discard record calls.
108 return my_suite.schedule(lambda x: None)
Aviv Keshetd4a04302013-04-30 15:48:30 -0700109
110
Aviv Keshet5e33c172013-07-16 05:00:49 -0700111def run_job(job, host, sysroot_autotest_path, results_directory, fast_mode,
Aviv Keshetc14951a2013-08-12 18:17:35 -0700112 id_digits=1, ssh_verbosity=0, args=None, pretend=False):
Aviv Keshetd4a04302013-04-30 15:48:30 -0700113 """
114 Shell out to autoserv to run an individual test job.
115
116 @param job: A Job object containing the control file contents and other
117 relevent metadata for this test.
118 @param host: Hostname of DUT to run test against.
119 @param sysroot_autotest_path: Absolute path of autotest directory.
Aviv Keshetc8824402013-06-29 20:37:30 -0700120 @param results_directory: Absolute path of directory to store results in.
121 (results will be stored in subdirectory of this).
Christopher Wileyf6b5aae2013-07-09 10:14:02 -0700122 @param fast_mode: bool to use fast mode (disables slow autotest features).
Aviv Keshet5e33c172013-07-16 05:00:49 -0700123 @param id_digits: The minimum number of digits that job ids should be
124 0-padded to when formatting as a string for results
125 directory.
Aviv Keshetc14951a2013-08-12 18:17:35 -0700126 @param ssh_verbosity: SSH verbosity level, passed along to autoserv_utils
Aviv Keshet30322f92013-07-18 13:21:52 -0700127 @param args: String that should be passed as args parameter to autoserv,
128 and then ultimitely to test itself.
Aviv Keshetc5e46092013-07-19 10:15:40 -0700129 @param pretend: If True, will print out autoserv commands rather than
130 running them.
Aviv Keshetc8824402013-06-29 20:37:30 -0700131 @returns: Absolute path of directory where results were stored.
Aviv Keshetd4a04302013-04-30 15:48:30 -0700132 """
133 with tempfile.NamedTemporaryFile() as temp_file:
134 temp_file.write(job.control_file)
135 temp_file.flush()
Aviv Keshetc8824402013-06-29 20:37:30 -0700136 results_directory = os.path.join(results_directory,
Aviv Keshet5e33c172013-07-16 05:00:49 -0700137 'results-%0*d' % (id_digits, job.id))
Aviv Keshet30322f92013-07-18 13:21:52 -0700138 extra_args = [temp_file.name]
139 if args:
140 extra_args.extend(['--args', args])
Aviv Keshetc8824402013-06-29 20:37:30 -0700141
Aviv Keshetd4a04302013-04-30 15:48:30 -0700142 command = autoserv_utils.autoserv_run_job_command(
143 os.path.join(sysroot_autotest_path, 'server'),
144 machines=host, job=job, verbose=False,
Aviv Keshetc8824402013-06-29 20:37:30 -0700145 results_directory=results_directory,
Aviv Keshetc14951a2013-08-12 18:17:35 -0700146 fast_mode=fast_mode, ssh_verbosity=ssh_verbosity,
Aviv Keshete43bccf2013-08-14 14:11:59 -0700147 extra_args=extra_args,
148 no_console_prefix=True)
Aviv Keshetc5e46092013-07-19 10:15:40 -0700149
150 if not pretend:
Aviv Keshete43bccf2013-08-14 14:11:59 -0700151 logging.debug('Running autoserv command: %s', ' '.join(command))
Aviv Keshetc5e46092013-07-19 10:15:40 -0700152 global _autoserv_proc
Aviv Keshete43bccf2013-08-14 14:11:59 -0700153 _autoserv_proc = subprocess.Popen(command,
154 stdout=subprocess.PIPE,
155 stderr=subprocess.STDOUT)
156 # This incantation forces unbuffered reading from stdout,
157 # so that autoserv output can be displayed to the user
158 # immediately.
159 for message in iter(_autoserv_proc.stdout.readline, b''):
160 logging.info('autoserv| %s', message.strip())
161
Aviv Keshetc5e46092013-07-19 10:15:40 -0700162 _autoserv_proc.wait()
163 _autoserv_proc = None
164 return results_directory
165 else:
166 logging.info('Pretend mode. Would run autoserv command: %s',
167 ' '.join(command))
Aviv Keshetd4a04302013-04-30 15:48:30 -0700168
169
170def setup_local_afe():
171 """
172 Setup a local afe database and return a direct_afe object to access it.
173
174 @returns: A autotest_lib.frontend.afe.direct_afe instance.
175 """
176 # This import statement is delayed until now rather than running at
177 # module load time, because it kicks off a local sqlite :memory: backed
178 # database, and we don't need that unless we are doing a local run.
179 from autotest_lib.frontend import setup_django_lite_environment
180 from autotest_lib.frontend.afe import direct_afe
181 return direct_afe.directAFE()
182
183
Christopher Wileyf6b5aae2013-07-09 10:14:02 -0700184def perform_local_run(afe, autotest_path, tests, remote, fast_mode,
Aviv Keshetc5e46092013-07-19 10:15:40 -0700185 build=_NO_BUILD, board=_NO_BOARD, args=None,
Aviv Keshet15782de2013-07-31 11:40:41 -0700186 pretend=False, no_experimental=False,
Aviv Keshetc14951a2013-08-12 18:17:35 -0700187 results_directory=None, ssh_verbosity=0):
Aviv Keshetd4a04302013-04-30 15:48:30 -0700188 """
189 @param afe: A direct_afe object used to interact with local afe database.
190 @param autotest_path: Absolute path of sysroot installed autotest.
191 @param tests: List of strings naming tests and suites to run. Suite strings
192 should be formed like "suite:smoke".
193 @param remote: Remote hostname.
Christopher Wileyf6b5aae2013-07-09 10:14:02 -0700194 @param fast_mode: bool to use fast mode (disables slow autotest features).
Aviv Keshetd4a04302013-04-30 15:48:30 -0700195 @param build: String specifying build for local run.
Aviv Keshet10711962013-06-24 12:20:33 -0700196 @param board: String specifyinb board for local run.
Aviv Keshet30322f92013-07-18 13:21:52 -0700197 @param args: String that should be passed as args parameter to autoserv,
198 and then ultimitely to test itself.
Aviv Keshetc5e46092013-07-19 10:15:40 -0700199 @param pretend: If True, will print out autoserv commands rather than
200 running them.
Aviv Keshete9170d92013-07-19 11:20:45 -0700201 @param no_experimental: Skip experimental tests when scheduling a suite.
Aviv Keshet15782de2013-07-31 11:40:41 -0700202 @param results_directory: Directory to store results in. Defaults to None,
203 in which case results will be stored in a new
204 subdirectory of /tmp
Aviv Keshetc14951a2013-08-12 18:17:35 -0700205 @param ssh_verbosity: SSH verbosity level, passed through to
206 autoserv_utils.
Aviv Keshetd4a04302013-04-30 15:48:30 -0700207 """
208 afe.create_label(constants.VERSION_PREFIX + build)
Aviv Keshet10711962013-06-24 12:20:33 -0700209 afe.create_label(board)
Aviv Keshetd4a04302013-04-30 15:48:30 -0700210 afe.create_host(remote)
211
212 # Schedule tests / suites in local afe
213 for test in tests:
214 suitematch = re.match(r'suite:(.*)', test)
215 if suitematch:
216 suitename = suitematch.group(1)
Aviv Keshet69ebb6c2013-06-11 13:58:44 -0700217 logging.info('Scheduling suite %s...', suitename)
Aviv Keshet10711962013-06-24 12:20:33 -0700218 ntests = schedule_local_suite(autotest_path, suitename, afe,
Aviv Keshetba4992a2013-07-02 14:09:23 -0700219 build=build, board=board,
Aviv Keshete9170d92013-07-19 11:20:45 -0700220 results_directory=results_directory,
221 no_experimental=no_experimental)
Aviv Keshetd4a04302013-04-30 15:48:30 -0700222 else:
Aviv Keshet69ebb6c2013-06-11 13:58:44 -0700223 logging.info('Scheduling test %s...', test)
Aviv Keshet10711962013-06-24 12:20:33 -0700224 ntests = schedule_local_test(autotest_path, test, afe,
Aviv Keshetba4992a2013-07-02 14:09:23 -0700225 build=build, board=board,
226 results_directory=results_directory)
Aviv Keshet69ebb6c2013-06-11 13:58:44 -0700227 logging.info('... scheduled %s tests.', ntests)
Aviv Keshetd4a04302013-04-30 15:48:30 -0700228
Aviv Keshet5e33c172013-07-16 05:00:49 -0700229 if not afe.get_jobs():
230 logging.info('No jobs scheduled. End of local run.')
Aviv Keshet5e33c172013-07-16 05:00:49 -0700231
232 last_job_id = afe.get_jobs()[-1].id
233 job_id_digits=len(str(last_job_id))
Aviv Keshetd4a04302013-04-30 15:48:30 -0700234 for job in afe.get_jobs():
Aviv Keshet5e33c172013-07-16 05:00:49 -0700235 run_job(job, remote, autotest_path, results_directory, fast_mode,
Aviv Keshetc14951a2013-08-12 18:17:35 -0700236 job_id_digits, ssh_verbosity, args, pretend)
Aviv Keshetd4a04302013-04-30 15:48:30 -0700237
Aviv Keshetd4a04302013-04-30 15:48:30 -0700238
239def validate_arguments(arguments):
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700240 """
241 Validates parsed arguments.
242
243 @param arguments: arguments object, as parsed by ParseArguments
244 @raises: ValueError if arguments were invalid.
245 """
Aviv Keshet30322f92013-07-18 13:21:52 -0700246 if arguments.build:
247 raise ValueError('-i/--build flag not yet supported.')
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700248
249 if not arguments.board:
250 raise ValueError('Board autodetection not yet supported. '
251 '--board required.')
252
Aviv Keshetd4a04302013-04-30 15:48:30 -0700253 if arguments.remote == ':lab:':
254 raise ValueError('Running tests in test lab not yet supported.')
Aviv Keshet30322f92013-07-18 13:21:52 -0700255 if arguments.args:
256 raise ValueError('--args flag not supported when running against '
257 ':lab:')
Aviv Keshetc5e46092013-07-19 10:15:40 -0700258 if arguments.pretend:
259 raise ValueError('--pretend flag not supported when running '
260 'against :lab:')
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700261
Aviv Keshetc14951a2013-08-12 18:17:35 -0700262 if arguments.ssh_verbosity:
263 raise ValueError('--ssh_verbosity flag not supported when running '
264 'against :lab:')
265
Aviv Keshetd4a04302013-04-30 15:48:30 -0700266
267def parse_arguments(argv):
Aviv Keshet021c19f2013-02-22 13:19:43 -0800268 """
269 Parse command line arguments
270
271 @param argv: argument list to parse
272 @returns: parsed arguments.
273 """
274 parser = argparse.ArgumentParser(description='Run remote tests.')
275
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700276 parser.add_argument('remote', metavar='REMOTE',
Aviv Keshet021c19f2013-02-22 13:19:43 -0800277 help='hostname[:port] for remote device. Specify '
Aviv Keshete43bccf2013-08-14 14:11:59 -0700278 ':lab: to run in test lab, or :vm:PORT_NUMBER to '
279 'run in vm.')
Aviv Keshet021c19f2013-02-22 13:19:43 -0800280 parser.add_argument('tests', nargs='+', metavar='TEST',
281 help='Run given test(s). Use suite:SUITE to specify '
Aviv Keshete43bccf2013-08-14 14:11:59 -0700282 'test suite.')
Prathmesh Prabhu63f00aa2013-07-26 13:33:06 -0700283 default_board = cros_build_lib.GetDefaultBoard()
284 parser.add_argument('-b', '--board', metavar='BOARD', default=default_board,
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700285 action='store',
Prathmesh Prabhu63f00aa2013-07-26 13:33:06 -0700286 help='Board for which the test will run. Default: %s' %
287 (default_board or 'Not configured'))
Aviv Keshetd4a04302013-04-30 15:48:30 -0700288 parser.add_argument('-i', '--build', metavar='BUILD',
Aviv Keshet021c19f2013-02-22 13:19:43 -0800289 help='Build to test. Device will be reimaged if '
Aviv Keshete43bccf2013-08-14 14:11:59 -0700290 'necessary. Omit flag to skip reimage and test '
291 'against already installed DUT image.')
Christopher Wileyf6b5aae2013-07-09 10:14:02 -0700292 parser.add_argument('--fast', action='store_true', dest='fast_mode',
293 default=False,
294 help='Enable fast mode. This will cause test_that to '
295 'skip time consuming steps like sysinfo and '
296 'collecting crash information.')
Aviv Keshetd4a04302013-04-30 15:48:30 -0700297 parser.add_argument('--args', metavar='ARGS',
Aviv Keshet30322f92013-07-18 13:21:52 -0700298 help='Argument string to pass through to test. Only '
Aviv Keshete43bccf2013-08-14 14:11:59 -0700299 'supported for runs against a local DUT.')
Aviv Keshet15782de2013-07-31 11:40:41 -0700300 parser.add_argument('--results_dir', metavar='RESULTS_DIR',
301 help='Instead of storing results in a new subdirectory'
Aviv Keshete43bccf2013-08-14 14:11:59 -0700302 ' of /tmp , store results in RESULTS_DIR. If '
303 'RESULTS_DIR already exists, will attempt to '
304 'continue using this directory, which may result '
305 'in test failures due to file collisions.')
Aviv Keshetc5e46092013-07-19 10:15:40 -0700306 parser.add_argument('--pretend', action='store_true', default=False,
307 help='Print autoserv commands that would be run, '
308 'rather than running them.')
Aviv Keshet8ea71df2013-07-19 10:49:36 -0700309 parser.add_argument('--no-quickmerge', action='store_true', default=False,
310 dest='no_quickmerge',
311 help='Skip the quickmerge step and use the sysroot '
312 'as it currently is. May result in un-merged '
313 'source tree changes not being reflected in run.')
Aviv Keshete9170d92013-07-19 11:20:45 -0700314 parser.add_argument('--no-experimental', action='store_true',
315 default=False, dest='no_experimental',
316 help='When scheduling a suite, skip any tests marked '
317 'as experimental. Applies only to tests scheduled'
318 ' via suite:[SUITE].')
Aviv Keshetfd775912013-08-06 11:37:16 -0700319 parser.add_argument('--whitelist-chrome-crashes', action='store_true',
320 default=False, dest='whitelist_chrome_crashes',
321 help='Ignore chrome crashes when producing test '
Aviv Keshete43bccf2013-08-14 14:11:59 -0700322 'report. This flag gets passed along to the '
323 'report generation tool.')
Aviv Keshetc14951a2013-08-12 18:17:35 -0700324 parser.add_argument('--ssh_verbosity', action='store', type=int,
325 choices=[0, 1, 2, 3], default=0,
326 help='Verbosity level for ssh, between 0 and 3 '
327 'inclusive.')
Aviv Keshete43bccf2013-08-14 14:11:59 -0700328 parser.add_argument('--debug', action='store_true',
329 help='Include DEBUG level messages in stdout. Note: '
330 'these messages will be included in output log '
331 'file regardless.')
Aviv Keshet021c19f2013-02-22 13:19:43 -0800332 return parser.parse_args(argv)
333
334
Aviv Keshet1d991ea2013-06-12 17:24:23 -0700335def sigint_handler(signum, stack_frame):
336 #pylint: disable-msg=C0111
337 """Handle SIGINT or SIGTERM to a local test_that run.
338
339 This handler sends a SIGINT to the running autoserv process,
340 if one is running, giving it up to 5 seconds to clean up and exit. After
341 the timeout elapses, autoserv is killed. In either case, after autoserv
342 exits then this process exits with status 1.
343 """
344 # If multiple signals arrive before handler is unset, ignore duplicates
345 if not _sigint_handler_lock.acquire(False):
346 return
347 try:
348 # Ignore future signals by unsetting handler.
349 signal.signal(signal.SIGINT, signal.SIG_IGN)
350 signal.signal(signal.SIGTERM, signal.SIG_IGN)
351
352 logging.warning('Received SIGINT or SIGTERM. Cleaning up and exiting.')
353 if _autoserv_proc:
354 logging.warning('Sending SIGINT to autoserv process. Waiting up '
355 'to %s seconds for cleanup.',
356 _AUTOSERV_SIGINT_TIMEOUT_SECONDS)
357 _autoserv_proc.send_signal(signal.SIGINT)
358 timed_out, _ = retry.timeout(_autoserv_proc.wait,
359 timeout_sec=_AUTOSERV_SIGINT_TIMEOUT_SECONDS)
360 if timed_out:
361 _autoserv_proc.kill()
362 logging.warning('Timed out waiting for autoserv to handle '
363 'SIGINT. Killed autoserv.')
364 finally:
365 _sigint_handler_lock.release() # this is not really necessary?
366 sys.exit(1)
367
368
Aviv Keshet021c19f2013-02-22 13:19:43 -0800369def main(argv):
370 """
371 Entry point for test_that script.
372 @param argv: arguments list
373 """
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700374
Aviv Keshete43bccf2013-08-14 14:11:59 -0700375 if not cros_build_lib.IsInsideChroot():
376 print >> sys.stderr, 'Script must be invoked inside the chroot.'
377 return 1
Aviv Keshet712128f2013-06-11 14:41:08 -0700378
Aviv Keshetd4a04302013-04-30 15:48:30 -0700379 arguments = parse_arguments(argv)
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700380 try:
Aviv Keshetd4a04302013-04-30 15:48:30 -0700381 validate_arguments(arguments)
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700382 except ValueError as err:
Aviv Keshete43bccf2013-08-14 14:11:59 -0700383 print >> sys.stderr, ('Invalid arguments. %s' % err.message)
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700384 return 1
385
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700386 sysroot_path = os.path.join('/build', arguments.board, '')
387 sysroot_autotest_path = os.path.join(sysroot_path, 'usr', 'local',
388 'autotest', '')
389 sysroot_site_utils_path = os.path.join(sysroot_autotest_path,
390 'site_utils')
391
392 if not os.path.exists(sysroot_path):
Aviv Keshete43bccf2013-08-14 14:11:59 -0700393 print >> sys.stderr, ('%s does not exist. Have you run '
394 'setup_board?' % sysroot_path)
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700395 return 1
396 if not os.path.exists(sysroot_autotest_path):
Aviv Keshete43bccf2013-08-14 14:11:59 -0700397 print >> sys.stderr, ('%s does not exist. Have you run '
398 'build_packages?' % sysroot_autotest_path)
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700399 return 1
400
Aviv Keshet2dc98932013-06-17 15:22:10 -0700401 # If we are not running the sysroot version of script, perform
402 # a quickmerge if necessary and then re-execute
403 # the sysroot version of script with the same arguments.
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700404 realpath = os.path.realpath(__file__)
405 if os.path.dirname(realpath) != sysroot_site_utils_path:
Aviv Keshete43bccf2013-08-14 14:11:59 -0700406 logging_manager.configure_logging(
407 server_logging_config.ServerLoggingConfig(),
408 use_console=True,
409 verbose=arguments.debug)
Aviv Keshet8ea71df2013-07-19 10:49:36 -0700410 if arguments.no_quickmerge:
411 logging.info('Skipping quickmerge step as requested.')
412 else:
Aviv Keshete43bccf2013-08-14 14:11:59 -0700413 logging.info('Running autotest_quickmerge step.')
414 s = subprocess.Popen([_QUICKMERGE_SCRIPTNAME,
415 '--board='+arguments.board],
416 stdout=subprocess.PIPE,
417 stderr=subprocess.STDOUT)
418 for message in iter(s.stdout.readline, b''):
419 logging.debug('quickmerge| %s', message.strip())
420 s.wait()
Aviv Keshet2dc98932013-06-17 15:22:10 -0700421
Aviv Keshete43bccf2013-08-14 14:11:59 -0700422 logging.info('Re-running test_that script in sysroot.')
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700423 script_command = os.path.join(sysroot_site_utils_path,
424 os.path.basename(realpath))
Aviv Keshet1d991ea2013-06-12 17:24:23 -0700425 proc = None
426 def resend_sig(signum, stack_frame):
427 #pylint: disable-msg=C0111
428 if proc:
429 proc.send_signal(signum)
430 signal.signal(signal.SIGINT, resend_sig)
431 signal.signal(signal.SIGTERM, resend_sig)
432
433 proc = subprocess.Popen([script_command] + argv)
434
435 return proc.wait()
Aviv Keshet0e5d5252013-04-26 16:01:36 -0700436
Aviv Keshete43bccf2013-08-14 14:11:59 -0700437 # We are running the sysroot version of the script.
438 # No further levels of bootstrapping that will occur, so
439 # create a results directory and start sending our logging messages
440 # to it.
441 results_directory = arguments.results_dir
442 if results_directory is None:
443 # Create a results_directory as subdir of /tmp
444 results_directory = tempfile.mkdtemp(prefix='test_that_results_')
445 else:
446 # Create results_directory if it does not exist
447 try:
448 os.makedirs(results_directory)
449 except OSError as e:
450 if e.errno != errno.EEXIST:
451 raise
452
453 logging_manager.configure_logging(
454 server_logging_config.ServerLoggingConfig(),
455 results_dir=results_directory,
456 use_console=True,
457 verbose=arguments.debug,
458 debug_log_name='test_that')
459 logging.info('Began logging to %s', results_directory)
460
Aviv Keshetd4a04302013-04-30 15:48:30 -0700461 # Hard coded to True temporarily. This will eventually be parsed to false
462 # if we are doing a run in the test lab.
463 local_run = True
Aviv Keshet021c19f2013-02-22 13:19:43 -0800464
Aviv Keshet1d991ea2013-06-12 17:24:23 -0700465 signal.signal(signal.SIGINT, sigint_handler)
466 signal.signal(signal.SIGTERM, sigint_handler)
467
Aviv Keshetd4a04302013-04-30 15:48:30 -0700468 if local_run:
469 afe = setup_local_afe()
Aviv Keshete43bccf2013-08-14 14:11:59 -0700470 perform_local_run(afe, sysroot_autotest_path, arguments.tests,
471 arguments.remote, arguments.fast_mode,
472 args=arguments.args,
473 pretend=arguments.pretend,
474 no_experimental=arguments.no_experimental,
475 results_directory=results_directory,
476 ssh_verbosity=arguments.ssh_verbosity)
Aviv Keshetc5e46092013-07-19 10:15:40 -0700477 if arguments.pretend:
478 logging.info('Finished pretend run. Exiting.')
479 return 0
480
Aviv Keshetfd775912013-08-06 11:37:16 -0700481 test_report_command = [_TEST_REPORT_SCRIPTNAME]
482 if arguments.whitelist_chrome_crashes:
483 test_report_command.append('--whitelist_chrome_crashes')
Aviv Keshete43bccf2013-08-14 14:11:59 -0700484 test_report_command.append(results_directory)
Aviv Keshetfd775912013-08-06 11:37:16 -0700485 final_result = subprocess.call(test_report_command)
Prathmesh Prabhu0819a612013-07-18 15:50:02 -0700486 logging.info('Finished running tests. Results can be found in %s',
Aviv Keshete43bccf2013-08-14 14:11:59 -0700487 results_directory)
Aviv Keshetc9e74622013-07-18 10:11:11 -0700488 try:
489 os.unlink(_LATEST_RESULTS_DIRECTORY)
490 except OSError:
491 pass
Aviv Keshete43bccf2013-08-14 14:11:59 -0700492 os.symlink(results_directory, _LATEST_RESULTS_DIRECTORY)
Prathmesh Prabhu0819a612013-07-18 15:50:02 -0700493 return final_result
Aviv Keshetba4992a2013-07-02 14:09:23 -0700494
Aviv Keshet021c19f2013-02-22 13:19:43 -0800495
496if __name__ == '__main__':
Aviv Keshetd4a04302013-04-30 15:48:30 -0700497 sys.exit(main(sys.argv[1:]))