Example #1
0
 def _get_matching_job_list(self, ns, job_list):
     logger.debug("_get_matching_job_list(%r, %r)", ns, job_list)
     qualifier_list = []
     # Add whitelists
     for whitelist_file in ns.whitelist:
         qualifier = self.get_whitelist_from_file(
             whitelist_file.name, whitelist_file)
         if qualifier is not None:
             qualifier_list.append(qualifier)
     # Add all the --include jobs
     for pattern in ns.include_pattern_list:
         try:
             qualifier = RegExpJobQualifier(
                 '^{}$'.format(pattern), inclusive=True)
         except Exception as exc:
             logger.warning(
                 _("Incorrect pattern %r: %s"), pattern, exc)
         else:
             qualifier_list.append(qualifier)
     # Add all the --exclude jobs
     for pattern in ns.exclude_pattern_list:
         try:
             qualifier = RegExpJobQualifier(
                 '^{}$'.format(pattern), inclusive=False)
         except Exception as exc:
             logger.warning(
                 _("Incorrect pattern %r: %s"), pattern, exc)
         else:
             qualifier_list.append(qualifier)
     logger.debug("select_jobs(%r, %r)", job_list, qualifier_list)
     return select_jobs(job_list, qualifier_list)
Example #2
0
 def _get_matching_job_list(self, ns, job_list):
     logger.debug("_get_matching_job_list(%r, %r)", ns, job_list)
     qualifier_list = []
     # Add whitelists
     for whitelist_file in ns.whitelist:
         qualifier = self.get_whitelist_from_file(whitelist_file.name,
                                                  whitelist_file)
         if qualifier is not None:
             qualifier_list.append(qualifier)
     # Add all the --include jobs
     for pattern in ns.include_pattern_list:
         try:
             qualifier = RegExpJobQualifier('^{}$'.format(pattern),
                                            inclusive=True)
         except Exception as exc:
             logger.warning(_("Incorrect pattern %r: %s"), pattern, exc)
         else:
             qualifier_list.append(qualifier)
     # Add all the --exclude jobs
     for pattern in ns.exclude_pattern_list:
         try:
             qualifier = RegExpJobQualifier('^{}$'.format(pattern),
                                            inclusive=False)
         except Exception as exc:
             logger.warning(_("Incorrect pattern %r: %s"), pattern, exc)
         else:
             qualifier_list.append(qualifier)
     logger.debug("select_jobs(%r, %r)", job_list, qualifier_list)
     return select_jobs(job_list, qualifier_list)
Example #3
0
 def _run_jobs_with_session(self, ns, manager, runner):
     # TODO: run all resource jobs concurrently with multiprocessing
     # TODO: make local job discovery nicer, it would be best if
     # desired_jobs could be managed entirely internally by SesionState. In
     # such case the list of jobs to run would be changed during iteration
     # but would be otherwise okay).
     if self._local_only:
         print("[ Loading Jobs Definition ]".center(80, '='))
     else:
         print("[ Running All Jobs ]".center(80, '='))
     again = True
     while again:
         again = False
         for job in manager.state.run_list:
             # Skip jobs that already have result, this is only needed when
             # we run over the list of jobs again, after discovering new
             # jobs via the local job output
             if (manager.state.job_state_map[job.id].result.outcome
                     is not None):
                 continue
             self._run_single_job_with_session(ns, manager, runner, job)
             manager.checkpoint()
             if job.plugin == "local":
                 # After each local job runs rebuild the list of matching
                 # jobs and run everything again
                 desired_job_list = select_jobs(manager.state.job_list,
                                                self.whitelists)
                 if self._local_only:
                     desired_job_list = [
                         job for job in desired_job_list
                         if job.plugin == 'local'
                     ]
                 self._update_desired_job_list(manager, desired_job_list)
                 again = True
                 break
Example #4
0
 def _run_jobs_with_session(self, ns, manager, runner):
     # TODO: run all resource jobs concurrently with multiprocessing
     # TODO: make local job discovery nicer, it would be best if
     # desired_jobs could be managed entirely internally by SesionState. In
     # such case the list of jobs to run would be changed during iteration
     # but would be otherwise okay).
     if self._local_only:
         print("[ Loading Jobs Definition ]".center(80, '='))
     else:
         print("[ Running All Jobs ]".center(80, '='))
     again = True
     while again:
         again = False
         for job in manager.state.run_list:
             # Skip jobs that already have result, this is only needed when
             # we run over the list of jobs again, after discovering new
             # jobs via the local job output
             if (manager.state.job_state_map[job.id].result.outcome
                     is not None):
                 continue
             self._run_single_job_with_session(ns, manager, runner, job)
             manager.checkpoint()
             if job.plugin == "local":
                 # After each local job runs rebuild the list of matching
                 # jobs and run everything again
                 desired_job_list = select_jobs(manager.state.job_list,
                                                self.whitelists)
                 if self._local_only:
                     desired_job_list = [
                         job for job in desired_job_list
                         if job.plugin == 'local']
                 self._update_desired_job_list(manager, desired_job_list)
                 again = True
                 break
