示例#1
0
 def test_exception_no_fork(self):
     with OutputCapture(level=logging.INFO) as captured:
         with self.assertRaises(RuntimeError):
             with TaskPool(workers=1, force_fork=False) as pool:
                 pool.do(exception, 'Testing exception')
                 pool.wait()
     self.assertEqual(captured.webkitcorepy.log.getvalue(), '')
示例#2
0
    def test_single_no_fork(self):
        with OutputCapture(level=logging.WARNING) as captured:
            with TaskPool(workers=1, force_fork=False) as pool:
                pool.do(action, 'a')
                pool.do(log, logging.WARNING, '1')
                pool.wait()

        self.assertEqual(captured.stdout.getvalue(), 'action(a)\n')
        self.assertEqual(captured.webkitcorepy.log.getvalue(), '1\n')
示例#3
0
 def test_teardown_arguments(self):
     with OutputCapture() as captured:
         with TaskPool(workers=4, teardown=teardown, teardownargs=['Teardown argument']) as pool:
             for character in self.alphabet:
                 pool.do(action, character)
             pool.wait()
     self.assertEqual(
         sorted(captured.webkitcorepy.log.getvalue().splitlines()),
         ['worker/{} Teardown argument'.format(x) for x in range(4)],
     )
示例#4
0
 def test_setup(self):
     with OutputCapture() as captured:
         with TaskPool(workers=4, setup=setup) as pool:
             for character in self.alphabet:
                 pool.do(action, character)
             pool.wait()
     self.assertEqual(
         sorted(captured.webkitcorepy.log.getvalue().splitlines()),
         ['worker/{} Setting up'.format(x) for x in range(4)],
     )
示例#5
0
 def test_exception(self):
     with OutputCapture(level=logging.INFO) as captured:
         with self.assertRaises(RuntimeError):
             with TaskPool(workers=1, force_fork=True) as pool:
                 pool.do(exception, 'Testing exception')
                 pool.wait()
     self.assertEqual(
         captured.webkitcorepy.log.getvalue().splitlines(),
         ['worker/0 starting', 'worker/0 stopping'],
     )
示例#6
0
    def test_callback(self):
        sequence = []

        with OutputCapture():
            with TaskPool(workers=4) as pool:
                for character in self.alphabet:
                    pool.do(action, character, callback=lambda value: sequence.append(value))
                pool.wait()
        self.assertEqual(
            self.alphabet,
            ''.join(sorted(sequence)),
        )
示例#7
0
    def test_multiple(self):
        with OutputCapture(level=logging.INFO) as captured:
            with TaskPool(workers=4) as pool:
                for character in self.alphabet:
                    pool.do(action, character)
                pool.wait()

        lines = captured.stdout.getvalue().splitlines()
        self.assertEquals(sorted(lines), ['action({})'.format(character) for character in self.alphabet])
        self.assertEqual(
            sorted(captured.webkitcorepy.log.getvalue().splitlines()),
            sorted(['worker/{} starting'.format(number) for number in range(4)] + ['worker/{} stopping'.format(number) for number in range(4)]),
        )
示例#8
0
    def run_test(self, test_input, shard_name):
        self._batch_count += 1

        stop_when_done = False
        if 0 < self._batch_size <= self._batch_count:
            self._batch_count = 0
            stop_when_done = True

        test_timeout_sec = self._timeout(test_input)
        start = time.time()

        TaskPool.Process.queue.send(
            TaskPool.Task(
                handle_started_test,
                None,
                TaskPool.Process.name,
                test_input.test_name,
            ))

        result = self._run_test_with_or_without_timeout(
            test_input, test_timeout_sec, stop_when_done)
        result.shard_name = shard_name
        result.worker_name = TaskPool.Process.name
        result.total_run_time = time.time() - start
        result.test_number = self._num_tests
        self._num_tests += 1

        TaskPool.Process.queue.send(
            TaskPool.Task(
                handle_finished_test,
                None,
                TaskPool.Process.name,
                result,
            ))

        self._clean_up_after_test(test_input, result)
