Esempio n. 1
0
 def test_resource_job_result_overwrites_old_resources(self):
     # This function checks what happens when a JobResult for job R is
     # presented to a session that has some resources from that job already.
     result_R_old = JobResult({
         'job':
         self.job_R,
         'io_log':
         make_io_log(((0, 'stdout', b"attr: old value\n"), ),
                     self.scratch_dir)
     })
     self.session.update_job_result(self.job_R, result_R_old)
     # So here the old result is stored into a new 'R' resource
     expected_before = {'R': [Resource({'attr': 'old value'})]}
     self.assertEqual(self.session._resource_map, expected_before)
     # Now we present the second result for the same job
     result_R_new = JobResult({
         'job':
         self.job_R,
         'io_log':
         make_io_log(((0, 'stdout', b"attr: new value\n"), ),
                     self.scratch_dir)
     })
     self.session.update_job_result(self.job_R, result_R_new)
     # 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.
     expected_after = {'R': [Resource({'attr': 'new value'})]}
     self.assertEqual(self.session._resource_map, expected_after)
 def test_everything(self, mock_logger):
     result = DiskJobResult({
         'outcome':
         IJobResult.OUTCOME_PASS,
         'comments':
         "it said blah",
         'io_log_filename':
         make_io_log([(0, 'stdout', b'blah\n')], self.scratch_dir.name),
         'return_code':
         0
     })
     self.assertEqual(str(result), "pass")
     # This result contains a random vale of io_log_filename so direct repr
     # comparison is not feasable. All we want to check here is that it
     # looks right and that it has the outcome value
     self.assertTrue(repr(result).startswith("<DiskJobResult"))
     self.assertTrue(repr(result).endswith(">"))
     self.assertIn("outcome:'pass'", repr(result))
     self.assertEqual(result.outcome, IJobResult.OUTCOME_PASS)
     self.assertEqual(result.comments, "it said blah")
     self.assertEqual(result.io_log, ((0, 'stdout', b'blah\n'), ))
     assert mock_logger.warning.call_count == 1
     self.assertEqual(result.io_log_as_flat_text, 'blah\n')
     self.assertEqual(result.return_code, 0)
     self.assertFalse(result.is_hollow)
Esempio n. 3
0
 def test_resource_job_with_broken_output(self):
     # This function checks how SessionState parses partially broken
     # resource jobs.  A JobResult with broken output is constructed below.
     # The output will describe one proper record, one broken record and
     # another proper record in that order.
     result_R = JobResult({
         'job': self.job_R,
         'io_log': make_io_log((
             (0, 'stdout', b"attr: value-1\n"),
             (1, 'stdout', b"\n"),
             (1, 'stdout', b"I-sound-like-a-broken-record\n"),
             (1, 'stdout', b"\n"),
             (1, 'stdout', b"attr: value-2\n")),
             self.scratch_dir)
     })
     # Since we cannot control the output of scripts and people indeed make
     # mistakes a warning is issued but no exception is raised to the
     # caller.
     self.session.update_job_result(self.job_R, result_R)
     # The observation here is that the parser is not handling the exception
     # in away which would allow for recovery. Out of all the output only
     # the first record is created and stored properly. The third, proper
     # record is entirely ignored.
     expected = {'R': [Resource({'attr': 'value-1'})]}
     self.assertEqual(self.session._resource_map, expected)
Esempio n. 4
0
 def test_resource_job_result_updates_resource_and_job_states(self):
     # This function checks what happens when a JobResult for job R (which
     # is a resource job via the resource plugin) is presented to the
     # session.
     result_R = JobResult({
         'job': self.job_R,
         'io_log': make_io_log(((0, 'stdout', b"attr: value\n"),),
                               self.scratch_dir)
     })
     self.session.update_job_result(self.job_R, result_R)
     # The most obvious thing that can happen, is that the result is simply
     # stored in the associated job state object.
     self.assertIs(self.job_state('R').result, result_R)
     # Initially the _resource_map was empty. SessionState parses the io_log
     # of results of resource jobs and creates appropriate resource objects.
     self.assertIn("R", self.session._resource_map)
     expected = {'R': [Resource({'attr': 'value'})]}
     self.assertEqual(self.session._resource_map, expected)
     # As job results are presented to the session the readiness of other
     # jobs is changed. Since A depends on R via a resource expression and
     # the particular resource that were produced by R in this test should
     # allow the expression to match the readiness inhibitor from A should
     # have been removed. Since this test does not use
     # update_desired_job_list() a will still have the UNDESIRED inhibitor
     # but it will no longer have the PENDING_RESOURCE inhibitor,
     self.assertEqual(self.job_inhibitor('A', 0).cause,
                      JobReadinessInhibitor.UNDESIRED)
     # Now if we put A on the desired list this should clear the UNDESIRED
     # inhibitor and make A runnable.
     self.session.update_desired_job_list([self.job_A])
     self.assertTrue(self.job_state('A').can_start())
