Пример #1
0
def test_execute_jobs():
    context = Mock()
    context.args = Mock()
    context.args.event_handlers = None
    task_context = Mock()
    task_context.pkg = Mock()
    task_context.pkg.name = 'name'
    jobs = {
        'one':
        Job(identifier='id',
            dependencies=set(),
            task=None,
            task_context=task_context)
    }

    event_reactor = Mock()
    event_reactor.__enter__ = lambda self: self
    event_reactor.__exit__ = lambda self, *args: None
    with patch('colcon_core.executor.create_event_reactor',
               return_value=event_reactor):
        with EntryPointContext(extension1=Extension1, extension2=Extension2):
            # no extension selected
            with pytest.raises(AssertionError):
                execute_jobs(context, jobs)

            # execute method not implemented and sending skipped job event
            context.args.executor = 'extension2'
            with patch('colcon_core.executor.logger.error') as error:
                rc = execute_jobs(context, jobs)
            assert rc == 1
            assert error.call_count == 1
            assert len(error.call_args[0]) == 1
            assert error.call_args[0][0].startswith(
                "Exception in executor extension 'extension2': \n")
            assert event_reactor.get_queue().put.call_count == 2
            assert isinstance(
                event_reactor.get_queue().put.call_args_list[0][0][0][0],
                JobQueued)
            assert isinstance(
                event_reactor.get_queue().put.call_args_list[1][0][0][0],
                JobSkipped)

            # successful execution
            event_reactor.get_queue().put.reset_mock()
            jobs['one'].returncode = 0
            extensions = get_executor_extensions()
            extensions[110]['extension2'].execute = \
                lambda args, jobs, on_error: 0
            callback = Mock()
            rc = execute_jobs(context,
                              jobs,
                              on_error=OnError.interrupt,
                              pre_execution_callback=callback)
            assert rc == 0
            assert event_reactor.get_queue().put.call_count == 1
            assert isinstance(event_reactor.get_queue().put.call_args[0][0][0],
                              JobQueued)
            assert callback.call_count == 1
Пример #2
0
    def _get_jobs(self, args, installers, decorators):
        jobs = OrderedDict()
        workspace_package_names = [
            decorator.descriptor.name for decorator in decorators
        ]
        logger.info(
            'Including {} in bundle...'.format(workspace_package_names))
        for decorator in decorators:
            if not decorator.selected:
                continue

            pkg = decorator.descriptor
            extension = get_task_extension('colcon_bundle.task.bundle',
                                           pkg.type)
            if not extension:
                logger.warn('No task extension to bundle a {pkg.type} package'.
                            format_map(locals()))
                continue

            recursive_dependencies = OrderedDict()
            for dep_name in decorator.recursive_dependencies:
                dep_path = args.install_base
                if not args.merge_install:
                    dep_path = os.path.join(dep_path, dep_name)
                recursive_dependencies[dep_name] = dep_path

            dest = self.task_argument_destinations.values()
            package_args = BundlePackageArguments(pkg,
                                                  installers,
                                                  args,
                                                  additional_destinations=dest)
            ordered_package_args = ', '.join([
                ('%s: %s' % (repr(k), repr(package_args.__dict__[k])))
                for k in sorted(package_args.__dict__.keys())
            ])
            logger.debug(
                'Bundling package {pkg.name} with the following arguments: '
                '{{{ordered_package_args}}}'.format_map(locals()))
            task_context = TaskContext(pkg=pkg,
                                       args=package_args,
                                       dependencies=recursive_dependencies)

            task_context.installers = installers

            job = Job(identifier=pkg.name,
                      dependencies=set(recursive_dependencies.keys()),
                      task=extension,
                      task_context=task_context)

            jobs[pkg.name] = job
        return jobs
