Index: swarm_client/tools/run_swarm_tests_on_swarm.py |
=================================================================== |
--- swarm_client/tools/run_swarm_tests_on_swarm.py (revision 235167) |
+++ swarm_client/tools/run_swarm_tests_on_swarm.py (working copy) |
@@ -1,249 +0,0 @@ |
-#!/usr/bin/env python |
-# Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-# Use of this source code is governed by a BSD-style license that can be |
-# found in the LICENSE file. |
- |
-"""Runs the whole set unit tests on swarm.""" |
- |
-import datetime |
-import glob |
-import getpass |
-import hashlib |
-import logging |
-import optparse |
-import os |
-import shutil |
-import subprocess |
-import sys |
-import tempfile |
-import time |
- |
-BASE_DIR = os.path.dirname(os.path.abspath(__file__)) |
-ROOT_DIR = os.path.dirname(BASE_DIR) |
- |
-sys.path.insert(0, ROOT_DIR) |
- |
-from utils import threading_utils |
- |
- |
-# Mapping of the sys.platform value into Swarm OS value. |
-OSES = {'win32': 'win', 'linux2': 'linux', 'darwin': 'mac'} |
- |
- |
-class Runner(object): |
- def __init__(self, isolate_server, swarm_server, add_task, progress, tempdir): |
- self.isolate_server = isolate_server |
- self.swarm_server = swarm_server |
- self.add_task = add_task |
- self.progress = progress |
- self.tempdir = tempdir |
- self.prefix = ( |
- getpass.getuser() + '-' + datetime.datetime.now().isoformat() + '-') |
- |
- @staticmethod |
- def _call(args): |
- start = time.time() |
- proc = subprocess.Popen( |
- [sys.executable] + args, |
- stdout=subprocess.PIPE, |
- stderr=subprocess.STDOUT, |
- cwd=ROOT_DIR) |
- stdout = proc.communicate()[0] |
- return proc.returncode, stdout, time.time() - start |
- |
- def archive(self, test, platform): |
- # Put the .isolated files in a temporary directory. This is simply done so |
- # the current directory doesn't have the following files created: |
- # - swarm_client_tests.isolated |
- # - swarm_client_tests.isolated.state |
- test_name = os.path.basename(test) |
- handle, isolated = tempfile.mkstemp( |
- dir=self.tempdir, prefix='run_swarm_tests_on_swarm_', |
- suffix='.isolated') |
- os.close(handle) |
- try: |
- returncode, stdout, duration = self._call( |
- [ |
- 'isolate.py', |
- 'archive', |
- '--isolate', os.path.join(BASE_DIR, 'run_a_test.isolate'), |
- '--isolated', isolated, |
- '--outdir', self.isolate_server, |
- '--variable', 'TEST_EXECUTABLE', test, |
- '--variable', 'OS', OSES[platform], |
- ]) |
- step_name = '%s/%s (%3.2fs)' % (platform, test_name, duration) |
- if returncode: |
- self.progress.update_item( |
- 'Failed to archive %s\n%s' % (step_name, stdout), index=1) |
- else: |
- hash_value = hashlib.sha1(open(isolated, 'rb').read()).hexdigest() |
- logging.info('%s: %s', step_name, hash_value) |
- self.progress.update_item('Archived %s' % step_name, index=1) |
- self.add_task(0, self.trigger, test, platform, hash_value) |
- finally: |
- try: |
- os.remove(isolated) |
- except OSError: |
- logging.debug('%s was already deleted', isolated) |
- return None |
- |
- def trigger(self, test, platform, hash_value): |
- test_name = os.path.basename(test) |
- returncode, stdout, duration = self._call( |
- [ |
- 'swarming.py', |
- 'trigger', |
- '--os', platform, |
- '--swarming', self.swarm_server, |
- '--task-prefix', self.prefix, |
- '--isolate-server', self.isolate_server, |
- '--task', |
- # Isolated hash. |
- hash_value, |
- # Test name. |
- 'swarm_client_tests_%s_%s' % (platform, test_name), |
- # Number of shards. |
- '1', |
- # test filter. |
- '*', |
- ]) |
- step_name = '%s/%s (%3.2fs)' % (platform, test_name, duration) |
- if returncode: |
- self.progress.update_item( |
- 'Failed to trigger %s\n%s' % (step_name, stdout), index=1) |
- else: |
- self.progress.update_item('Triggered %s' % step_name, index=1) |
- self.add_task(0, self.get_result, test, platform) |
- return None |
- |
- def get_result(self, test, platform): |
- test_name = os.path.basename(test) |
- name = '%s_%s' % (platform, test_name) |
- returncode, stdout, duration = self._call( |
- [ |
- 'swarming.py', |
- 'collect', |
- '--swarming', self.swarm_server, |
- self.prefix + 'swarm_client_tests_' + name, |
- ]) |
- step_name = '%s/%s (%3.2fs)' % (platform, test_name, duration) |
- # Only print the output for failures, successes are unexciting. |
- if returncode: |
- self.progress.update_item( |
- 'Failed %s:\n%s' % (step_name, stdout), index=1) |
- return (test_name, platform, stdout) |
- self.progress.update_item('Passed %s' % step_name, index=1) |
- return None |
- |
- |
-def run_swarm_tests_on_swarm(oses, tests, logs, isolate_server, swarm_server): |
- runs = len(tests) * len(oses) |
- total = 3 * runs |
- columns = [('index', 0), ('size', total)] |
- progress = threading_utils.Progress(columns) |
- progress.use_cr_only = False |
- tempdir = tempfile.mkdtemp(prefix='swarm_client_tests') |
- try: |
- with threading_utils.ThreadPoolWithProgress( |
- progress, runs, runs, total) as pool: |
- start = time.time() |
- runner = Runner( |
- isolate_server, swarm_server, pool.add_task, progress, tempdir) |
- for test in tests: |
- for platform in oses: |
- pool.add_task(0, runner.archive, test, platform) |
- |
- failed_tests = pool.join() |
- duration = time.time() - start |
- print('') |
- finally: |
- shutil.rmtree(tempdir) |
- |
- if logs: |
- os.makedirs(logs) |
- for test, platform, stdout in failed_tests: |
- name = '%s_%s' % (platform, os.path.basename(test)) |
- with open(os.path.join(logs, name + '.log'), 'wb') as f: |
- f.write(stdout) |
- |
- print('Completed in %3.2fs' % duration) |
- if failed_tests: |
- failed_tests_per_os = {} |
- for test, platform, _ in failed_tests: |
- failed_tests_per_os.setdefault(test, []).append(platform) |
- print('Detected the following failures:') |
- for test, platforms in failed_tests_per_os.iteritems(): |
- print(' %s on %s' % (test, ', '.join(sorted(platforms)))) |
- return bool(failed_tests) |
- |
- |
-def main(): |
- parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) |
- parser.add_option( |
- '-I', '--isolate-server', |
- metavar='URL', default='', |
- help='Isolate server to use') |
- parser.add_option( |
- '-S', '--swarming', |
- metavar='URL', default='', |
- help='Swarming server to use') |
- parser.add_option( |
- '-l', '--logs', |
- help='Destination where to store the failure logs (recommended)') |
- parser.add_option('-o', '--os', help='Run tests only on this OS') |
- parser.add_option('-t', '--test', help='Run only this test') |
- parser.add_option('-v', '--verbose', action='store_true') |
- options, args = parser.parse_args() |
- if args: |
- parser.error('Unsupported argument %s' % args) |
- if options.verbose: |
- os.environ['ISOLATE_DEBUG'] = '1' |
- |
- if not options.isolate_server: |
- parser.error('--isolate-server is required.') |
- if not options.swarming: |
- parser.error('--swarming is required.') |
- |
- logging.basicConfig(level=logging.DEBUG if options.verbose else logging.ERROR) |
- |
- # Note that the swarm and the isolate code use different strings for the |
- # different oses. |
- oses = OSES.keys() |
- tests = [ |
- os.path.relpath(i, BASE_DIR) |
- for i in glob.iglob(os.path.join(ROOT_DIR, 'tests', '*_test.py')) |
- ] |
- |
- if options.test: |
- valid_tests = sorted(map(os.path.basename, tests)) |
- if not options.test in valid_tests: |
- parser.error( |
- '--test %s is unknown. Valid values are:\n%s' % ( |
- options.test, '\n'.join(' ' + i for i in valid_tests))) |
- tests = [t for t in tests if t.endswith(os.path.sep + options.test)] |
- |
- if options.os: |
- if options.os not in oses: |
- parser.error( |
- '--os %s is unknown. Valid values are %s' % ( |
- options.os, ', '.join(sorted(oses)))) |
- oses = [options.os] |
- |
- if sys.platform in ('win32', 'cygwin'): |
- # If we are on Windows, don't generate the tests for Linux and Mac since |
- # they use symlinks and we can't create symlinks on windows. |
- oses = ['win32'] |
- if options.os != 'win32': |
- print('Linux and Mac tests skipped since running on Windows.') |
- |
- return run_swarm_tests_on_swarm( |
- oses, |
- tests, |
- options.logs, |
- options.isolate_server, |
- options.swarming) |
- |
- |
-if __name__ == '__main__': |
- sys.exit(main()) |