def try_sudo(p): if sys.platform in ('darwin', 'linux2', 'linux') and not sudo_failed: # Try passwordless sudo, just in case. In practice, it is preferable # to use linux capabilities. with open(os.devnull, 'rb') as f: if not subprocess42.call( ['sudo', '-n', 'chmod', 'a+rwX,-t', p], stdin=f): return False logging.debug('sudo chmod %s failed', p) return True
def test_call(self): cmd = [sys.executable, '-u', '-c', 'import sys; sys.exit(0)'] self.assertEqual(0, subprocess42.call(cmd)) cmd = [sys.executable, '-u', '-c', 'import sys; sys.exit(1)'] self.assertEqual(1, subprocess42.call(cmd))
def get_client(service_url, package_template, version, cache_dir, timeout=None): """Returns a context manager that yields a CipdClient. A blocking call. Upon exit from the context manager, the client binary may be deleted (if the internal cache is full). Args: service_url (str): URL of the CIPD backend. package_template (str): package name template of the CIPD client. version (str): version of CIPD client package. cache_dir: directory to store instance cache, version cache and a hardlink to the client binary. timeout (int): if not None, timeout in seconds for this function. Yields: CipdClient. Raises: Error if CIPD client version cannot be resolved or client cannot be fetched. """ timeoutfn = tools.sliding_timeout(timeout) # Package names are always lower case. # TODO(maruel): Assert instead? package_name = package_template.lower().replace('${platform}', get_platform()) # Resolve version to instance id. # Is it an instance id already? They look like HEX SHA1. if isolated_format.is_valid_hash(version, hashlib.sha1): instance_id = version elif ':' in version: # it's an immutable tag, cache the resolved version # version_cache is {hash(package_name, tag) -> instance id} mapping. # It does not take a lot of disk space. version_cache = local_caching.DiskContentAddressedCache( six.text_type(os.path.join(cache_dir, 'versions')), local_caching.CachePolicies( # 1GiB. max_cache_size=1024 * 1024 * 1024, min_free_space=0, max_items=300, # 3 weeks. max_age_secs=21 * 24 * 60 * 60), trim=True) # Convert (package_name, version) to a string that may be used as a # filename in disk cache by hashing it. version_digest = hashlib.sha1('%s\n%s' % (package_name, version)).hexdigest() try: with version_cache.getfileobj(version_digest) as f: instance_id = f.read() except local_caching.CacheMiss: instance_id = resolve_version(service_url, package_name, version, timeout=timeoutfn()) version_cache.write(version_digest, instance_id) version_cache.trim() else: # it's a ref, hit the backend instance_id = resolve_version(service_url, package_name, version, timeout=timeoutfn()) # instance_cache is {instance_id -> client binary} mapping. # It is bounded by 5 client versions. instance_cache = local_caching.DiskContentAddressedCache( six.text_type(os.path.join(cache_dir, 'clients')), local_caching.CachePolicies( # 1GiB. max_cache_size=1024 * 1024 * 1024, min_free_space=0, max_items=10, # 3 weeks. max_age_secs=21 * 24 * 60 * 60), trim=True) if instance_id not in instance_cache: logging.info('Fetching CIPD client %s:%s', package_name, instance_id) fetch_url = get_client_fetch_url(service_url, package_name, instance_id, timeout=timeoutfn()) _fetch_cipd_client(instance_cache, instance_id, fetch_url, timeoutfn) # A single host can run multiple swarming bots, but they cannot share same # root bot directory. Thus, it is safe to use the same name for the binary. cipd_bin_dir = six.text_type(os.path.join(cache_dir, 'bin')) binary_path = os.path.join(cipd_bin_dir, 'cipd' + EXECUTABLE_SUFFIX) if fs.isfile(binary_path): # TODO(maruel): Do not unconditionally remove the binary. try: file_path.remove(binary_path) except WindowsError: # pylint: disable=undefined-variable # See whether cipd.exe is running for crbug.com/1028781 ret = subprocess42.call(['tasklist.exe']) if ret: logging.error('tasklist returns non-zero: %d', ret) raise else: file_path.ensure_tree(cipd_bin_dir) with instance_cache.getfileobj(instance_id) as f: isolateserver.putfile(f, binary_path, 0o511) # -r-x--x--x _ensure_batfile(binary_path) yield CipdClient(binary_path, package_name=package_name, instance_id=instance_id, service_url=service_url) instance_cache.trim()
def main(argv): """CLI frontend to validate arguments.""" tools.disable_buffering() parser, options, cmd = process_args(argv) if options.gtest_list_tests: # Special case, return the output of the target unmodified. return subprocess42.call(cmd + ['--gtest_list_tests']) cwd = os.getcwd() test_cases = parser.process_gtest_options(cmd, cwd, options) if options.no_dump: result_file = None else: result_file = options.result if not result_file: if cmd[0] == sys.executable: result_file = '%s.run_test_cases' % cmd[1] else: result_file = '%s.run_test_cases' % cmd[0] if not test_cases: # The fact of not running any test is considered a failure. This is to # prevent silent failure with an invalid --gtest_filter argument or because # of a misconfigured unit test. if test_cases is not None: print('Found no test to run') if result_file: dump_results_as_json(result_file, { 'test_cases': [], 'expected': 0, 'success': [], 'flaky': [], 'fail': [], 'missing': [], 'duration': 0, }) return 1 if options.disabled: cmd.append('--gtest_also_run_disabled_tests') if options.manual: cmd.append('--run-manual') try: return run_test_cases( cmd, cwd, test_cases, options.jobs, options.timeout, options.clusters, options.retries, options.run_all, options.max_failures, options.no_cr, options.gtest_output, result_file, options.verbose) except Failure as e: print >> sys.stderr, e.args[0] return 1