def test_build_status_returns_finished_after_all_subjobs_complete_and_slaves_finished(self): subjobs = self._create_subjobs(count=3) mock_project_type = self._create_mock_project_type() mock_slave = self._create_mock_slave(num_executors=3) build = Build(BuildRequest({})) build.prepare(subjobs, mock_project_type, self._create_job_config(self._FAKE_MAX_EXECUTORS)) build.allocate_slave(mock_slave) # all three subjobs are now "in progress" # Mock out call to create build artifacts after subjobs complete build._create_build_artifact = MagicMock() for subjob in subjobs: build.mark_subjob_complete(subjob.subjob_id()) # Note: this was never a unit test! We have to wait for a thread to complete post build # actions here. TODO: Fix this poll.wait_for(lambda: build._postbuild_tasks_are_finished, 5) # Verify build artifacts was called after subjobs completed build._create_build_artifact.assert_called_once_with() build.finish() status = build._status() self.assertTrue(build._subjobs_are_finished) self.assertTrue(build._postbuild_tasks_are_finished) self.assertTrue(build._teardowns_finished) self.assertEqual(status, BuildStatus.FINISHED)
def test_build_status_returns_finished_after_all_subjobs_complete_and_slaves_finished( self): subjobs = self._create_subjobs(count=3) mock_project_type = self._create_mock_project_type() mock_slave = self._create_mock_slave(num_executors=3) build = Build(BuildRequest({})) build.prepare(subjobs, mock_project_type, self._create_job_config()) build.allocate_slave( mock_slave) # all three subjobs are now "in progress" # Mock out call to create build artifacts after subjobs complete build._create_build_artifact = MagicMock() for subjob in subjobs: build.mark_subjob_complete(subjob.subjob_id()) # Note: this was never a unit test! We have to wait for a thread to complete post build # actions here. TODO: Fix this poll.wait_for(lambda: build._postbuild_tasks_are_finished, 5) # Verify build artifacts was called after subjobs completed build._create_build_artifact.assert_called_once_with() build.finish() status = build._status() self.assertTrue(build._subjobs_are_finished) self.assertTrue(build._postbuild_tasks_are_finished) self.assertTrue(build._teardowns_finished) self.assertEqual(status, BuildStatus.FINISHED)
def test_build_status_returns_finished_after_all_subjobs_complete_and_slaves_finished( self): subjobs = self._create_subjobs(count=3) mock_project_type = self._create_mock_project_type() mock_slave = self._create_mock_slave(num_executors=3) postbuild_tasks_complete_event = Event() build = Build(BuildRequest({})) build._project_type = mock_project_type build._create_build_artifact = MagicMock() self._on_async_postbuild_tasks_completed( build, postbuild_tasks_complete_event.set) build.prepare(subjobs, self._create_job_config()) build.allocate_slave( mock_slave) # all three subjobs are now "in progress" for subjob in subjobs: build.complete_subjob(subjob.subjob_id()) # Wait for the async thread to complete executing postbuild tasks. self.assertTrue( postbuild_tasks_complete_event.wait(timeout=2), 'Postbuild tasks should complete within a few' 'seconds.') # Verify build artifacts was called after subjobs completed build._create_build_artifact.assert_called_once_with() self.assertTrue(build._subjobs_are_finished) self.assertEqual(build._status(), BuildStatus.FINISHED)
def test_update_state_to_canceled_sets_state_correctly(self): build = Build(BuildRequest({})) build._unstarted_subjobs = Queue() success = build.update_state({'status': 'canceled'}) self.assertEqual(build._status(), BuildStatus.CANCELED, "Status not set to canceled") self.assertTrue(success, "Update did not report success")
def test_build_status_returns_requested_after_build_creation(self): build = Build(BuildRequest({})) status = build._status() self.assertEqual( status, BuildStatus.QUEUED, 'Build status should be QUEUED immediately after build has been created.' )
def test_build_status_returns_queued_after_build_preparation(self): subjobs = self._create_subjobs() mock_project_type = self._create_mock_project_type() build = Build(BuildRequest({})) build.prepare(subjobs, mock_project_type, self._create_job_config(self._FAKE_MAX_EXECUTORS)) status = build._status() self.assertEqual(status, BuildStatus.QUEUED)
def test_build_status_returns_queued_after_build_preparation(self): subjobs = self._create_subjobs() mock_project_type = self._create_mock_project_type() build = Build(BuildRequest({})) build.prepare(subjobs, mock_project_type, self._create_job_config()) status = build._status() self.assertEqual( status, BuildStatus.QUEUED, 'Build status should be QUEUED after build has been prepared.')
def test_build_status_returns_building_after_some_subjobs_are_executing(self): subjobs = self._create_subjobs(count=3) mock_project_type = self._create_mock_project_type() mock_slave = self._create_mock_slave(num_executors=2) build = Build(BuildRequest({})) build.prepare(subjobs, mock_project_type, self._create_job_config(self._FAKE_MAX_EXECUTORS)) build.allocate_slave(mock_slave) # two out of three subjobs are now "in progress" status = build._status() self.assertEqual(status, BuildStatus.BUILDING)
def test_cancel_exits_early_if_build_not_running(self): build = Build(BuildRequest({})) build._unstarted_subjobs = Queue() slave_mock = Mock() build._slaves_allocated = [slave_mock] build._status = Mock(return_value=BuildStatus.FINISHED) build.cancel() self.assertFalse(build._is_canceled, "Build should not be canceled") self.assertEqual(slave_mock.teardown.call_count, 0, "Teardown should not have been called")
def test_build_status_returns_queued_after_build_preparation(self): subjobs = self._create_subjobs() mock_project_type = self._create_mock_project_type() build = Build(BuildRequest({})) build._project_type = mock_project_type build.prepare(subjobs, self._create_job_config()) status = build._status() self.assertEqual(status, BuildStatus.QUEUED, 'Build status should be QUEUED after build has been prepared.')
def test_build_status_returns_building_after_setup_has_started(self): subjobs = self._create_subjobs() mock_project_type = self._create_mock_project_type() mock_slave = self._create_mock_slave() build = Build(BuildRequest({})) build._project_type = mock_project_type build.prepare(subjobs, self._create_job_config()) build.allocate_slave(mock_slave) self.assertEqual(build._status(), BuildStatus.BUILDING, 'Build status should be BUILDING after setup has started on slaves.')
def test_build_status_returns_building_after_setup_has_started(self): subjobs = self._create_subjobs() mock_project_type = self._create_mock_project_type() mock_slave = self._create_mock_slave() build = Build(BuildRequest({})) build.prepare(subjobs, mock_project_type, self._create_job_config()) build.allocate_slave(mock_slave) self.assertEqual( build._status(), BuildStatus.BUILDING, 'Build status should be BUILDING after setup has started on slaves.' )
def test_build_status_returns_building_after_setup_is_complete_and_subjobs_are_executing(self): subjobs = self._create_subjobs(count=3) mock_project_type = self._create_mock_project_type() mock_slave = self._create_mock_slave(num_executors=2) build = Build(BuildRequest({})) build._project_type = mock_project_type build.prepare(subjobs, self._create_job_config()) build.allocate_slave(mock_slave) build.begin_subjob_executions_on_slave(mock_slave) # two out of three subjobs are now in progress self.assertEqual(build._status(), BuildStatus.BUILDING, 'Build status should be BUILDING after subjobs have started executing on slaves.')
def test_build_status_returns_building_after_setup_is_complete_and_subjobs_are_executing( self): subjobs = self._create_subjobs(count=3) mock_project_type = self._create_mock_project_type() mock_slave = self._create_mock_slave(num_executors=2) build = Build(BuildRequest({})) build.prepare(subjobs, mock_project_type, self._create_job_config()) build.allocate_slave(mock_slave) build.begin_subjob_executions_on_slave( mock_slave) # two out of three subjobs are now in progress self.assertEqual( build._status(), BuildStatus.BUILDING, 'Build status should be BUILDING after subjobs have started executing on slaves.' )
def test_build_status_returns_finished_after_all_subjobs_complete_and_slaves_finished(self): subjobs = self._create_subjobs(count=3) mock_project_type = self._create_mock_project_type() mock_slave = self._create_mock_slave(num_executors=3) postbuild_tasks_complete_event = Event() build = Build(BuildRequest({})) build._project_type = mock_project_type build._create_build_artifact = MagicMock() self._on_async_postbuild_tasks_completed(build, postbuild_tasks_complete_event.set) build.prepare(subjobs, self._create_job_config()) build.allocate_slave(mock_slave) # all three subjobs are now "in progress" for subjob in subjobs: build.complete_subjob(subjob.subjob_id()) # Wait for the async thread to complete executing postbuild tasks. self.assertTrue(postbuild_tasks_complete_event.wait(timeout=2), 'Postbuild tasks should complete within a few' 'seconds.') # Verify build artifacts was called after subjobs completed build._create_build_artifact.assert_called_once_with() self.assertTrue(build._subjobs_are_finished) self.assertEqual(build._status(), BuildStatus.FINISHED)
def test_build_status_returns_requested_after_build_creation(self): build = Build(BuildRequest({})) status = build._status() self.assertEqual(status, BuildStatus.QUEUED, 'Build status should be QUEUED immediately after build has been created.')
def test_build_status_returns_requested_after_build_creation(self): build = Build(BuildRequest({})) status = build._status() self.assertEqual(status, BuildStatus.QUEUED)
def _store_build(cls, build: Build) -> int: """ Serialize a Build object and commit all of the parts to the database, and then return the build_id that was assigned after committing. :param build: The build to store into the database. """ with Connection.get() as session: build_params = build._build_request._build_parameters fsm_timestamps = { state.lower(): timestamp for state, timestamp in build._state_machine.transition_timestamps.items() } build_artifact_dir = None if build._build_artifact is not None: build_artifact_dir = build._build_artifact.build_artifact_dir build_schema = BuildSchema( artifacts_tar_file=build._artifacts_tar_file, artifacts_zip_file=build._artifacts_zip_file, error_message=build._error_message, postbuild_tasks_are_finished=bool( build._postbuild_tasks_are_finished), setup_failures=build.setup_failures, timing_file_path=build._timing_file_path, build_artifact_dir=build_artifact_dir, build_parameters=json.dumps( build._build_request.build_parameters()), state=build._status(), queued_ts=fsm_timestamps['queued'], finished_ts=fsm_timestamps['finished'], prepared_ts=fsm_timestamps['prepared'], preparing_ts=fsm_timestamps['preparing'], error_ts=fsm_timestamps['error'], canceled_ts=fsm_timestamps['canceled'], building_ts=fsm_timestamps['building']) session.add(build_schema) # Commit this first to get the build_id created by the database # We use this build_id to store the other parts of a Build object session.commit() build_id = build_schema.build_id # FailedArtifactDirectories if build._build_artifact is not None: for directory in build._build_artifact._get_failed_artifact_directories( ): failed_artifact_directories_schema = FailedArtifactDirectoriesSchema( build_id=build_id, failed_artifact_directory=directory) session.add(failed_artifact_directories_schema) # FailedSubjobAtomPairs if build._build_artifact is not None: for subjob_id, atom_id in build._build_artifact.get_failed_subjob_and_atom_ids( ): failed_subjob_atom_pairs_schema = FailedSubjobAtomPairsSchema( build_id=build_id, subjob_id=subjob_id, atom_id=atom_id) session.add(failed_subjob_atom_pairs_schema) # Subjobs subjobs = build._all_subjobs_by_id for subjob_id in subjobs: subjob = build._all_subjobs_by_id[subjob_id] subjob_schema = SubjobsSchema(subjob_id=subjob_id, build_id=build_id, completed=subjob.completed) session.add(subjob_schema) # Atoms for atom in subjob._atoms: # pylint: disable=protected-access atom_schema = AtomsSchema( atom_id=atom.id, build_id=build_id, subjob_id=subjob_id, command_string=atom.command_string, expected_time=atom.expected_time, actual_time=atom.actual_time, exit_code=atom.exit_code, state=atom.state, ) session.add(atom_schema) return build_id