Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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")
Exemplo n.º 5
0
    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.'
        )
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
    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")
Exemplo n.º 8
0
    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.')
Exemplo n.º 9
0
    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)
Exemplo n.º 10
0
    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")
Exemplo n.º 11
0
    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.')
Exemplo n.º 12
0
    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.')
Exemplo n.º 13
0
    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")
Exemplo n.º 14
0
    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.'
        )
Exemplo n.º 15
0
    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.')
Exemplo n.º 16
0
    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.'
        )
Exemplo n.º 17
0
    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)
Exemplo n.º 18
0
    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.')
Exemplo n.º 19
0
    def test_build_status_returns_requested_after_build_creation(self):
        build = Build(BuildRequest({}))
        status = build._status()

        self.assertEqual(status, BuildStatus.QUEUED)
Exemplo n.º 20
0
    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