コード例 #1
0
ファイル: test_session.py プロジェクト: nkaul/ocp-checkbox
 def test_resume_session(self):
     # All of the tests below are using one session. The session has four
     # jobs, Job A depends on a resource provided by job R which has no
     # dependencies at all. Both Job X and Y depend on job A.
     #
     # A -(resource dependency)-> R
     #
     # X -(direct dependency) -> A
     #
     # Y -(direct dependency) -> A
     self.job_A = make_job("A", requires="R.attr == 'value'")
     self.job_A_expr = self.job_A.get_resource_program().expression_list[0]
     self.job_R = make_job("R", plugin="resource")
     self.job_X = make_job("X", depends='A')
     self.job_Y = make_job("Y", depends='A')
     self.job_list = [self.job_A, self.job_R, self.job_X, self.job_Y]
     # Create a new session (session_dir is empty)
     self.session = SessionState(self.job_list)
     result_R = JobResult({
         'job':
         self.job_R,
         'io_log':
         make_io_log(((0, 'stdout', b"attr: value\n"), ), self._sandbox)
     })
     result_A = JobResult({
         'job': self.job_A,
         'outcome': JobResult.OUTCOME_PASS
     })
     result_X = JobResult({
         'job': self.job_X,
         'outcome': JobResult.OUTCOME_PASS
     })
     # Job Y can't start as it requires job A
     self.assertFalse(self.job_state('Y').can_start())
     self.session.update_desired_job_list([self.job_X, self.job_Y])
     self.session.open()
     self.session.update_job_result(self.job_R, result_R)
     self.session.update_job_result(self.job_A, result_A)
     self.session.update_job_result(self.job_X, result_X)
     self.session.persistent_save()
     self.session.close()
     # Create a new session (session_dir should contain session data)
     self.session = SessionState(self.job_list)
     self.session.open()
     # Resume the previous session
     self.session.resume()
     # This time job Y can start
     self.assertTrue(self.job_state('Y').can_start())
     self.session.close()
コード例 #2
0
 def test_init_with_identical_jobs(self):
     A = make_job("A")
     second_A = make_job("A")
     third_A = make_job("A")
     session = SessionState([A, second_A, third_A])
     # But we don't really store both, just the first one
     self.assertEqual(session.job_list, [A])
コード例 #3
0
 def test_crash_on_missing_job(self):
     """ http://pad.lv/1334296 """
     A = make_job("A")
     state = SessionState([])
     problems = state.update_desired_job_list([A])
     self.assertEqual(problems, [DependencyUnknownError(A)])
     self.assertEqual(state.desired_job_list, [])
コード例 #4
0
 def make_realistic_test_session(self, session_dir):
     # Create a more realistic session with two jobs but with richer set
     # of data in the actual jobs and results.
     job_a = JobDefinition({
         'plugin': 'shell',
         'name': 'job_a',
         'summary': 'This is job A',
         'command': 'echo testing && true',
         'requires': 'job_b.ready == "yes"'
     })
     job_b = JobDefinition({
         'plugin': 'resource',
         'name': 'job_b',
         'summary': 'This is job B',
         'command': 'echo ready: yes'
     })
     session = SessionState([job_a, job_b])
     session.update_desired_job_list([job_a, job_b])
     result_a = MemoryJobResult({
         'outcome': IJobResult.OUTCOME_PASS,
         'return_code': 0,
         'io_log': [(0, 'stdout', b'testing\n')],
     })
     result_b = MemoryJobResult({
         'outcome': IJobResult.OUTCOME_PASS,
         'return_code': 0,
         'comments': 'foo',
         'io_log': [(0, 'stdout', b'ready: yes\n')],
     })
     session.update_job_result(job_a, result_a)
     session.update_job_result(job_b, result_b)
     return session
コード例 #5
0
 def test_mandatory_jobs_are_first_in_run_list(self):
     A = make_job('A')
     B = make_job('B')
     session = SessionState([A, B])
     session.update_mandatory_job_list([B])
     session.update_desired_job_list([A])
     self.assertEqual(session.run_list, [B, A])
