def run_tests(self, expectations, test_inputs, tests_to_skip, num_workers, retry_attempt): batch_size = self._options.derived_batch_size # If we're retrying a test, then it's because we think it might be flaky # and rerunning it might provide a different result. We must restart # content shell to get a valid result, as otherwise state can leak # from previous tests. To do so, we set a batch size of 1, as that # prevents content shell reuse. if not self._options.must_use_derived_batch_size and retry_attempt >= 1: batch_size = 1 self._expectations = expectations self._test_inputs = test_inputs test_run_results = TestRunResults( self._expectations, len(test_inputs) + len(tests_to_skip), self._test_result_sink, ) self._current_run_results = test_run_results self._printer.num_tests = len(test_inputs) self._printer.num_completed = 0 for test_name in set(tests_to_skip): result = test_results.TestResult(test_name) result.type = ResultType.Skip test_run_results.add( result, expected=True, test_is_slow=self._test_is_slow(test_name)) self._printer.write_update('Sharding tests ...') locked_shards, unlocked_shards = self._sharder.shard_tests( test_inputs, int(self._options.child_processes), self._options.fully_parallel, self._options.virtual_parallel, batch_size == 1) self._reorder_tests_by_args(locked_shards) self._reorder_tests_by_args(unlocked_shards) # We don't have a good way to coordinate the workers so that they don't # try to run the shards that need a lock. The easiest solution is to # run all of the locked shards first. all_shards = locked_shards + unlocked_shards num_workers = min(num_workers, len(all_shards)) if retry_attempt < 1: self._printer.print_workers_and_shards(self._port, num_workers, len(all_shards), len(locked_shards)) if self._options.dry_run: return test_run_results self._printer.write_update( 'Starting %s ...' % grammar.pluralize('worker', num_workers)) start_time = time.time() try: with message_pool.get(self, self._worker_factory, num_workers, self._port.host) as pool: pool.run(('test_list', shard.name, shard.test_inputs, batch_size) for shard in all_shards) if self._shards_to_redo: num_workers -= len(self._shards_to_redo) if num_workers > 0: with message_pool.get(self, self._worker_factory, num_workers, self._port.host) as pool: pool.run(('test_list', shard.name, shard.test_inputs, batch_size) for shard in self._shards_to_redo) else: self._mark_interrupted_tests_as_skipped( self._current_run_results) raise TestRunInterruptedException( 'All workers have device failures. Exiting.') except TestRunInterruptedException as error: _log.warning(error.reason) test_run_results.interrupted = True except KeyboardInterrupt: self._printer.flush() self._printer.writeln('Interrupted, exiting ...') test_run_results.keyboard_interrupted = True except Exception as error: _log.debug('%s("%s") raised, exiting', error.__class__.__name__, error) raise finally: test_run_results.run_time = time.time() - start_time return test_run_results
def run_tests(self, expectations, test_inputs, tests_to_skip, num_workers, retry_attempt): self._expectations = expectations self._test_inputs = test_inputs self._retry_attempt = retry_attempt test_run_results = TestRunResults( self._expectations, len(test_inputs) + len(tests_to_skip)) self._current_run_results = test_run_results self._printer.num_tests = len(test_inputs) self._printer.num_completed = 0 if retry_attempt < 1: self._printer.print_expected( test_run_results, self._expectations.get_tests_with_result_type) for test_name in set(tests_to_skip): result = test_results.TestResult(test_name) result.type = test_expectations.SKIP test_run_results.add(result, expected=True, test_is_slow=self._test_is_slow(test_name)) self._printer.write_update('Sharding tests ...') locked_shards, unlocked_shards = self._sharder.shard_tests( test_inputs, int(self._options.child_processes), self._options.fully_parallel, self._options.batch_size == 1) self._reorder_tests_by_args(locked_shards) self._reorder_tests_by_args(unlocked_shards) # We don't have a good way to coordinate the workers so that they don't # try to run the shards that need a lock. The easiest solution is to # run all of the locked shards first. all_shards = locked_shards + unlocked_shards num_workers = min(num_workers, len(all_shards)) if retry_attempt < 1: self._printer.print_workers_and_shards(num_workers, len(all_shards), len(locked_shards)) if self._options.dry_run: return test_run_results self._printer.write_update('Starting %s ...' % grammar.pluralize('worker', num_workers)) start_time = time.time() try: with message_pool.get(self, self._worker_factory, num_workers, self._port.host) as pool: pool.run(('test_list', shard.name, shard.test_inputs) for shard in all_shards) if self._shards_to_redo: num_workers -= len(self._shards_to_redo) if num_workers > 0: with message_pool.get(self, self._worker_factory, num_workers, self._port.host) as pool: pool.run(('test_list', shard.name, shard.test_inputs) for shard in self._shards_to_redo) except TestRunInterruptedException as error: _log.warning(error.reason) test_run_results.interrupted = True except KeyboardInterrupt: self._printer.flush() self._printer.writeln('Interrupted, exiting ...') test_run_results.keyboard_interrupted = True except Exception as error: _log.debug('%s("%s") raised, exiting', error.__class__.__name__, error) raise finally: test_run_results.run_time = time.time() - start_time return test_run_results