Example #5
0
def get_matching_job_list(job_list, qualifier):
    """
    Get a list of jobs that are designated by the specified qualifier.

    This is intended to be used with :class:`CompositeQualifier`
    but works with any :class:`IJobQualifier` subclass.
    """
    return select_jobs(job_list, [qualifier])
Example #6
0
def get_matching_job_list(job_list, qualifier):
    """
    Get a list of jobs that are designated by the specified qualifier.

    This is intended to be used with :class:`CompositeQualifier`
    but works with any :class:`IJobQualifier` subclass.
    """
    return select_jobs(job_list, [qualifier])
Example #7
0
    def _add_test_plan_sheet(self, workbook, plan, job_list):
        """A sheet for a given test plan."""
        # Create a sheet for this test plan
        sheet = workbook.add_worksheet(_('{}').format(plan.tr_name()[0:30]))
        # Define cell formatting
        fmt_header = workbook.add_format({
            'bold': True,
            'font_color': '#ffffff',
            'bg_color': '#77216f',  # Light Aubergine
        })
        fmt_code = workbook.add_format({
            'font_name': 'courier',
        })
        fmt_info = workbook.add_format({
            'font_color': '#dd4814',  # Ubuntu Orange
            'font_name': 'Ubuntu',
            'font_size': 16,
        })
        # Create a section with static information
        sheet.write('A2', _("Test Plan Name"), fmt_info)
        sheet.write('B2', plan.tr_name())
        sheet.write('A3', _("Test Plan ID"), fmt_info)
        sheet.write('B3', plan.id, fmt_code)
        sheet.merge_range('A4:B4', 'TIP: plainbox run -T {}'.format(plan.id),
                          fmt_code)
        # We can add anything we want to all the rows in range(INFO_OFFSET)
        INFO_OFFSET = 5
        # Find what is the effective run list of this test plan
        state = SessionState(job_list)
        state.update_desired_job_list(
            select_jobs(job_list, [plan.get_qualifier()]))

        def max_of(callback):
            """Get the maximum of some function applied to each job."""
            return max((callback(job) for job in state.run_list), default=0)

        COL_ID, COL_SUMMARY = range(2)
        # Add columns: id
        sheet.write(INFO_OFFSET, COL_ID, _("Test Case ID"), fmt_header)
        sheet.write(INFO_OFFSET, COL_SUMMARY, _("Summary"), fmt_header)
        sheet.set_column(
            COL_ID, COL_ID,
            max_of(lambda job: nr_cols_of(job.partial_id)) * WIDTH_FACTOR +
            WIDTH_PADDING)
        sheet.set_column(
            COL_SUMMARY, COL_SUMMARY,
            max_of(lambda job: nr_cols_of(job.tr_summary())) * WIDTH_FACTOR +
            WIDTH_PADDING)
        # Add the information about each job as a separate row
        for index, job in enumerate(state.run_list, INFO_OFFSET + 1):
            sheet.set_row(index, HEIGHT_FACTOR + HEIGHT_PADDING)
            sheet.write(index, COL_ID, job.partial_id, fmt_code)
            sheet.write(index, COL_SUMMARY, job.tr_summary())
        # Make sure the sheet is read only
        sheet.protect()
Example #8
0
 def test_select_jobs__inclusion(self):
     """
     verify that select_jobs() honors qualifier ordering
     """
     job_a = JobDefinition({'id': 'a'})
     job_b = JobDefinition({'id': 'b'})
     job_c = JobDefinition({'id': 'c'})
     qual_a = JobIdQualifier("a", self.origin)
     qual_c = JobIdQualifier("c", self.origin)
     for job_list in permutations([job_a, job_b, job_c], 3):
         # Regardless of how the list of job is ordered the result
         # should be the same, depending on the qualifier list
         self.assertEqual(select_jobs(job_list, [qual_a, qual_c]),
                          [job_a, job_c])
