| 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())
|
|
|