示例#9
0
    def run(self, tests, num_workers):
        if not tests:
            return

        self.printer.write_update('Sharding tests ...')
        shards = Runner._shard_tests(tests)

        original_level = server_process_logger.level
        server_process_logger.setLevel(logging.CRITICAL)

        try:
            if Runner.instance:
                raise RuntimeError('Cannot nest API test runners')
            Runner.instance = self
            self._num_workers = min(num_workers, len(shards))

            devices = None
            if getattr(self.port, 'DEVICE_MANAGER', None):
                devices = dict(
                    available_devices=self.port.DEVICE_MANAGER.
                    AVAILABLE_DEVICES,
                    initialized_devices=self.port.DEVICE_MANAGER.
                    INITIALIZED_DEVICES,
                )

            with TaskPool(
                    workers=self._num_workers,
                    setup=setup_shard,
                    setupkwargs=dict(port=self.port, devices=devices),
                    teardown=teardown_shard,
            ) as pool:
                for name, tests in iteritems(shards):
                    pool.do(run_shard, name, *tests)
                pool.wait()

        finally:
            server_process_logger.setLevel(original_level)
            Runner.instance = None
示例#10
0
 def test_invalid_shutdown(self):
     with OutputCapture():
         with self.assertRaises(TaskPool.Exception):
             with TaskPool(workers=1, teardown=teardown, grace_period=1, force_fork=True) as pool:
                 pool.do(wait, 2)
示例#11
0
    def run(self, name, *tests):
        binary_name = name.split('.')[0]
        remaining_tests = ['.'.join(test.split('.')[1:]) for test in tests]

        # Try to run the shard in a single process.
        while remaining_tests and not self._port.get_option('run_singly'):
            starting_length = len(remaining_tests)
            server_process = ServerProcess(
                self._port,
                binary_name,
                Runner.command_for_port(self._port, [
                    self._port._build_path(binary_name),
                    '--gtest_filter={}'.format(':'.join(remaining_tests))
                ]),
                env=self._port.environment_for_api_tests())

            try:
                deadline = time.time() + self._timeout
                last_test = None
                last_status = None
                stdout_buffer = ''

                server_process.start()
                while remaining_tests:
                    stdout = string_utils.decode(
                        server_process.read_stdout_line(deadline),
                        target_type=str)

                    # If we've triggered a timeout, we don't know which test caused it. Break out and run singly.
                    if stdout is None and server_process.timed_out:
                        break

                    if stdout is None and server_process.has_crashed():
                        # It's possible we crashed before printing anything.
                        if last_status == Runner.STATUS_PASSED:
                            last_test = None
                        else:
                            last_status = Runner.STATUS_CRASHED
                        break

                    assert stdout is not None
                    stdout_split = stdout.rstrip().split(' ')
                    if len(stdout_split) != 2 or not (
                            stdout_split[0].startswith('**')
                            and stdout_split[0].endswith('**')):
                        stdout_buffer += stdout
                        continue
                    if last_test is not None:
                        remaining_tests.remove(last_test)

                        for line in stdout_buffer.splitlines(False):
                            _log.error(line)
                        TaskPool.Process.queue.send(
                            TaskPool.Task(
                                report_result,
                                None,
                                TaskPool.Process.name,
                                '{}.{}'.format(binary_name, last_test),
                                last_status,
                                stdout_buffer,
                            ))
                        deadline = time.time() + self._timeout
                        stdout_buffer = ''

                    if '**PASS**' == stdout_split[0]:
                        last_status = Runner.STATUS_PASSED
                    else:
                        last_status = Runner.STATUS_FAILED
                    last_test = stdout_split[1]

                # We assume that stderr is only relevant if there is a crash (meaning we triggered an assert)
                if last_test:
                    remaining_tests.remove(last_test)
                    stdout_buffer += string_utils.decode(
                        server_process.pop_all_buffered_stdout(),
                        target_type=str)
                    stderr_buffer = string_utils.decode(
                        server_process.pop_all_buffered_stderr(),
                        target_type=str
                    ) if last_status == Runner.STATUS_CRASHED else ''
                    for line in (stdout_buffer +
                                 stderr_buffer).splitlines(keepends=False):
                        _log.error(line)

                    TaskPool.Process.queue.send(
                        TaskPool.Task(
                            report_result,
                            None,
                            TaskPool.Process.name,
                            '{}.{}'.format(binary_name, last_test),
                            last_status,
                            self._filter_noisy_output(stdout_buffer +
                                                      stderr_buffer),
                        ))

                if server_process.timed_out:
                    break

                # If we weren't able to determine the results for any tests, we need to run what remains singly.
                if starting_length == len(remaining_tests):
                    break
            finally:
                server_process.stop()

        # Now, just try and run the rest of the tests singly.
        for test in remaining_tests:
            self._run_single_test(binary_name, test)