Пример #3
0
    def _get_jobs(self, args, decorators, install_base):
        jobs = OrderedDict()
        unselected_packages = set()
        for decorator in decorators:
            pkg = decorator.descriptor

            if not decorator.selected:
                unselected_packages.add(pkg)
                continue

            extension = get_task_extension('colcon_core.task.build', pkg.type)
            if not extension:
                logger.warning(
                    "No task extension to 'build' a '{pkg.type}' package".
                    format_map(locals()))
                continue

            recursive_dependencies = OrderedDict()
            for dep_name in decorator.recursive_dependencies:
                dep_path = install_base
                if not args.merge_install:
                    dep_path = os.path.join(dep_path, dep_name)
                recursive_dependencies[dep_name] = dep_path

            package_args = BuildPackageArguments(
                pkg,
                args,
                additional_destinations=self.task_argument_destinations.values(
                ))
            ordered_package_args = ', '.join([
                ('%s: %s' % (repr(k), repr(package_args.__dict__[k])))
                for k in sorted(package_args.__dict__.keys())
            ])
            logger.debug(
                "Building package '{pkg.name}' with the following arguments: "
                '{{{ordered_package_args}}}'.format_map(locals()))
            task_context = TaskContext(pkg=pkg,
                                       args=package_args,
                                       dependencies=recursive_dependencies)

            job = Job(identifier=pkg.name,
                      dependencies=set(recursive_dependencies.keys()),
                      task=extension,
                      task_context=task_context)

            jobs[pkg.name] = job
        return jobs, unselected_packages
Пример #4
0
def test_job():
    task = Task()
    task_context = Mock()
    task_context.dependencies = Mock()
    task_context.pkg = Mock()
    task_context.pkg.name = 'name'
    job = Job(identifier='id',
              dependencies=set(),
              task=task,
              task_context=task_context)
    assert str(job) == 'id'

    events = []
    event_queue = Mock()
    event_queue.put = lambda event: events.append(event)
    job.set_event_queue(event_queue)
    assert len(events) == 1
    assert isinstance(events[-1][0], JobQueued)
    assert events[-1][0].identifier == 'name'
    assert events[-1][0].dependencies == task_context.dependencies
    assert events[-1][1] == job

    # successful task
    rc = run_until_complete(job())
    assert rc == 0
    assert len(events) == 3
    assert isinstance(events[-2][0], JobStarted)
    assert events[-2][0].identifier == 'name'
    assert events[-2][1] == job
    assert isinstance(events[-1][0], JobEnded)
    assert events[-1][0].identifier == 'name'
    assert events[-1][0].rc == 0
    assert events[-1][1] == job

    # canceled task
    job.returncode = None
    task.return_value = CancelledError()
    rc = run_until_complete(job())
    assert rc is SIGINT_RESULT
    assert len(events) == 5
    assert isinstance(events[-2][0], JobStarted)
    assert events[-2][0].identifier == 'name'
    assert events[-2][1] == job
    assert isinstance(events[-1][0], JobEnded)
    assert events[-1][0].identifier == 'name'
    assert events[-1][0].rc is SIGINT_RESULT
    assert events[-1][1] == job

    # task raising exception
    job.returncode = None
    task.return_value = RuntimeError('custom exception')
    with pytest.raises(RuntimeError):
        run_until_complete(job())
    assert len(events) == 8
    assert isinstance(events[-3][0], JobStarted)
    assert events[-3][0].identifier == 'name'
    assert events[-3][1] == job
    assert isinstance(events[-2][0], StderrLine)
    assert events[-2][0].line.endswith(b'\nRuntimeError: custom exception\n')
    assert events[-2][1] == job
    assert isinstance(events[-1][0], JobEnded)
    assert events[-1][0].identifier == 'name'
    assert events[-1][0].rc == 1
    assert events[-1][1] == job

    # override task return code
    job.returncode = 2
    task.return_value = 0
    rc = run_until_complete(job())
    assert rc == 2
    assert len(events) == 10
    assert isinstance(events[-2][0], JobStarted)
    assert events[-2][0].identifier == 'name'
    assert events[-2][1] == job
    assert isinstance(events[-1][0], JobEnded)
    assert events[-1][0].identifier == 'name'
    assert events[-1][0].rc == 2
    assert events[-1][1] == job
