def testJoinTimeout(self):
   def f():
     pass
   event = threading.Event()
   def g():
     event.wait()
   group = reraiser_thread.ReraiserThreadGroup(
       [reraiser_thread.ReraiserThread(g),
        reraiser_thread.ReraiserThread(f)])
   group.StartAll()
   with self.assertRaises(reraiser_thread.TimeoutError):
     group.JoinAll(watchdog_timer.WatchdogTimer(0.01))
   event.set()
Exemple #2
0
    def __call__(self, *args, **kwargs):
        """Emulate calling |self| with |args| and |kwargs|.

    Note that this call is asynchronous. Call pFinish on the return value to
    block until the call finishes.

    Returns:
      A Parallelizer wrapping the ReraiserThreadGroup running the call in
      parallel.
    Raises:
      AttributeError if the wrapped objects aren't callable.
    """
        self.pGet(None)

        if not self._objs:
            raise AttributeError('Nothing to call.')
        for o in self._objs:
            if not callable(o):
                raise AttributeError("'%s' is not callable" % o.__name__)

        r = type(self)(self._orig_objs)
        r._objs = reraiser_thread.ReraiserThreadGroup([
            reraiser_thread.ReraiserThread(o,
                                           args=args,
                                           kwargs=kwargs,
                                           name='%s.%s' % (str(d), o.__name__))
            for d, o in zip(self._orig_objs, self._objs)
        ])
        r._objs.StartAll()  # pylint: disable=W0212
        return r
Exemple #3
0
    def pMap(self, f, *args, **kwargs):
        """Map a function across the current wrapped objects in parallel.

    This calls f(o, *args, **kwargs) for each o in the set of wrapped objects.

    Note that this call is asynchronous. Call pFinish on the return value to
    block until the call finishes.

    Args:
      f: The function to call.
      args: The positional args to pass to f.
      kwargs: The keyword args to pass to f.
    Returns:
      A Parallelizer wrapping the ReraiserThreadGroup running the map in
      parallel.
    """
        self._assertNoShadow('pMap')
        r = type(self)(self._orig_objs)
        r._objs = reraiser_thread.ReraiserThreadGroup([
            reraiser_thread.ReraiserThread(f,
                                           args=tuple([o] + list(args)),
                                           kwargs=kwargs,
                                           name='%s(%s)' % (f.__name__, d))
            for d, o in zip(self._orig_objs, self._objs)
        ])
        r._objs.StartAll()  # pylint: disable=W0212
        return r
def _RunAllTests(runners, tests, num_retries, timeout=None):
    """Run all tests using the given TestRunners.

  Args:
    runners: a list of TestRunner objects.
    tests: a list of Tests to run using the given TestRunners.
    num_retries: number of retries for a test.
    timeout: watchdog timeout in seconds, defaults to the default timeout.

  Returns:
    A TestRunResults object.
  """
    logging.warning('Running %s tests with %s test runners.' %
                    (len(tests), len(runners)))
    tests_collection = _TestCollection([_Test(t) for t in tests])
    results = []
    watcher = watchdog_timer.WatchdogTimer(timeout)
    workers = reraiser_thread.ReraiserThreadGroup([
        reraiser_thread.ReraiserThread(
            _RunTestsFromQueue,
            [r, tests_collection, results, watcher, num_retries],
            name=r.device[-4:]) for r in runners
    ])
    workers.StartAll()
    workers.JoinAll(watcher)
    run_results = base_test_result.TestRunResults()
    for r in results:
        run_results.AddTestRunResults(r)
    return run_results
Exemple #5
0
def _CreateRunners(runner_factory, devices, timeout=None):
    """Creates a test runner for each device and calls SetUp() in parallel.

  Note: if a device is unresponsive the corresponding TestRunner will not be
    included in the returned list.

  Args:
    runner_factory: Callable that takes a device and index and returns a
      TestRunner object.
    devices: List of device serial numbers as strings.
    timeout: Watchdog timeout in seconds, defaults to the default timeout.

  Returns:
    A list of TestRunner objects.
  """
    logging.warning('Creating %s test runners.' % len(devices))
    runners = []
    counter = _ThreadSafeCounter()
    threads = reraiser_thread.ReraiserThreadGroup([
        reraiser_thread.ReraiserThread(_SetUp,
                                       [runner_factory, d, runners, counter],
                                       name=d[-4:]) for d in devices
    ])
    threads.StartAll()
    threads.JoinAll(watchdog_timer.WatchdogTimer(timeout))
    return runners