コード例 #6
0
 def test_also_after_suspend_manual_flag(self):
     # Define a job
     job = make_job("A", summary="foo", flags='also-after-suspend-manual')
     # Define an empty session
     session = SessionState([])
     # Add the job to the session
     session.add_unit(job)
     # Both jobs got added to job list
     self.assertEqual(len(session.job_list), 2)
     self.assertIn(job, session.job_list)
     self.assertEqual(session.job_list[1].id, 'after-suspend-manual-A')
     self.assertEqual(session.job_list[1].summary, 'foo after suspend (S3)')
     self.assertEqual(
         session.job_list[1].depends,
         'A com.canonical.certification::suspend/suspend_advanced')
     sibling = session.job_list[1]
     self.assertNotIn('also-after-suspend-manual', sibling.get_flag_set())
     # Both jobs got added to job state map
     self.assertIs(session.job_state_map[job.id].job, job)
     self.assertIs(session.job_state_map[sibling.id].job, sibling)
     # Both jobs are not added to the desired job list
     self.assertNotIn(job, session.desired_job_list)
     self.assertNotIn(sibling, session.desired_job_list)
     # Both jobs are not in the run list
     self.assertNotIn(job, session.run_list)
     self.assertNotIn(sibling, session.run_list)
     # Both jobs are not selected to run
     self.assertEqual(
         session.job_state_map[job.id].readiness_inhibitor_list,
         [UndesiredJobReadinessInhibitor])
     self.assertEqual(
         session.job_state_map[sibling.id].readiness_inhibitor_list,
         [UndesiredJobReadinessInhibitor])
コード例 #7
0
 def test_add_sibling_unit(self):
     # Define a job
     job = make_job("A", summary="foo", siblings='[{"id": "B"}]')
     # Define an empty session
     session = SessionState([])
     # Add the job to the session
     session.add_unit(job)
     # Both jobs got added to job list
     self.assertEqual(len(session.job_list), 2)
     self.assertIn(job, session.job_list)
     self.assertEqual(session.job_list[1].id, 'B')
     self.assertEqual(session.job_list[1].summary, 'foo')
     sibling = session.job_list[1]
     # Both jobs got added to job state map
     self.assertIs(session.job_state_map[job.id].job, job)
     self.assertIs(session.job_state_map[sibling.id].job, sibling)
     # Both jobs are not added to the desired job list
     self.assertNotIn(job, session.desired_job_list)
     self.assertNotIn(sibling, session.desired_job_list)
     # Both jobs are not in the run list
     self.assertNotIn(job, session.run_list)
     self.assertNotIn(sibling, session.run_list)
     # Both jobs are not selected to run
     self.assertEqual(
         session.job_state_map[job.id].readiness_inhibitor_list,
         [UndesiredJobReadinessInhibitor])
     self.assertEqual(
         session.job_state_map[sibling.id].readiness_inhibitor_list,
         [UndesiredJobReadinessInhibitor])
コード例 #8
0
 def test_category_map(self):
     """
     Ensure that passing OPTION_WITH_CATEGORY_MAP causes a category id ->
     tr_name mapping to show up.
     """
     exporter = self.TestSessionStateExporter([
         SessionStateExporterBase.OPTION_WITH_CATEGORY_MAP
     ])
     # Create three untis, two categories (foo, bar) and two jobs (froz,
     # bot) so that froz.category_id == foo
     cat_foo = CategoryUnit({
         'id': 'foo',
         'name': 'The foo category',
     })
     cat_bar = CategoryUnit({
         'id': 'bar',
         'name': 'The bar category',
     })
     job_froz = JobDefinition({
         'plugin': 'shell',
         'id': 'froz',
         'category_id': 'foo'
     })
     # Create and export a session with the three units
     state = SessionState([cat_foo, cat_bar, job_froz])
     session_manager = mock.Mock(spec_set=SessionManager, state=state)
     data = exporter.get_session_data_subset(session_manager)
     # Ensure that only the foo category was used, and the bar category was
     # discarded as nothing was referencing it
     self.assertEqual(data['category_map'], {
         'foo': 'The foo category',
     })
コード例 #9
0
ファイル: sru.py プロジェクト: Roadmaster/checkbox
 def run(self):
     # Compute the run list, this can give us notification about problems in
     # the selected jobs. Currently we just display each problem
     # Create a session that handles most of the stuff needed to run jobs
     try:
         self.session = SessionState(self.job_list)
     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)
     with self.session.open():
         self._set_job_selection()
         self.runner = JobRunner(self.session.session_dir,
                                 self.provider_list,
                                 self.session.jobs_io_log_dir,
                                 command_io_delegate=self,
                                 dry_run=self.ns.dry_run)
         self._run_all_jobs()
         if self.config.fallback_file is not Unset:
             self._save_results()
         self._submit_results()
     # FIXME: sensible return value
     return 0