Example #9
0
 def test_select_jobs__inclusion(self):
     """
     verify that select_jobs() honors qualifier ordering
     """
     job_a = JobDefinition({'id': 'a'})
     job_b = JobDefinition({'id': 'b'})
     job_c = JobDefinition({'id': 'c'})
     qual_a = JobIdQualifier("a")
     qual_c = JobIdQualifier("c")
     for job_list in permutations([job_a, job_b, job_c], 3):
         # Regardless of how the list of job is ordered the result
         # should be the same, depending on the qualifier list
         self.assertEqual(
             select_jobs(job_list, [qual_a, qual_c]),
             [job_a, job_c])
Example #10
0
 def interactively_pick_jobs_to_run(self):
     print(self.C.header(_("Selecting Jobs For Execution")))
     self._update_desired_job_list(select_jobs(
         self.manager.state.job_list, self._qualifier_list))
     if self.launcher.skip_test_selection or not self.is_interactive:
         return
     tree = SelectableJobTreeNode.create_tree(
         self.manager.state, self.manager.state.run_list)
     title = _('Choose tests to run on your system:')
     self.display.run(ScrollableTreeNode(tree, title))
     # NOTE: tree.selection is correct but ordered badly.  To retain
     # the original ordering we should just treat it as a mask and
     # use it to filter jobs from desired_job_list.
     wanted_set = frozenset(tree.selection + tree.resource_jobs)
     job_list = [job for job in self.manager.state.run_list
                 if job in wanted_set]
     self._update_desired_job_list(job_list)
 def _get_matching_job_list(self, ns, job_list):
     logger.debug("_get_matching_job_list(%r, %r)", ns, job_list)
     qualifier_list = []
     # Add the test plan
     if ns.test_plan is not None:
         # Uh, dodgy, recreate a list of providers from the list of jobs we
         # know about here. This code needs to be re-factored to use the
         # upcoming provider store class.
         for provider in {job.provider for job in job_list}:
             for unit in provider.id_map[ns.test_plan]:
                 if unit.Meta.name == 'test plan':
                     qualifier_list.append(unit.get_qualifier())
                     break
         else:
             logger.debug(_("There is no test plan: %s"), ns.test_plan)
     # Add whitelists
     for whitelist_file in ns.whitelist:
         qualifier = self.get_whitelist_from_file(whitelist_file.name,
                                                  whitelist_file)
         if qualifier is not None:
             qualifier_list.append(qualifier)
     # Add all the --include jobs
     for pattern in ns.include_pattern_list:
         origin = Origin(CommandLineTextSource('-i', pattern), None, None)
         try:
             qualifier = RegExpJobQualifier('^{}$'.format(pattern),
                                            origin,
                                            inclusive=True)
         except Exception as exc:
             logger.warning(_("Incorrect pattern %r: %s"), pattern, exc)
         else:
             qualifier_list.append(qualifier)
     # Add all the --exclude jobs
     for pattern in ns.exclude_pattern_list:
         origin = Origin(CommandLineTextSource('-x', pattern), None, None)
         try:
             qualifier = RegExpJobQualifier('^{}$'.format(pattern),
                                            origin,
                                            inclusive=False)
         except Exception as exc:
             logger.warning(_("Incorrect pattern %r: %s"), pattern, exc)
         else:
             qualifier_list.append(qualifier)
     logger.debug("select_jobs(%r, %r)", job_list, qualifier_list)
     return select_jobs(job_list, qualifier_list)
Example #12
0
 def select_local_jobs(self):
     print(self.C.header(_("Selecting Job Generators")))
     # Create a qualifier list that will pick all local jobs out of the
     # subset of jobs also enumerated by the whitelists we've already
     # picked.
     #
     # Since each whitelist is a qualifier that selects jobs enumerated
     # within, we only need to and an exclusive qualifier that deselects
     # non-local jobs and we're done.
     qualifier_list = []
     qualifier_list.extend(self._qualifier_list)
     origin = Origin.get_caller_origin()
     qualifier_list.append(FieldQualifier(
         'plugin', OperatorMatcher(operator.ne, 'local'), origin,
         inclusive=False))
     local_job_list = select_jobs(
         self.manager.state.job_list, qualifier_list)
     self._update_desired_job_list(local_job_list)