示例#12
0
    def _run_single_test(self, binary_name, test):
        server_process = ServerProcess(
            self._port,
            binary_name,
            Runner.command_for_port(self._port, [
                self._port._build_path(binary_name),
                '--gtest_filter={}'.format(test)
            ]),
            env=self._port.environment_for_api_tests())

        status = Runner.STATUS_RUNNING
        if test.split('.')[1].startswith(
                'DISABLED_') and not self._port.get_option('force'):
            status = Runner.STATUS_DISABLED

        stdout_buffer = ''
        stderr_buffer = ''

        try:
            deadline = time.time() + self._timeout
            if status != Runner.STATUS_DISABLED:
                server_process.start()

            while status == Runner.STATUS_RUNNING:
                stdout_line, stderr_line = server_process.read_either_stdout_or_stderr_line(
                    deadline)
                if not stderr_line and not stdout_line:
                    break

                if stderr_line:
                    stderr_line = string_utils.decode(stderr_line,
                                                      target_type=str)
                    stderr_buffer += stderr_line
                    _log.error(stderr_line[:-1])
                if stdout_line:
                    stdout_line = string_utils.decode(stdout_line,
                                                      target_type=str)
                    if '**PASS**' in stdout_line:
                        status = Runner.STATUS_PASSED
                    elif '**FAIL**' in stdout_line:
                        status = Runner.STATUS_FAILED
                    else:
                        stdout_buffer += stdout_line
                        _log.error(stdout_line[:-1])

            if status == Runner.STATUS_DISABLED:
                pass
            elif server_process.timed_out:
                status = Runner.STATUS_TIMEOUT
            elif server_process.has_crashed():
                status = Runner.STATUS_CRASHED
            elif status == Runner.STATUS_RUNNING:
                status = Runner.STATUS_FAILED

        finally:
            remaining_stderr = string_utils.decode(
                server_process.pop_all_buffered_stderr(), target_type=str)
            remaining_stdout = string_utils.decode(
                server_process.pop_all_buffered_stdout(), target_type=str)
            for line in (remaining_stdout +
                         remaining_stderr).splitlines(False):
                _log.error(line)
            output_buffer = stderr_buffer + stdout_buffer + remaining_stderr + remaining_stdout
            server_process.stop()

        TaskPool.Process.queue.send(
            TaskPool.Task(
                report_result,
                None,
                TaskPool.Process.name,
                '{}.{}'.format(binary_name, test),
                status,
                self._filter_noisy_output(output_buffer),
            ))
示例#13
0
    def run_tests(self,
                  expectations,
                  test_inputs,
                  num_workers,
                  retrying,
                  device_type=None):
        self._expectations = expectations
        self._test_inputs = list(test_inputs)

        self._retrying = retrying

        # FIXME: rename all variables to test_run_results or some such ...
        run_results = TestRunResults(self._expectations, len(test_inputs))
        self._current_run_results = run_results
        self.printer.num_tests = len(test_inputs)
        self.printer.num_started = 0

        if not retrying:
            self.printer.print_expected(
                run_results,
                self._expectations.model().get_tests_with_result_type)

        self.printer.write_update('Sharding tests ...')
        all_shards = self._sharder.shard_tests(
            test_inputs, int(self._options.child_processes),
            self._options.fully_parallel)

        num_workers = min(num_workers, len(all_shards))
        self.printer.print_workers_and_shards(num_workers, len(all_shards))

        if self._options.dry_run:
            return run_results

        self.printer.write_update('Starting {} ...'.format(
            pluralize(num_workers, "worker")))

        devices = None
        if getattr(self._port, 'DEVICE_MANAGER', None):
            devices = dict(
                available_devices=self._port.DEVICE_MANAGER.AVAILABLE_DEVICES,
                initialized_devices=self._port.DEVICE_MANAGER.
                INITIALIZED_DEVICES,
            )

        try:
            LayoutTestRunner.instance = self
            with TaskPool(
                    workers=num_workers,
                    setup=setup_shard,
                    setupkwargs=dict(
                        port=self._port,
                        devices=devices,
                        results_directory=self._results_directory,
                        retrying=self._retrying,
                    ),
                    teardown=teardown_shard,
            ) as pool:
                for shard in all_shards:
                    pool.do(
                        run_shard,
                        shard,
                        callback=lambda value: self.
                        _annotate_results_with_additional_failures(value),
                    )
                pool.wait()

        except TestRunInterruptedException as e:
            _log.warning(e.reason)
            run_results.interrupted = True
        except KeyboardInterrupt:
            self.printer.flush()
            self.printer.writeln('Interrupted, exiting ...')
            run_results.keyboard_interrupted = True
        except Exception as e:
            _log.debug('{}("{}") raised, exiting'.format(
                e.__class__.__name__, str(e)))
            raise
        finally:
            LayoutTestRunner.instance = None

        return run_results