コード例 #10
0
ファイル: analyze.py プロジェクト: nkaul/ocp-checkbox
 def __init__(self, provider, ns):
     super(AnalyzeInvocation, self).__init__(provider)
     self.ns = ns
     self.job_list = self.get_job_list(ns)
     self.desired_job_list = self._get_matching_job_list(ns, self.job_list)
     self.session = SessionState(self.job_list)
     self.problem_list = self.session.update_desired_job_list(
         self.desired_job_list)
コード例 #11
0
ファイル: analyze.py プロジェクト: Roadmaster/checkbox
 def __init__(self, provider_list, config, ns):
     super().__init__(provider_list, config)
     self.ns = ns
     self.job_list = self.get_job_list(ns)
     self.desired_job_list = self._get_matching_job_list(ns, self.job_list)
     self.session = SessionState(self.job_list)
     self.problem_list = self.session.update_desired_job_list(
         self.desired_job_list)
コード例 #12
0
 def test_init_with_identical_jobs(self):
     A = make_job("A")
     second_A = make_job("A")
     third_A = make_job("A")
     # Identical jobs are folded for backwards compatibility with some local
     # jobs that re-added existing jobs
     session = SessionState([A, second_A, third_A])
     # But we don't really store both, just the first one
     self.assertEqual(session.job_list, [A])
コード例 #13
0
 def __init__(self, provider_loader, config_loader, ns):
     super().__init__(provider_loader, config_loader)
     self.ns = ns
     self.unit_list = list(
         itertools.chain(*[p.unit_list for p in self.provider_list]))
     self.session = SessionState(self.unit_list)
     self.desired_job_list = self._get_matching_job_list(
         ns, self.session.job_list)
     self.problem_list = self.session.update_desired_job_list(
         self.desired_job_list)
コード例 #14
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()
コード例 #15
0
 def test_init_with_colliding_jobs(self):
     # This is similar to the test above but the jobs actually differ In
     # this case the _second_ job is rejected but it really signifies a
     # deeper problem that should only occur during development of jobs
     A = make_job("A")
     different_A = make_job("A", plugin="resource")
     with self.assertRaises(DependencyDuplicateError) as call:
         SessionState([A, different_A])
         self.assertIs(call.exception.job, A)
         self.assertIs(call.exception.duplicate_job, different_A)
         self.assertIs(call.exception.affected_job, different_A)
コード例 #16
0
 def test_get_estimated_duration_manual_unknown(self):
     four_seconds = make_job("four_seconds",
                             plugin="shell",
                             command="fibble",
                             estimated_duration=4.0)
     no_estimated_duration = make_job("no_estimated_duration",
                                      plugin="user-verify",
                                      command="bibble")
     session = SessionState([four_seconds, no_estimated_duration])
     session.update_desired_job_list([four_seconds, no_estimated_duration])
     self.assertEqual(session.get_estimated_duration(), (4.0, None))
コード例 #17
0
 def make_test_session(self):
     # Create a small session with two jobs and two results
     job_a = make_job('job_a')
     job_b = make_job('job_b')
     session = SessionState([job_a, job_b])
     session.update_desired_job_list([job_a, job_b])
     result_a = make_job_result(outcome=IJobResult.OUTCOME_PASS)
     result_b = make_job_result(outcome=IJobResult.OUTCOME_FAIL)
     session.update_job_result(job_a, result_a)
     session.update_job_result(job_b, result_b)
     return session
コード例 #18
0
 def test_get_estimated_duration_automated_unknown(self):
     three_seconds = make_job("three_seconds",
                              plugin="shell",
                              command="frob",
                              estimated_duration=3.0)
     no_estimated_duration = make_job("no_estimated_duration",
                                      plugin="shell",
                                      command="borf")
     session = SessionState([three_seconds, no_estimated_duration])
     session.update_desired_job_list([three_seconds, no_estimated_duration])
     self.assertEqual(session.get_estimated_duration(), (None, 0.0))