Пример #5
0
    def main(self, *, context):
        check_and_mark_build_tool(context.args.build_base)

        lcov_base_abspath = Path(os.path.abspath(context.args.lcov_base))
        lcov_base_abspath.mkdir(exist_ok=True)

        gcc_pkgs = self._get_gcc_packages(context,
                                          additional_argument_names=['*'])

        jobs = OrderedDict()
        for pkg in gcc_pkgs:
            task_context = TaskContext(pkg=pkg,
                                       args=context.args,
                                       dependencies=OrderedDict())

            if context.args.zero_counters:
                extension = LcovZeroCountersTask()
            else:
                extension = LcovCaptureTask()
            extension.PACKAGE_TYPE = pkg.type

            job = Job(
                identifier=pkg.name,
                dependencies=set(),  # Can be generated in any order
                task=extension,
                task_context=task_context)
            jobs[pkg.name] = job

        rc = execute_jobs(context, jobs)

        if context.args.initial or context.args.zero_counters:
            return rc

        print("\nCalculating total coverage... ")
        total_output_file = str(lcov_base_abspath / 'total_coverage.info')
        if rc == 0:
            output_files = []
            for pkg in gcc_pkgs:
                output_file = os.path.abspath(
                    os.path.join(context.args.build_base, pkg.name,
                                 'coverage.info'))
                if os.stat(output_file).st_size != 0:
                    output_files.append(output_file)
            if len(output_files) == 0:
                logger.error(
                    'No valid coverage.info files found. Did you run tests?')
                return 1
            rc = lcov_add(context,
                          output_files,
                          total_output_file,
                          verbose=context.args.verbose)

        if rc != 0:
            return rc

        if context.args.filter:
            print("\nApplying filters... ")
            rc = lcov_remove(context, total_output_file)

        if rc != 0:
            return rc

        print("\nGenerating HTML: ", end='')
        # Check that genhtml exists
        if GENHTML_EXECUTABLE is None:
            raise RuntimeError("Could not find 'genhtml' executable")

        # Generate html
        cmd = [
            GENHTML_EXECUTABLE, '--quiet', '--output-directory',
            str(lcov_base_abspath), total_output_file, '--config-file',
            str(context.args.lcov_config_file)
        ]
        if CPP_FILT_EXECUTABLE is not None:
            cmd.extend(['--demangle-cpp'])
        # Strip paths to packages
        for path in context.args.base_paths:
            cmd.extend(['--prefix', str(os.path.abspath(path))])
        rc = subprocess.run(cmd).returncode
        print("Done")
        return rc
Пример #6
0
    def main(self, *, context):  # noqa: D102
        build_base = context.args.build_base
        check_and_mark_build_tool(build_base)

        # Check once if the 'coverage' command is available,
        # otherwise we will need to fall back on using the Python module
        has_command = has_coverage_command()
        logger.info("'coverage' command available: {has_command}".format_map(
            locals()))

        # Get packages
        coveragepy_pkgs = self._get_coveragepy_packages(context)
        if not coveragepy_pkgs:
            logger.warning('No packages selected or found')
            return 0

        # Combine each package's .coverage files
        jobs = OrderedDict()
        for pkg in coveragepy_pkgs:
            task_context = TaskContext(
                pkg=pkg,
                args=context.args,
                dependencies=OrderedDict(),
            )
            task = CoveragePyTask(has_command)
            job = Job(
                identifier=pkg.name,
                dependencies=set(),
                task=task,
                task_context=task_context,
            )
            jobs[pkg.name] = job
        rc = execute_jobs(context, jobs)

        # Get all packages' .coverage files
        coverage_files = [
            str(
                Path(
                    CoveragePyTask.get_package_combine_dir(
                        build_base, pkg.name)) / '.coverage')
            for pkg in coveragepy_pkgs
        ]
        # Filter out non-existing files in case processing failed for some packages
        coverage_files = list(filter(os.path.exists, coverage_files))
        if 0 == len(coverage_files):
            logger.warning('No coverage files found')
            return 0
        logger.info('Coverage files: {coverage_files}'.format_map(locals()))

        # Combine .coverage files
        coveragepy_base_dir = str(os.path.abspath(
            context.args.coveragepy_base))
        Path(coveragepy_base_dir).mkdir(exist_ok=True)
        rc, stdout, _ = coverage_combine(coverage_files, coveragepy_base_dir,
                                         has_command)
        if 0 == rc and context.args.verbose:
            # Print report
            rc, stdout, _ = coverage_report(
                coveragepy_base_dir,
                context.args.coverage_report_args,
                has_command,
            )
            if 0 == rc:
                print('\n' + stdout)
        # Generate HTML report
        rc, stdout, _ = coverage_html(
            coveragepy_base_dir,
            context.args.coverage_html_args,
            has_command,
        )
        return rc