Exemple #6
0
def Run(func, timeout, retries, args=[], kwargs={}):
    """Runs the passed function in a separate thread with timeouts and retries.

  Args:
    func: the function to be wrapped.
    timeout: the timeout in seconds for each try.
    retries: the number of retries.
    args: list of positional args to pass to |func|.
    kwargs: dictionary of keyword args to pass to |func|.

  Returns:
    The return value of func(*args, **kwargs).
  """
    # The return value uses a list because Python variables are references, not
    # values. Closures make a copy of the reference, so updating the closure's
    # reference wouldn't update where the original reference pointed.
    ret = [None]

    def RunOnTimeoutThread():
        ret[0] = func(*args, **kwargs)

    while True:
        try:
            name = 'TimeoutThread-for-%s' % threading.current_thread().name
            thread_group = reraiser_thread.ReraiserThreadGroup([
                reraiser_thread.ReraiserThread(RunOnTimeoutThread, name=name)
            ])
            thread_group.StartAll()
            thread_group.JoinAll(watchdog_timer.WatchdogTimer(timeout))
            return ret[0]
        except:
            if retries <= 0:
                raise
            retries -= 1
def _RunAllTests(runners,
                 test_collection_factory,
                 num_retries,
                 timeout=None,
                 tag_results_with_device=False):
    """Run all tests using the given TestRunners.

  Args:
    runners: A list of TestRunner objects.
    test_collection_factory: A callable to generate a _TestCollection object for
        each test runner.
    num_retries: Number of retries for a test.
    timeout: Watchdog timeout in seconds.
    tag_results_with_device: If True, appends the name of the device on which
        the test was run to the test name. Used when replicating to identify
        which device ran each copy of the test, and to ensure each copy of the
        test is recorded separately.

  Returns:
    A tuple of (TestRunResults object, exit code)
  """
    logging.warning('Running tests with %s test runners.' % (len(runners)))
    results = []
    exit_code = 0
    run_results = base_test_result.TestRunResults()
    watcher = watchdog_timer.WatchdogTimer(timeout)
    test_collections = [test_collection_factory() for _ in runners]

    threads = [
        reraiser_thread.ReraiserThread(
            _RunTestsFromQueue,
            [r, tc, results, watcher, num_retries, tag_results_with_device],
            name=r.device_serial[-4:])
        for r, tc in zip(runners, test_collections)
    ]

    workers = reraiser_thread.ReraiserThreadGroup(threads)
    workers.StartAll()

    # Catch DeviceUnreachableErrors and set a warning exit code
    try:
        workers.JoinAll(watcher)
    except (
            adb_wrapper.DeviceUnreachableError,
            # TODO(jbudorick) Remove this once the underlying implementations
            #                 for the above are switched or wrapped.
            android_commands.errors.DeviceUnresponsiveError) as e:
        logging.error(e)
        exit_code = constants.WARNING_EXIT_CODE

    assert all([len(tc) == 0 for tc in test_collections]), (
        'Some tests were not run, all devices are likely offline (ran %d tests)'
        % len(run_results.GetAll()))

    for r in results:
        run_results.AddTestRunResults(r)
    if not run_results.DidRunPass():
        exit_code = constants.ERROR_EXIT_CODE
    return (run_results, exit_code)
 def testJoinRaise(self):
   def f():
     raise TestException
   group = reraiser_thread.ReraiserThreadGroup(
     [reraiser_thread.ReraiserThread(f) for _ in xrange(5)])
   group.StartAll()
   with self.assertRaises(TestException):
     group.JoinAll()
  def testRaise(self):
    def f():
      raise TestException

    thread = reraiser_thread.ReraiserThread(f)
    thread.start()
    thread.join()
    with self.assertRaises(TestException):
      thread.ReraiseIfException()
Exemple #10
0
def _RunAllTests(runners, test_collection_factory, num_retries, timeout=None,
                 tag_results_with_device=False):
  """Run all tests using the given TestRunners.

  Args:
    runners: A list of TestRunner objects.
    test_collection_factory: A callable to generate a TestCollection object for
        each test runner.
    num_retries: Number of retries for a test.
    timeout: Watchdog timeout in seconds.
    tag_results_with_device: If True, appends the name of the device on which
        the test was run to the test name. Used when replicating to identify
        which device ran each copy of the test, and to ensure each copy of the
        test is recorded separately.

  Returns:
    A tuple of (TestRunResults object, exit code)
  """
  logging.warning('Running tests with %s test runners.' % (len(runners)))
  results = []
  exit_code = 0
  run_results = base_test_result.TestRunResults()
  watcher = watchdog_timer.WatchdogTimer(timeout)
  test_collections = [test_collection_factory() for _ in runners]

  threads = [
      reraiser_thread.ReraiserThread(
          _RunTestsFromQueue,
          [r, tc, results, watcher, num_retries, tag_results_with_device],
          name=r.device_serial[-4:])
      for r, tc in zip(runners, test_collections)]

  workers = reraiser_thread.ReraiserThreadGroup(threads)
  workers.StartAll()

  try:
    workers.JoinAll(watcher)
  except device_errors.CommandFailedError:
    logging.exception('Command failed on device.')
  except device_errors.CommandFailedError:
    logging.exception('Command timed out on device.')
  except device_errors.DeviceUnreachableError:
    logging.exception('Device became unreachable.')

  if not all((len(tc) == 0 for tc in test_collections)):
    logging.error('Only ran %d tests (all devices are likely offline).' %
                  len(results))
    for tc in test_collections:
      run_results.AddResults(base_test_result.BaseTestResult(
          t, base_test_result.ResultType.UNKNOWN) for t in tc.test_names())

  for r in results:
    run_results.AddTestRunResults(r)
  if not run_results.DidRunPass():
    exit_code = constants.ERROR_EXIT_CODE
  return (run_results, exit_code)
