blob: b4d426f8dee4196684bd12e815d52511335309f0 [file] [log] [blame]
Nicolas Nobleddef2462015-01-06 18:08:25 -08001#!/usr/bin/python
2"""Run tests in parallel."""
3
4import argparse
5import glob
6import itertools
7import multiprocessing
8import sys
ctiller3040cb72015-01-07 12:13:17 -08009import time
Nicolas Nobleddef2462015-01-06 18:08:25 -080010
11import jobset
ctiller3040cb72015-01-07 12:13:17 -080012import watch_dirs
Nicolas Nobleddef2462015-01-06 18:08:25 -080013
Craig Tiller738c3342015-01-12 14:28:33 -080014# SimpleConfig: just compile with CONFIG=config, and run the binary to test
15class SimpleConfig(object):
16 def __init__(self, config):
17 self.build_config = config
18
19 def run_command(self, binary):
20 return [binary]
21
22
23# ValgrindConfig: compile with some CONFIG=config, but use valgrind to run
24class ValgrindConfig(object):
25 def __init__(self, config):
26 self.build_config = config
27
28 def run_command(self, binary):
29 return ['valgrind', binary]
30
31
32# different configurations we can run under
33_CONFIGS = {
34 'dbg': SimpleConfig('dbg'),
35 'opt': SimpleConfig('opt'),
36 'tsan': SimpleConfig('tsan'),
37 'msan': SimpleConfig('msan'),
38 'asan': SimpleConfig('asan'),
Craig Tiller934baa32015-01-12 18:19:45 -080039 'gcov': SimpleConfig('gcov'),
Craig Tiller738c3342015-01-12 14:28:33 -080040 'valgrind': ValgrindConfig('dbg'),
41 }
42
43
Craig Tillerb29797b2015-01-12 13:51:54 -080044_DEFAULT = ['dbg', 'opt']
Craig Tiller7c1d7f72015-01-12 17:08:33 -080045_MAKE_TEST_TARGETS = ['buildtests_c', 'buildtests_cxx']
Nicolas Nobleddef2462015-01-06 18:08:25 -080046
47# parse command line
48argp = argparse.ArgumentParser(description='Run grpc tests.')
49argp.add_argument('-c', '--config',
Craig Tiller738c3342015-01-12 14:28:33 -080050 choices=['all'] + sorted(_CONFIGS.keys()),
Nicolas Nobleddef2462015-01-06 18:08:25 -080051 nargs='+',
Craig Tillerb29797b2015-01-12 13:51:54 -080052 default=_DEFAULT)
Nicolas Nobleddef2462015-01-06 18:08:25 -080053argp.add_argument('-t', '--test-filter', nargs='*', default=['*'])
54argp.add_argument('-n', '--runs_per_test', default=1, type=int)
ctiller3040cb72015-01-07 12:13:17 -080055argp.add_argument('-f', '--forever',
56 default=False,
57 action='store_const',
58 const=True)
Nicolas Nobleddef2462015-01-06 18:08:25 -080059args = argp.parse_args()
60
61# grab config
Craig Tiller738c3342015-01-12 14:28:33 -080062run_configs = set(_CONFIGS[cfg]
63 for cfg in itertools.chain.from_iterable(
64 _CONFIGS.iterkeys() if x == 'all' else [x]
65 for x in args.config))
66build_configs = set(cfg.build_config for cfg in run_configs)
Nicolas Nobleddef2462015-01-06 18:08:25 -080067filters = args.test_filter
68runs_per_test = args.runs_per_test
ctiller3040cb72015-01-07 12:13:17 -080069forever = args.forever
Nicolas Nobleddef2462015-01-06 18:08:25 -080070
Nicolas Nobleddef2462015-01-06 18:08:25 -080071
ctiller3040cb72015-01-07 12:13:17 -080072def _build_and_run(check_cancelled):
73 """Do one pass of building & running tests."""
74 # build latest, sharing cpu between the various makes
75 if not jobset.run(
76 (['make',
Craig Tiller738c3342015-01-12 14:28:33 -080077 '-j', '%d' % (multiprocessing.cpu_count() + 1),
Craig Tiller7c1d7f72015-01-12 17:08:33 -080078 target,
ctiller3040cb72015-01-07 12:13:17 -080079 'CONFIG=%s' % cfg]
Craig Tillerbe7b0922015-01-13 12:29:51 -080080 for cfg in build_configs
Craig Tiller7c1d7f72015-01-12 17:08:33 -080081 for target in _MAKE_TEST_TARGETS),
82 check_cancelled, maxjobs=1):
Craig Tillerd86a3942015-01-14 12:48:54 -080083 return 1
ctiller3040cb72015-01-07 12:13:17 -080084
85 # run all the tests
Craig Tillerd86a3942015-01-14 12:48:54 -080086 if not jobset.run((
Craig Tiller738c3342015-01-12 14:28:33 -080087 config.run_command(x)
88 for config in run_configs
89 for filt in filters
90 for x in itertools.chain.from_iterable(itertools.repeat(
91 glob.glob('bins/%s/%s_test' % (
92 config.build_config, filt)),
Craig Tillerd86a3942015-01-14 12:48:54 -080093 runs_per_test))), check_cancelled):
94 return 2
95
96 return 0
ctiller3040cb72015-01-07 12:13:17 -080097
98
99if forever:
100 while True:
101 dw = watch_dirs.DirWatcher(['src', 'include', 'test'])
102 initial_time = dw.most_recent_change()
103 have_files_changed = lambda: dw.most_recent_change() != initial_time
104 _build_and_run(have_files_changed)
105 while not have_files_changed():
106 time.sleep(1)
107else:
Craig Tillerd86a3942015-01-14 12:48:54 -0800108 sys.exit(_build_and_run(lambda: False))
ctiller3040cb72015-01-07 12:13:17 -0800109