コード例 #19
0
 def test_crash_in_update_desired_job_list(self):
     # This checks if a DependencyError can cause crash
     # update_desired_job_list() with a ValueError, in certain conditions.
     A = make_job('A', depends='X')
     L = make_job('L', plugin='local')
     session = SessionState([A, L])
     problems = session.update_desired_job_list([A, L])
     # We should get exactly one DependencyMissingError related to job A and
     # the undefined job X (that is presumably defined by the local job L)
     self.assertEqual(len(problems), 1)
     self.assertIsInstance(problems[0], DependencyMissingError)
     self.assertIs(problems[0].affected_job, A)
コード例 #20
0
 def test_get_estimated_duration_manual(self):
     two_seconds = make_job("two_seconds",
                            plugin="manual",
                            command="farboo",
                            estimated_duration=2.0)
     shell_job = make_job("shell_job",
                          plugin="shell",
                          command="boofar",
                          estimated_duration=0.6)
     session = SessionState([two_seconds, shell_job])
     session.update_desired_job_list([two_seconds, shell_job])
     self.assertEqual(session.get_estimated_duration(), (0.6, 32.0))
コード例 #21
0
 def test_dont_remove_missing_jobs(self):
     """ http://pad.lv/1444126 """
     A = make_job("A", depends="B")
     B = make_job("B", depends="C")
     state = SessionState([A, B])
     problems = state.update_desired_job_list([A, B])
     self.assertEqual(problems, [
         DependencyMissingError(B, 'C', 'direct'),
         DependencyMissingError(A, 'B', 'direct'),
     ])
     self.assertEqual(state.desired_job_list, [])
     self.assertEqual(state.run_list, [])
コード例 #22
0
 def test_get_estimated_duration_auto(self):
     # Define jobs with an estimated duration
     one_second = make_job("one_second",
                           plugin="shell",
                           command="foobar",
                           estimated_duration=1.0)
     half_second = make_job("half_second",
                            plugin="shell",
                            command="barfoo",
                            estimated_duration=0.5)
     session = SessionState([one_second, half_second])
     session.update_desired_job_list([one_second, half_second])
     self.assertEqual(session.get_estimated_duration(), (1.5, 0.0))
コード例 #23
0
ファイル: test_misc.py プロジェクト: xinpengliu/checkbox
 def setUp(self):
     self.A = make_job('a', name='A')
     self.B = make_job('b', name='B', plugin='local', description='foo')
     self.C = make_job('c', name='C')
     self.D = make_job('d', name='D', plugin='shell')
     self.E = make_job('e', name='E', plugin='shell')
     self.F = make_job('f', name='F', plugin='resource', description='baz')
     state = SessionState([self.A, self.B, self.C, self.D, self.E, self.F])
     # D and E are a child of B
     state.job_state_map[self.D.id].via_job = self.B
     state.job_state_map[self.E.id].via_job = self.B
     self.tree = SelectableJobTreeNode.create_tree(
         state, [self.A, self.B, self.C, self.D, self.E, self.F])
コード例 #24
0
 def setUp(self):
     # All of the tests below are using one session. The session has four
     # jobs, clustered into two independent groups. Job A depends on a
     # resource provided by job R which has no dependencies at all. Job X
     # depends on job Y which in turn has no dependencies at all.
     #
     # A -(resource dependency)-> R
     #
     # X -(direct dependency) -> Y
     self.job_A = make_job("A", requires="R.attr == 'value'")
     self.job_A_expr = self.job_A.get_resource_program().expression_list[0]
     self.job_R = make_job("R", plugin="resource")
     self.job_X = make_job("X", depends='Y')
     self.job_Y = make_job("Y")
     self.job_list = [self.job_A, self.job_R, self.job_X, self.job_Y]
     self.session = SessionState(self.job_list)
コード例 #25
0
ファイル: test_misc.py プロジェクト: xinpengliu/checkbox
 def setUp(self):
     A = make_job('A')
     B = make_job('B', plugin='local', description='foo')
     C = make_job('C')
     D = make_job('D', plugin='shell')
     E = make_job('E', plugin='local', description='bar')
     F = make_job('F', plugin='shell')
     G = make_job('G', plugin='local', description='baz')
     R = make_job('R', plugin='resource')
     Z = make_job('Z', plugin='local', description='zaz')
     state = SessionState([A, B, C, D, E, F, G, R, Z])
     # D and E are a child of B
     state.job_state_map[D.id].via_job = B
     state.job_state_map[E.id].via_job = B
     # F is a child of E
     state.job_state_map[F.id].via_job = E
     self.tree = JobTreeNode.create_tree(state, [R, B, C, D, E, F, G, A, Z])
