#!/usr/bin/python
"""Run tests in parallel."""

import argparse
import glob
import itertools
import multiprocessing
import sys
import time

import jobset
import watch_dirs

# flags required for make for each configuration
_CONFIGS = ['dbg', 'opt', 'tsan', 'msan', 'asan']

# parse command line
argp = argparse.ArgumentParser(description='Run grpc tests.')
argp.add_argument('-c', '--config',
                  choices=['all'] + _CONFIGS,
                  nargs='+',
                  default=['all'])
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 config
configs = [cfg
           for cfg in itertools.chain.from_iterable(
               _CONFIGS if x == 'all' else [x]
               for x in args.config)]
filters = args.test_filter
runs_per_test = args.runs_per_test
forever = args.forever


def _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' % max(multiprocessing.cpu_count() / len(configs), 1),
        'buildtests_c',
        'CONFIG=%s' % cfg]
       for cfg in configs), check_cancelled):
    sys.exit(1)

  # run all the tests
  jobset.run(([x]
              for x in itertools.chain.from_iterable(
                  itertools.chain.from_iterable(itertools.repeat(
                      glob.glob('bins/%s/%s_test' % (config, filt)),
                      runs_per_test))
                  for config in configs
                  for filt in filters)), 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)


@@ -264,16 +264,42 @@
  'asan'%5D
+%0A_DEFAULT = %5B'dbg', 'opt'%5D
 %0A%0A# pars
@@ -512,23 +512,24 @@
 default=
-%5B'all'%5D
+_DEFAULT
 )%0Aargp.a

Remove ?san from the default tests.