Exemple #11
0
def _TearDownRunners(runners):
    """Calls TearDown() for each test runner in parallel.
  Args:
    runners: a list of TestRunner objects.
  """
    threads = reraiser_thread.ReraiserThreadGroup([
        reraiser_thread.ReraiserThread(runner.TearDown) for runner in runners
    ])
    threads.StartAll()
    threads.JoinAll()
  def testInit(self):
    ran = [False] * 5
    def f(i):
      ran[i] = True

    group = reraiser_thread.ReraiserThreadGroup(
      [reraiser_thread.ReraiserThread(f, args=[i]) for i in range(5)])
    group.StartAll()
    group.JoinAll()
    for v in ran:
      self.assertTrue(v)
def _TearDownRunners(runners, timeout=None):
  """Calls TearDown() for each test runner in parallel.

  Args:
    runners: A list of TestRunner objects.
    timeout: Watchdog timeout in seconds, defaults to the default timeout.
  """
  threads = reraiser_thread.ReraiserThreadGroup(
      [reraiser_thread.ReraiserThread(r.TearDown, name=r.device[-4:])
       for r in runners])
  threads.StartAll()
  threads.JoinAll(watchdog_timer.WatchdogTimer(timeout))
  def testNominal(self):
    result = [None, None]

    def f(a, b=None):
      result[0] = a
      result[1] = b

    thread = reraiser_thread.ReraiserThread(f, [1], {'b': 2})
    thread.start()
    thread.join()
    self.assertEqual(result[0], 1)
    self.assertEqual(result[1], 2)
Exemple #15
0
def _RunAllTests(runners,
                 test_collection_factory,
                 num_retries,
                 timeout=None,
                 tag_results_with_device=False):
    """Run all tests using the given TestRunners.

  Args:
    runners: A list of TestRunner objects.
    test_collection_factory: A callable to generate a _TestCollection object for
        each test runner.
    num_retries: Number of retries for a test.
    timeout: Watchdog timeout in seconds.
    tag_results_with_device: If True, appends the name of the device on which
        the test was run to the test name. Used when replicating to identify
        which device ran each copy of the test, and to ensure each copy of the
        test is recorded separately.

  Returns:
    A tuple of (TestRunResults object, exit code)
  """
    logging.warning('Running tests with %s test runners.' % (len(runners)))
    results = []
    exit_code = 0
    watcher = watchdog_timer.WatchdogTimer(timeout)

    workers = reraiser_thread.ReraiserThreadGroup([
        reraiser_thread.ReraiserThread(_RunTestsFromQueue, [
            r,
            test_collection_factory(), results, watcher, num_retries,
            tag_results_with_device
        ],
                                       name=r.device[-4:]) for r in runners
    ])
    run_results = base_test_result.TestRunResults()
    workers.StartAll()

    # Catch DeviceUnresponsiveErrors and set a warning exit code
    try:
        workers.JoinAll(watcher)
    except android_commands.errors.DeviceUnresponsiveError as e:
        logging.error(e)
        exit_code = constants.WARNING_EXIT_CODE

    for r in results:
        run_results.AddTestRunResults(r)
    if not run_results.DidRunPass():
        exit_code = constants.ERROR_EXIT_CODE
    return (run_results, exit_code)
Exemple #16
0
def _RunAllTests(runners, tests):
    """Run all tests using the given TestRunners.

  Args:
    runners: a list of TestRunner objects.
    tests: a list of Tests to run using the given TestRunners.

  Returns:
    A TestResults object.
  """
    logging.warning('****Running %s tests with %s test runners.' %
                    (len(tests), len(runners)))
    tests_collection = _TestCollection([_Test(t) for t in tests])
    results = []
    workers = reraiser_thread.ReraiserThreadGroup([
        reraiser_thread.ReraiserThread(_RunTestsFromQueue,
                                       [r, tests_collection, results])
        for r in runners
    ])
    workers.StartAll()
    workers.JoinAll()
    return test_result.TestResults.FromTestResults(results)
Exemple #17
0
def _CreateRunners(runner_factory, devices):
    """Creates a test runner for each device and calls SetUp() in parallel.

  Note: if a device is unresponsive the corresponding TestRunner will not be
    included in the returned list.

  Args:
    runner_factory: callable that takes a device and returns a TestRunner.
    devices: list of device serial numbers as strings.

  Returns:
    A list of TestRunner objects.
  """
    logging.warning('****Creating %s test runners.' % len(devices))
    test_runners = []
    threads = reraiser_thread.ReraiserThreadGroup([
        reraiser_thread.ReraiserThread(_SetUp,
                                       [runner_factory, d, test_runners])
        for d in devices
    ])
    threads.StartAll()
    threads.JoinAll()
    return test_runners