コード例 #26
0
ファイル: test_ctrl.py プロジェクト: kissiel/checkbox-ng
 def test_observe_result__missing_resource_key(self, mock_logger):
     job = make_job("R", plugin="resource")
     template = TemplateUnit({
         'template-resource': job.id,
         'id': 'foo-{missing}',
         'plugin': 'shell'
     })
     result = mock.Mock(spec=IJobResult, outcome=IJobResult.OUTCOME_PASS)
     result.get_io_log.return_value = [(0, 'stdout', b'attr: value1\n'),
                                       (0, 'stdout', b'\n'),
                                       (0, 'stdout', b'attr: value2\n')]
     session_state = SessionState([template, job])
     self.ctrl.observe_result(session_state, job, result)
     # Ensure that a warning was logged
     mock_logger.warning.assert_called_with(
         "Ignoring %s with missing template parameter %s", "foo-{missing}",
         "missing")
コード例 #27
0
 def test_set_resource_list(self):
     # Define an empty session
     session = SessionState([])
     # Define a resource
     old_res = Resource({'attr': 'old value'})
     # Set the resource list with the old resource
     # So here the old result is stored into a new 'R' resource
     session.set_resource_list('R', [old_res])
     # Ensure that it worked
     self.assertEqual(session._resource_map, {'R': [old_res]})
     # Define another resource
     new_res = Resource({'attr': 'new value'})
     # Now we present the second result for the same job
     session.set_resource_list('R', [new_res])
     # What should happen here is that the R resource is entirely replaced
     # by the data from the new result. The data should not be merged or
     # appended in any way.
     self.assertEqual(session._resource_map, {'R': [new_res]})
コード例 #28
0
 def test_add_job(self):
     # Define a job
     job = make_job("A")
     # Define an empty session
     session = SessionState([])
     # Add the job to the session
     session.add_job(job)
     # The job got added to job list
     self.assertIn(job, session.job_list)
     # The job got added to job state map
     self.assertIs(session.job_state_map[job.id].job, job)
     # The job is not added to the desired job list
     self.assertNotIn(job, session.desired_job_list)
     # The job is not in the run list
     self.assertNotIn(job, session.run_list)
     # The job is not selected to run
     self.assertEqual(
         session.job_state_map[job.id].readiness_inhibitor_list,
         [UndesiredJobReadinessInhibitor])
コード例 #29
0
 def test_add_job_duplicate_job(self):
     # Define a job
     job = make_job("A")
     # Define an empty session
     session = SessionState([])
     # Add the job to the session
     session.add_job(job)
     # The job got added to job list
     self.assertIn(job, session.job_list)
     # Define a perfectly identical job
     duplicate_job = make_job("A")
     self.assertEqual(job, duplicate_job)
     # Try adding it to the session
     #
     # Note that this does not raise any exceptions as the jobs are perfect
     # duplicates.
     session.add_job(duplicate_job)
     # The new job _did not_ get added to the job list
     self.assertEqual(len(session.job_list), 1)
     self.assertIsNot(duplicate_job, session.job_list[0])
コード例 #30
0
 def test_category_map_and_uncategorised(self):
     """
     Ensure that OPTION_WITH_CATEGORY_MAP synthetizes the special
     'uncategorised' category.
     """
     exporter = self.TestSessionStateExporter([
         SessionStateExporterBase.OPTION_WITH_CATEGORY_MAP
     ])
     # Create a job without a specific category
     job = JobDefinition({
         'plugin': 'shell',
         'id': 'id',
     })
     # Create and export a session with that one job
     state = SessionState([job])
     session_manager = mock.Mock(spec_set=SessionManager, state=state)
     data = exporter.get_session_data_subset(session_manager)
     # Ensure that the special 'uncategorized' category is used
     self.assertEqual(data['category_map'], {
         'com.canonical.plainbox::uncategorised': 'Uncategorised',
     })