Esempio n. 5
0
 def test_resource_job_with_broken_output(self):
     # This function checks how SessionState parses partially broken
     # resource jobs.  A JobResult with broken output is constructed below.
     # The output will describe one proper record, one broken record and
     # another proper record in that order.
     result_R = JobResult({
         'job':
         self.job_R,
         'io_log':
         make_io_log(
             ((0, 'stdout', b"attr: value-1\n"), (1, 'stdout', b"\n"),
              (1, 'stdout', b"I-sound-like-a-broken-record\n"),
              (1, 'stdout', b"\n"), (1, 'stdout', b"attr: value-2\n")),
             self.scratch_dir)
     })
     # Since we cannot control the output of scripts and people indeed make
     # mistakes a warning is issued but no exception is raised to the
     # caller.
     self.session.update_job_result(self.job_R, result_R)
     # The observation here is that the parser is not handling the exception
     # in away which would allow for recovery. Out of all the output only
     # the first record is created and stored properly. The third, proper
     # record is entirely ignored.
     expected = {'R': [Resource({'attr': 'value-1'})]}
     self.assertEqual(self.session._resource_map, expected)
Esempio n. 6
0
 def test_resource_job_result_updates_resource_and_job_states(self):
     # This function checks what happens when a JobResult for job R (which
     # is a resource job via the resource plugin) is presented to the
     # session.
     result_R = JobResult({
         'job':
         self.job_R,
         'io_log':
         make_io_log(((0, 'stdout', b"attr: value\n"), ), self.scratch_dir)
     })
     self.session.update_job_result(self.job_R, result_R)
     # The most obvious thing that can happen, is that the result is simply
     # stored in the associated job state object.
     self.assertIs(self.job_state('R').result, result_R)
     # Initially the _resource_map was empty. SessionState parses the io_log
     # of results of resource jobs and creates appropriate resource objects.
     self.assertIn("R", self.session._resource_map)
     expected = {'R': [Resource({'attr': 'value'})]}
     self.assertEqual(self.session._resource_map, expected)
     # As job results are presented to the session the readiness of other
     # jobs is changed. Since A depends on R via a resource expression and
     # the particular resource that were produced by R in this test should
     # allow the expression to match the readiness inhibitor from A should
     # have been removed. Since this test does not use
     # update_desired_job_list() a will still have the UNDESIRED inhibitor
     # but it will no longer have the PENDING_RESOURCE inhibitor,
     self.assertEqual(
         self.job_inhibitor('A', 0).cause, JobReadinessInhibitor.UNDESIRED)
     # Now if we put A on the desired list this should clear the UNDESIRED
     # inhibitor and make A runnable.
     self.session.update_desired_job_list([self.job_A])
     self.assertTrue(self.job_state('A').can_start())
Esempio n. 7
0
 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()
Esempio n. 8
0
 def test_everything(self):
     result = DiskJobResult({
         'outcome': IJobResult.OUTCOME_PASS,
         'comments': "it said blah",
         'io_log_filename': make_io_log([
             (0, 'stdout', b'blah\n')
         ], self.scratch_dir.name),
         'return_code': 0
     })
     self.assertEqual(str(result), "pass")
     self.assertEqual(repr(result), "<DiskJobResult outcome:'pass'>")
     self.assertEqual(result.outcome, IJobResult.OUTCOME_PASS)
     self.assertEqual(result.comments, "it said blah")
     self.assertEqual(result.io_log, ((0, 'stdout', b'blah\n'),))
     self.assertEqual(result.return_code, 0)
Esempio n. 9
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',
         'command': 'echo testing && true',
         'requires': 'job_b.ready == "yes"'
     })
     job_b = JobDefinition({
         'plugin': 'resource',
         'name': 'job_b',
         'command': 'echo ready: yes'
     })
     session = SessionState([job_a, job_b])
     session.update_desired_job_list([job_a, job_b])
     result_a = JobResult({
         'job': job_a,
         'outcome': 'pass',
         'return_code': 0,
         'io_log': make_io_log(
             (IOLogRecord(0, 'stdout', b'testing\n'),),
             session_dir)
     })
     result_b = JobResult({
         'job': job_b,
         'outcome': 'pass',
         'return_code': 0,
         'comments': 'foo',
         'io_log': make_io_log(
             (IOLogRecord(0, 'stdout', b'ready: yes\n'),),
             session_dir)
     })
     session.update_job_result(job_a, result_a)
     session.update_job_result(job_b, result_b)
     return session
Esempio n. 10
0
 def test_resource_job_result_overwrites_old_resources(self):
     # This function checks what happens when a JobResult for job R is
     # presented to a session that has some resources from that job already.
     result_R_old = JobResult({
         'job': self.job_R,
         'io_log': make_io_log(((0, 'stdout', b"attr: old value\n"),),
                               self.scratch_dir)
     })
     self.session.update_job_result(self.job_R, result_R_old)
     # So here the old result is stored into a new 'R' resource
     expected_before = {'R': [Resource({'attr': 'old value'})]}
     self.assertEqual(self.session._resource_map, expected_before)
     # Now we present the second result for the same job
     result_R_new = JobResult({
         'job': self.job_R,
         'io_log': make_io_log(((0, 'stdout', b"attr: new value\n"),),
                               self.scratch_dir)
     })
     self.session.update_job_result(self.job_R, result_R_new)
     # 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.
     expected_after = {'R': [Resource({'attr': 'new value'})]}
     self.assertEqual(self.session._resource_map, expected_after)
