| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 | #!/usr/bin/python"""Run tests in parallel."""import argparseimport globimport itertoolsimport multiprocessingimport sysimport timeimport jobsetimport watch_dirs# SimpleConfig: just compile with CONFIG=config, and run the binary to testclass SimpleConfig(object):  def __init__(self, config):    self.build_config = config  def run_command(self, binary):    return [binary]# ValgrindConfig: compile with some CONFIG=config, but use valgrind to runclass ValgrindConfig(object):  def __init__(self, config):    self.build_config = config  def run_command(self, binary):    return ['valgrind', binary]# different configurations we can run under_CONFIGS = {  'dbg': SimpleConfig('dbg'),  'opt': SimpleConfig('opt'),  'tsan': SimpleConfig('tsan'),  'msan': SimpleConfig('msan'),  'asan': SimpleConfig('asan'),  'gcov': SimpleConfig('gcov'),  'valgrind': ValgrindConfig('dbg'),  }_DEFAULT = ['dbg', 'opt']_MAKE_TEST_TARGETS = ['buildtests_c', 'buildtests_cxx']# parse command lineargp = argparse.ArgumentParser(description='Run grpc tests.')argp.add_argument('-c', '--config',                  choices=['all'] + sorted(_CONFIGS.keys()),                  nargs='+',                  default=_DEFAULT)argp.add_argument('-t', '--test-filter', nargs='*', default=['*'])argp.add_argument('-n', '--runs_per_test', default=1, type=int)argp.add_argument('-f', '--forever',                  default=False,                  action='store_const',                  const=True)args = argp.parse_args()# grab configrun_configs = set(_CONFIGS[cfg]                  for cfg in itertools.chain.from_iterable(                      _CONFIGS.iterkeys() if x == 'all' else [x]                      for x in args.config))build_configs = set(cfg.build_config for cfg in run_configs)filters = args.test_filterruns_per_test = args.runs_per_testforever = args.foreverdef _build_and_run(check_cancelled):  """Do one pass of building & running tests."""  # build latest, sharing cpu between the various makes  if not jobset.run(      (['make',        '-j', '%d' % (multiprocessing.cpu_count() + 1),        target,        'CONFIG=%s' % cfg]       for cfg in build_configs       for target in _MAKE_TEST_TARGETS),      check_cancelled, maxjobs=1):    sys.exit(1)  # run all the tests  jobset.run((      config.run_command(x)      for config in run_configs      for filt in filters      for x in itertools.chain.from_iterable(itertools.repeat(          glob.glob('bins/%s/%s_test' % (              config.build_config, filt)),          runs_per_test))), check_cancelled)if forever:  while True:    dw = watch_dirs.DirWatcher(['src', 'include', 'test'])    initial_time = dw.most_recent_change()    have_files_changed = lambda: dw.most_recent_change() != initial_time    _build_and_run(have_files_changed)    while not have_files_changed():      time.sleep(1)else:  _build_and_run(lambda: False)
 |