Example #13
0
 def test_select_jobs__exclusion(self):
     """
     verify that select_jobs() honors qualifier ordering
     """
     job_a = JobDefinition({'id': 'a'})
     job_b = JobDefinition({'id': 'b'})
     job_c = JobDefinition({'id': 'c'})
     qual_all = CompositeQualifier([
         JobIdQualifier("a"),
         JobIdQualifier("b"),
         JobIdQualifier("c"),
     ])
     qual_not_c = JobIdQualifier("c", inclusive=False)
     for job_list in permutations([job_a, job_b, job_c], 3):
         # Regardless of how the list of job is ordered the result
         # should be the same, depending on the qualifier list
         self.assertEqual(select_jobs(job_list, [qual_all, qual_not_c]),
                          [job_a, job_b])
Example #14
0
    def run(self):
        ns = self.ns
        job_list = self.get_job_list(ns)
        previous_session_file = SessionStorageRepository().get_last_storage()
        resume_in_progress = False
        if previous_session_file:
            if self.is_interactive:
                if self.ask_for_resume():
                    resume_in_progress = True
                    manager = SessionManager.load_session(
                        job_list, previous_session_file)
                    self._maybe_skip_last_job_after_resume(manager)
            else:
                resume_in_progress = True
                manager = SessionManager.load_session(job_list,
                                                      previous_session_file)
        if not resume_in_progress:
            # Create a session that handles most of the stuff needed to run
            # jobs
            try:
                manager = SessionManager.create_with_job_list(job_list,
                                                              legacy_mode=True)
            except DependencyDuplicateError as exc:
                # Handle possible DependencyDuplicateError that can happen if
                # someone is using plainbox for job development.
                print("The job database you are currently using is broken")
                print("At least two jobs contend for the name {0}".format(
                    exc.job.id))
                print("First job defined in: {0}".format(exc.job.origin))
                print("Second job defined in: {0}".format(
                    exc.duplicate_job.origin))
                raise SystemExit(exc)
            manager.state.metadata.title = " ".join(sys.argv)
            if self.is_interactive:
                if self.display is None:
                    self.display = get_display()
                if self.settings['welcome_text']:
                    self.display.run(ShowWelcome(
                        self.settings['welcome_text']))
                if not self.whitelists:
                    whitelists = []
                    for p in self.provider_list:
                        if p.name in self.settings['default_providers']:
                            whitelists.extend(
                                [w.name for w in p.get_builtin_whitelists()])
                    selection = self.display.run(
                        ShowMenu("Suite selection", whitelists))
                    if not selection:
                        raise SystemExit('No whitelists selected, aborting...')
                    for s in selection:
                        self.whitelists.append(
                            get_whitelist_by_name(self.provider_list,
                                                  whitelists[s]))
            else:
                self.whitelists.append(
                    get_whitelist_by_name(self.provider_list,
                                          self.settings['default_whitelist']))
        manager.checkpoint()

        if self.is_interactive and not resume_in_progress:
            # Pre-run all local jobs
            desired_job_list = select_jobs(manager.state.job_list, [
                CompositeQualifier(self.whitelists +
                                   [NonLocalJobQualifier(inclusive=False)])
            ])
            self._update_desired_job_list(manager, desired_job_list)
            # Ask the password before anything else in order to run local jobs
            # requiring privileges
            if self._auth_warmup_needed(manager):
                print("[ Authentication ]".center(80, '='))
                return_code = authenticate_warmup()
                if return_code:
                    raise SystemExit(return_code)
            self._local_only = True
            self._run_jobs(ns, manager)
            self._local_only = False

        if not resume_in_progress:
            # Run the rest of the desired jobs
            desired_job_list = select_jobs(manager.state.job_list,
                                           self.whitelists)
            self._update_desired_job_list(manager, desired_job_list)
            if self.is_interactive:
                # Ask the password before anything else in order to run jobs
                # requiring privileges
                if self._auth_warmup_needed(manager):
                    print("[ Authentication ]".center(80, '='))
                    return_code = authenticate_warmup()
                    if return_code:
                        raise SystemExit(return_code)
                tree = SelectableJobTreeNode.create_tree(
                    manager.state.run_list, legacy_mode=True)
                title = 'Choose tests to run on your system:'
                if self.display is None:
                    self.display = get_display()
                self.display.run(ScrollableTreeNode(tree, title))
                self._update_desired_job_list(manager, tree.selection)
                estimated_duration_auto, estimated_duration_manual = \
                    manager.state.get_estimated_duration()
                if estimated_duration_auto:
                    print(
                        "Estimated duration is {:.2f} "
                        "for automated jobs.".format(estimated_duration_auto))
                else:
                    print("Estimated duration cannot be "
                          "determined for automated jobs.")
                if estimated_duration_manual:
                    print("Estimated duration is {:.2f} "
                          "for manual jobs.".format(estimated_duration_manual))
                else:
                    print("Estimated duration cannot be "
                          "determined for manual jobs.")
        self._run_jobs(ns, manager)
        manager.destroy()

        # FIXME: sensible return value
        return 0