Esempio n. 11
0
 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()
Esempio n. 12
0
 def test_everything(self):
     result = DiskJobResult({
         'outcome':
         IJobResult.OUTCOME_PASS,
         'comments':
         "it said blah",
         'io_log_filename':
         make_io_log([(0, 'stdout', b'blah\n')], self.scratch_dir.name),
         'return_code':
         0
     })
     self.assertEqual(str(result), "pass")
     self.assertEqual(repr(result), "<DiskJobResult outcome:'pass'>")
     self.assertEqual(result.outcome, IJobResult.OUTCOME_PASS)
     self.assertEqual(result.comments, "it said blah")
     self.assertEqual(result.io_log, ((0, 'stdout', b'blah\n'), ))
     self.assertEqual(result.return_code, 0)
Esempio n. 13
0
 def test_desired_job_X_cannot_run_with_no_resource_R(self):
     # A variant of the two test cases above, using A-R jobs
     self.session.update_desired_job_list([self.job_A])
     result_R = JobResult({
         'job': self.job_R,
         'io_log': make_io_log(((0, 'stdout', b'attr: wrong value\n'),),
                               self.scratch_dir)
     })
     self.session.update_job_result(self.job_R, result_R)
     # Now A is inhibited by FAILED_RESOURCE
     self.assertNotEqual(self.job_state('A').readiness_inhibitor_list, [])
     self.assertEqual(self.job_inhibitor('A', 0).cause,
                      JobReadinessInhibitor.FAILED_RESOURCE)
     self.assertEqual(self.job_inhibitor('A', 0).related_job, self.job_R)
     self.assertEqual(self.job_inhibitor('A', 0).related_expression,
                      self.job_A_expr)
     self.assertFalse(self.job_state('A').can_start())
Esempio n. 14
0
 def test_everything(self):
     with TemporaryDirectory() as scratch_dir:
         result = JobResult({
             'job': self.job,
             'outcome': JobResult.OUTCOME_PASS,
             'comments': "it said blah",
             'io_log': make_io_log(((0, 'stdout', b'blah\n'),),
                                   scratch_dir),
             'return_code': 0
         })
         self.assertEqual(str(result), "A: pass")
         self.assertEqual(repr(result), (
             "<JobResult job:<JobDefinition name:'A' plugin:'dummy'>"
             " outcome:'pass'>"))
         self.assertIs(result.job, self.job)
         self.assertEqual(result.outcome, JobResult.OUTCOME_PASS)
         self.assertEqual(result.comments, "it said blah")
         self.assertEqual(result.io_log, ((0, 'stdout', b'blah\n'),))
         self.assertEqual(result.return_code, 0)
Esempio n. 15
0
 def test_everything(self):
     result = DiskJobResult(
         {
             "outcome": IJobResult.OUTCOME_PASS,
             "comments": "it said blah",
             "io_log_filename": make_io_log([(0, "stdout", b"blah\n")], self.scratch_dir.name),
             "return_code": 0,
         }
     )
     self.assertEqual(str(result), "pass")
     # This result contains a random vale of io_log_filename so direct repr
     # comparison is not feasable. All we want to check here is that it
     # looks right and that it has the outcome value
     self.assertTrue(repr(result).startswith("<DiskJobResult"))
     self.assertTrue(repr(result).endswith(">"))
     self.assertIn("outcome:'pass'", repr(result))
     self.assertEqual(result.outcome, IJobResult.OUTCOME_PASS)
     self.assertEqual(result.comments, "it said blah")
     self.assertEqual(result.io_log, ((0, "stdout", b"blah\n"),))
     self.assertEqual(result.return_code, 0)
Esempio n. 16
0
 def test_desired_job_X_cannot_run_with_no_resource_R(self):
     # A variant of the two test cases above, using A-R jobs
     self.session.update_desired_job_list([self.job_A])
     result_R = JobResult({
         'job':
         self.job_R,
         'io_log':
         make_io_log(((0, 'stdout', b'attr: wrong value\n'), ),
                     self.scratch_dir)
     })
     self.session.update_job_result(self.job_R, result_R)
     # Now A is inhibited by FAILED_RESOURCE
     self.assertNotEqual(self.job_state('A').readiness_inhibitor_list, [])
     self.assertEqual(
         self.job_inhibitor('A', 0).cause,
         JobReadinessInhibitor.FAILED_RESOURCE)
     self.assertEqual(self.job_inhibitor('A', 0).related_job, self.job_R)
     self.assertEqual(
         self.job_inhibitor('A', 0).related_expression, self.job_A_expr)
     self.assertFalse(self.job_state('A').can_start())