Example #15
0
    def run(self):
        ns = self.ns
        job_list = self.get_job_list(ns)
        previous_session_file = SessionStorageRepository().get_last_storage()
        resume_in_progress = False
        if previous_session_file:
            if self.is_interactive:
                if self.ask_for_resume():
                    resume_in_progress = True
                    manager = SessionManager.load_session(
                        job_list, previous_session_file)
                    self._maybe_skip_last_job_after_resume(manager)
            else:
                resume_in_progress = True
                manager = SessionManager.load_session(
                    job_list, previous_session_file)
        if not resume_in_progress:
            # Create a session that handles most of the stuff needed to run
            # jobs
            try:
                manager = SessionManager.create_with_job_list(
                    job_list, legacy_mode=True)
            except DependencyDuplicateError as exc:
                # Handle possible DependencyDuplicateError that can happen if
                # someone is using plainbox for job development.
                print("The job database you are currently using is broken")
                print("At least two jobs contend for the name {0}".format(
                    exc.job.id))
                print("First job defined in: {0}".format(exc.job.origin))
                print("Second job defined in: {0}".format(
                    exc.duplicate_job.origin))
                raise SystemExit(exc)
            manager.state.metadata.title = " ".join(sys.argv)
            if self.is_interactive:
                if self.display is None:
                    self.display = get_display()
                if self.settings['welcome_text']:
                    self.display.run(
                        ShowWelcome(self.settings['welcome_text']))
                if not self.whitelists:
                    whitelists = []
                    for p in self.provider_list:
                        if p.name in self.settings['default_providers']:
                            whitelists.extend(
                                [w.name for w in p.get_builtin_whitelists()])
                    selection = self.display.run(ShowMenu("Suite selection",
                                                          whitelists))
                    if not selection:
                        raise SystemExit('No whitelists selected, aborting...')
                    for s in selection:
                        self.whitelists.append(
                            get_whitelist_by_name(self.provider_list,
                                                  whitelists[s]))
            else:
                self.whitelists.append(
                    get_whitelist_by_name(
                        self.provider_list,
                        self.settings['default_whitelist']))
        manager.checkpoint()

        if self.is_interactive and not resume_in_progress:
            # Pre-run all local jobs
            desired_job_list = select_jobs(
                manager.state.job_list,
                [CompositeQualifier(
                    self.whitelists +
                    [NonLocalJobQualifier(inclusive=False)]
                )])
            self._update_desired_job_list(manager, desired_job_list)
            # Ask the password before anything else in order to run local jobs
            # requiring privileges
            if self._auth_warmup_needed(manager):
                print("[ Authentication ]".center(80, '='))
                return_code = authenticate_warmup()
                if return_code:
                    raise SystemExit(return_code)
            self._local_only = True
            self._run_jobs(ns, manager)
            self._local_only = False

        if not resume_in_progress:
            # Run the rest of the desired jobs
            desired_job_list = select_jobs(manager.state.job_list,
                                           self.whitelists)
            self._update_desired_job_list(manager, desired_job_list)
            if self.is_interactive:
                # Ask the password before anything else in order to run jobs
                # requiring privileges
                if self._auth_warmup_needed(manager):
                    print("[ Authentication ]".center(80, '='))
                    return_code = authenticate_warmup()
                    if return_code:
                        raise SystemExit(return_code)
                tree = SelectableJobTreeNode.create_tree(
                    manager.state.run_list,
                    legacy_mode=True)
                title = 'Choose tests to run on your system:'
                if self.display is None:
                    self.display = get_display()
                self.display.run(ScrollableTreeNode(tree, title))
                self._update_desired_job_list(manager, tree.selection)
                estimated_duration_auto, estimated_duration_manual = \
                    manager.state.get_estimated_duration()
                if estimated_duration_auto:
                    print(
                        "Estimated duration is {:.2f} "
                        "for automated jobs.".format(estimated_duration_auto))
                else:
                    print(
                        "Estimated duration cannot be "
                        "determined for automated jobs.")
                if estimated_duration_manual:
                    print(
                        "Estimated duration is {:.2f} "
                        "for manual jobs.".format(estimated_duration_manual))
                else:
                    print(
                        "Estimated duration cannot be "
                        "determined for manual jobs.")
        self._run_jobs(ns, manager)
        manager.destroy()

        # FIXME: sensible return value
        return 0