示例#1
0
 def test_add_device_context(self):
     """
     Ensure that adding a device context works
     """
     manager = SessionManager([], self.storage)
     manager.add_device_context(self.context)
     self.assertIn(self.context, manager.device_context_list)
示例#2
0
 def test_on_device_context_removed(self):
     """
     Ensure that removing a device context sends the appropriate signal
     """
     manager = SessionManager([self.context], self.storage)
     self.watchSignal(manager.on_device_context_removed)
     manager.remove_device_context(self.context)
     self.assertSignalFired(manager.on_device_context_removed, self.context)
示例#3
0
 def setUp(self):
     self.storage = mock.Mock(name="storage", spec=SessionStorage)
     self.state = mock.Mock(name="state", spec=SessionState)
     self.context = mock.Mock(name="context", spec=SessionDeviceContext)
     self.context2 = mock.Mock(name='context2',
                               spec_set=SessionDeviceContext)
     self.context_list = [self.context]  # NOTE: just the first context
     self.manager = SessionManager(self.context_list, self.storage)
示例#4
0
 def test_add_local_device_context(self):
     """
     Ensure that using add_local_device_context() adds a context with
     a special 'local' device and fires the appropriate signal
     """
     manager = SessionManager([], self.storage)
     self.watchSignal(manager.on_device_context_added)
     cls_name = "plainbox.impl.session.manager.SessionDeviceContext"
     with mock.patch(cls_name) as sdc:
         manager.add_local_device_context()
         self.assertSignalFired(manager.on_device_context_added, sdc())
         self.assertIn(sdc(), manager.device_context_list)
示例#5
0
 def test_create_with_unit_list(self, **mocks):
     """
     verify that SessionManager.create_with_unit_list() correctly sets up
     storage repository and creates session directories
     """
     mocks['SessionStorage'].create.return_value = mock.MagicMock(
         spec_set=SessionStorage)
     # Mock unit list
     unit_list = mock.Mock(name='unit_list')
     # Create the new manager
     manager = SessionManager.create_with_unit_list(unit_list)
     # Ensure that a state object was created
     mocks['SessionState'].assert_called_with(unit_list)
     state = mocks['SessionState']()
     # Ensure that a default repository was created
     mocks['SessionStorageRepository'].assert_called_with()
     repo = mocks['SessionStorageRepository']()
     # Ensure that a storage was created, with repository location and
     # without legacy mode turned on
     mocks['SessionStorage'].create.assert_called_with(repo.location)
     storage = mocks['SessionStorage'].create()
     # Ensure that a default directories were created
     mocks['WellKnownDirsHelper'].assert_called_with(storage)
     helper = mocks['WellKnownDirsHelper']()
     helper.populate.assert_called_with()
     # Ensure that the resulting manager has correct data inside
     self.assertEqual(manager.state, state)
     self.assertEqual(manager.storage, storage)
示例#6
0
 def test_load_session(self):
     """
     verify that SessionManager.load_session() correctly delegates the task
     to various other objects
     """
     job = mock.Mock(name='job', spec_set=JobDefinition)
     unit_list = [job]
     flags = None
     helper_name = "plainbox.impl.session.manager.SessionResumeHelper"
     with mock.patch(helper_name) as helper_cls:
         resumed_state = mock.Mock(spec_set=SessionState)
         resumed_state.unit_list = unit_list
         helper_cls().resume.return_value = resumed_state
         # NOTE: mock away _propagate_test_plans() so that we don't get
         # unwanted side effects we're not testing here.
         with mock.patch.object(SessionManager, '_propagate_test_plans'):
             manager = SessionManager.load_session(unit_list, self.storage)
     # Ensure that the storage object was used to load the session snapshot
     self.storage.load_checkpoint.assert_called_with()
     # Ensure that the helper was instantiated with the unit list, flags and
     # location
     helper_cls.assert_called_with(unit_list, flags, self.storage.location)
     # Ensure that the helper instance was asked to recreate session state
     helper_cls().resume.assert_called_with(self.storage.load_checkpoint(),
                                            None)
     # Ensure that the resulting manager has correct data inside
     self.assertEqual(manager.state, helper_cls().resume())
     self.assertEqual(manager.storage, self.storage)
示例#7
0
 def test_create_with_job_list(self, **mocks):
     """
     verify that SessionManager.create_with_job_list() correctly sets up
     storage repository and creates session directories
     """
     # Mock job list
     job_list = mock.Mock(name='job_list')
     # Create the new manager
     manager = SessionManager.create_with_job_list(job_list)
     # Ensure that a state object was created
     mocks['SessionState'].assert_called_with(job_list)
     state = mocks['SessionState']()
     # Ensure that a default repository was created
     mocks['SessionStorageRepository'].assert_called_with()
     repo = mocks['SessionStorageRepository']()
     # Ensure that a storage was created, with repository location and
     # without legacy mode turned on
     mocks['SessionStorage'].create.assert_called_with(repo.location, False)
     storage = mocks['SessionStorage'].create()
     # Ensure that a default directories were created
     mocks['WellKnownDirsHelper'].assert_called_with(storage)
     helper = mocks['WellKnownDirsHelper']()
     helper.populate.assert_called_with()
     # Ensure that the resulting manager has correct data inside
     self.assertEqual(manager.state, state)
     self.assertEqual(manager.storage, storage)
示例#8
0
 def test_default_device_context__no_contexts(self):
     """
     Verify that accessing SessionManager.default_device_context returns
     None when the manager doesn't have any device context objects yet
     """
     manager = SessionManager([], self.storage)
     self.assertIsNone(manager.default_device_context, None)
示例#9
0
 def _run_local_jobs(self):
     print(_("[Running Local Jobs]").center(80, '='))
     manager = SessionManager.create_with_state(self.session)
     try:
         manager.state.metadata.title = "plainbox dev analyze session"
         manager.state.metadata.flags = [SessionMetaData.FLAG_INCOMPLETE]
         manager.checkpoint()
         runner = JobRunner(manager.storage.location,
                            self.provider_list,
                            os.path.join(manager.storage.location,
                                         'io-logs'),
                            command_io_delegate=self)
         again = True
         while again:
             for job in self.session.run_list:
                 if job.plugin == 'local':
                     if self.session.job_state_map[
                             job.id].result.outcome is None:
                         self._run_local_job(manager, runner, job)
                         break
             else:
                 again = False
         manager.state.metadata.flags = []
         manager.checkpoint()
     finally:
         manager.destroy()
示例#10
0
    def get_nested_part(self):
        """Compute and return a set of test plan ids from nested_part field."""
        nested_parts = []
        if self.nested_part is not None:
            from plainbox.impl.session import SessionManager
            with SessionManager.get_throwaway_manager(self.provider_list) as m:
                context = m.default_device_context
                testplan_ids = []

                class V(Visitor):

                    def visit_Text_node(visitor, node: Text):
                        testplan_ids.append(self.qualify_id(node.text))

                    def visit_Error_node(visitor, node: Error):
                        logger.warning(_(
                            "unable to parse nested_part: %s"), node.msg)

                V().visit(WordList.parse(self.nested_part))
                for tp_id in testplan_ids:
                    try:
                        nested_parts.append(context.get_unit(tp_id, 'test plan'))
                    except KeyError:
                        logger.warning(_(
                            "unable to find nested part: %s"), tp_id)
        return nested_parts
示例#11
0
 def export_session(self):
     if self.ns.output_format == _('?'):
         self._print_output_format_list()
         return 0
     elif self.ns.output_options == _('?'):
         self._print_output_option_list()
         return 0
     storage = self._lookup_storage(self.ns.session_id)
     if storage is None:
         print(_("No such session: {0}").format(self.ns.session_id))
     else:
         print(_("Exporting session..."))
         manager = SessionManager.load_session(
             self._get_all_units(), storage, flags=self.ns.flag)
         exporter = self._create_exporter(manager)
         # Get a stream with exported session data.
         exported_stream = io.BytesIO()
         exporter.dump_from_session_manager(manager, exported_stream)
         exported_stream.seek(0)  # Need to rewind the file, puagh
         # Write the stream to file if requested
         if self.ns.output_file is sys.stdout:
             # This requires a bit more finesse, as exporters output bytes
             # and stdout needs a string.
             translating_stream = ByteStringStreamTranslator(
                 self.ns.output_file, "utf-8")
             copyfileobj(exported_stream, translating_stream)
         else:
             print(_("Saving results to {}").format(
                 self.ns.output_file.name))
             copyfileobj(exported_stream, self.ns.output_file)
         if self.ns.output_file is not sys.stdout:
             self.ns.output_file.close()
示例#12
0
 def test_create_with_state(self, **mocks):
     """
     verify that SessionManager.create_with_state() correctly sets up
     storage repository and creates session directories
     """
     mocks['SessionStorage'].create.return_value = mock.MagicMock(
         spec_set=SessionStorage)
     # Mock an empty list of units in teh session state object
     self.state.unit_list = []
     # Create the new manager
     manager = SessionManager.create_with_state(self.state)
     # Ensure that a default repository was created
     mocks['SessionStorageRepository'].assert_called_with()
     repo = mocks['SessionStorageRepository']()
     # Ensure that a storage was created, with repository location and
     # without legacy mode turned on
     mocks['SessionStorage'].create.assert_called_with(repo.location)
     storage = mocks['SessionStorage'].create()
     # Ensure that a default directories were created
     mocks['WellKnownDirsHelper'].assert_called_with(storage)
     helper = mocks['WellKnownDirsHelper']()
     helper.populate.assert_called_with()
     # Ensure that the device context was created with the right state
     # object
     mocks['SessionDeviceContext'].assert_called_with(self.state)
     # Ensure that the resulting manager has correct data inside
     self.assertEqual(manager.device_context_list,
                      [mocks['SessionDeviceContext']()])
     # self.assertEqual(manager.state, self.state)
     self.assertEqual(manager.storage, storage)
示例#13
0
 def _print_output_option_list(self):
     print(_("Each format may support a different set of options"))
     with SessionManager.get_throwaway_manager() as manager:
         for name, exporter in manager.exporter_map.items():
             print("{}: {}".format(
                 name,
                 ", ".join(exporter.exporter_cls.supported_option_list)))
    def create_manager(self, storage):
        """
        Create or resume a session that handles most of the stuff needed to run
        jobs.

        This sets the attr:`_manager` which enables :meth:`manager`,
        :meth:`state` and :meth:`storage` properties.

        The created session state has the on_job_added signal connected to
        :meth:`on_job_added()`.

        :raises SessionResumeError:
            If the session cannot be resumed for any reason.
        """
        all_units = list(
            itertools.chain(*[p.unit_list for p in self.provider_list]))
        try:
            if storage is not None:
                self._manager = SessionManager.load_session(all_units, storage)
            else:
                self._manager = SessionManager.create_with_unit_list(all_units)
        except DependencyDuplicateError as exc:
            # Handle possible DependencyDuplicateError that can happen if
            # someone is using plainbox for job development.
            print(
                self.C.RED(
                    _("The job database you are currently using is broken")))
            print(
                self.C.RED(
                    _("At least two jobs contend for the id {0}").format(
                        exc.job.id)))
            print(
                self.C.RED(
                    _("First job defined in: {0}").format(exc.job.origin)))
            print(
                self.C.RED(
                    _("Second job defined in: {0}").format(
                        exc.duplicate_job.origin)))
            raise SystemExit(exc)
        except SessionResumeError as exc:
            print(self.C.RED(exc))
            print(self.C.RED(_("This session cannot be resumed")))
            raise
        else:
            # Connect the on_job_added signal. We use it to mark the test loop
            # for re-execution and to update the list of desired jobs.
            self.state.on_job_added.connect(self.on_job_added)
示例#15
0
 def test_storage(self):
     """
     verify that accessing SessionManager.storage works okay
     """
     storage = mock.Mock(name="storage", spec=SessionStorage)
     state = mock.Mock(name="state", spec=SessionState)
     manager = SessionManager(state, storage)
     self.assertIs(manager.storage, storage)
示例#16
0
 def test_checkpoint(self):
     """
     verify that SessionManager.checkpoint() creates an image of the
     suspended session and writes it using the storage system.
     """
     storage = mock.Mock(name="storage", spec=SessionStorage)
     state = mock.Mock(name="state", spec=SessionState)
     manager = SessionManager(state, storage)
     # Mock the suspend helper, we don't want to suspend our mock objects
     helper_name = "plainbox.impl.session.manager.SessionSuspendHelper"
     with mock.patch(helper_name, spec=SessionSuspendHelper) as helper_cls:
         # Call the tested method
         manager.checkpoint()
         # Ensure that a fresh instance of the suspend helper was used to
         # call the suspend() method and that the session state parameter
         # was passed to it.
         helper_cls().suspend.assert_called_with(state)
     # Ensure that save_checkpoint() was called on the storage object with
     # the return value of what the suspend helper produced.
     storage.save_checkpoint.assert_called_with(helper_cls().suspend(state))
示例#17
0
 def test_checkpoint(self):
     """
     verify that SessionManager.checkpoint() creates an image of the
     suspended session and writes it using the storage system.
     """
     storage = mock.Mock(name="storage", spec=SessionStorage)
     state = mock.Mock(name="state", spec=SessionState)
     manager = SessionManager(state, storage)
     # Mock the suspend helper, we don't want to suspend our mock objects
     helper_name = "plainbox.impl.session.manager.SessionSuspendHelper"
     with mock.patch(helper_name, spec=SessionSuspendHelper) as helper_cls:
         # Call the tested method
         manager.checkpoint()
         # Ensure that a fresh instance of the suspend helper was used to
         # call the suspend() method and that the session state parameter
         # was passed to it.
         helper_cls().suspend.assert_called_with(state)
     # Ensure that save_checkpoint() was called on the storage object with
     # the return value of what the suspend helper produced.
     storage.save_checkpoint.assert_called_with(helper_cls().suspend(state))
示例#18
0
 def setUp(self):
     """Common initialization."""
     exporter_unit = self._get_all_exporter_units(
     )['2013.com.canonical.plainbox::hexr']
     self.exporter = Jinja2SessionStateExporter(
         system_id='SYSTEM_ID',
         timestamp='TIMESTAMP',
         client_version='CLIENT_VERSION',
         client_name='CLIENT_NAME',
         exporter_unit=exporter_unit)
     self.manager = SessionManager.create()
     self.manager.add_local_device_context()
示例#19
0
 def test_add_device_context__twice(self):
     """
     Ensure that you cannot add the same device context twice
     """
     manager = SessionManager([], self.storage)
     manager.add_device_context(self.context)
     with self.assertRaises(ValueError):
         manager.add_device_context(self.context)
示例#20
0
def get_all_exporter_names():
    """
    Get the identifiers (names) of all the supported session state exporters.

    :returns:
        A list of session exporter names (identifiers) available from all the
        providers.

    This function creates a temporary session associated with the local
    device and adds all of the available providers to it. Finally, it returns
    the list of exporter names. The session is transparently destroyed.
    """
    with SessionManager.get_throwaway_manager() as manager:
        return list(manager.exporter_map.keys())
示例#21
0
 def test_add_device_context__add_another(self):
     """
     Ensure that adding a second context also works
     """
     manager = SessionManager([], self.storage)
     manager.add_device_context(self.context)
     manager.add_device_context(self.context2)
     self.assertIn(self.context, manager.device_context_list)
     self.assertIn(self.context2, manager.device_context_list)
示例#22
0
 def setUp(self):
     self.exporter_unit = self._get_all_exporter_units()[
         '2013.com.canonical.plainbox::html']
     self.resource_map = {
         '2013.com.canonical.certification::lsb': [
             Resource({'description': 'Ubuntu 14.04 LTS'})],
         '2013.com.canonical.certification::package': [
             Resource({'name': 'plainbox', 'version': '1.0'}),
             Resource({'name': 'fwts', 'version': '0.15.2'})],
     }
     self.job1 = JobDefinition({'id': 'job_id1', '_summary': 'job 1'})
     self.job2 = JobDefinition({'id': 'job_id2', '_summary': 'job 2'})
     self.job3 = JobDefinition({'id': 'job_id3', '_summary': 'job 3'})
     self.result_fail = MemoryJobResult({
         'outcome': IJobResult.OUTCOME_FAIL, 'return_code': 1,
         'io_log': [(0, 'stderr', b'FATAL ERROR\n')],
     })
     self.result_pass = MemoryJobResult({
         'outcome': IJobResult.OUTCOME_PASS, 'return_code': 0,
         'io_log': [(0, 'stdout', b'foo\n')],
         'comments': 'blah blah'
     })
     self.result_skip = MemoryJobResult({
         'outcome': IJobResult.OUTCOME_SKIP,
         'comments': 'No such device'
     })
     self.attachment = JobDefinition({
         'id': 'dmesg_attachment',
         'plugin': 'attachment'})
     self.attachment_result = MemoryJobResult({
         'outcome': IJobResult.OUTCOME_PASS,
         'io_log': [(0, 'stdout', b'bar\n')],
         'return_code': 0
     })
     self.session_manager = SessionManager.create()
     self.session_manager.add_local_device_context()
     self.session_state = self.session_manager.default_device_context.state
     session_state = self.session_state
     session_state.add_unit(self.job1)
     session_state.add_unit(self.job2)
     session_state.add_unit(self.job3)
     session_state.add_unit(self.attachment)
     session_state.update_job_result(self.job1, self.result_fail)
     session_state.update_job_result(self.job2, self.result_pass)
     session_state.update_job_result(self.job3, self.result_skip)
     session_state.update_job_result(
         self.attachment, self.attachment_result)
     for resource_id, resource_list in self.resource_map.items():
         session_state.set_resource_list(resource_id, resource_list)
示例#23
0
 def test_create(self, **mocks):
     """
     verify that SessionManager.create() correctly sets up
     storage repository and creates session directories
     """
     mocks['SessionStorage'].create.return_value = mock.MagicMock(
         spec_set=SessionStorage)
     # Create the new manager
     manager = SessionManager.create()
     # Ensure that a storage was created, with repository location and
     # without legacy mode turned on
     mocks['SessionStorage'].create.assert_called_with('pbox-')
     storage = mocks['SessionStorage'].create()
     # Ensure that the resulting manager has correct data inside
     self.assertEqual(manager.device_context_list, [])
     self.assertEqual(manager.storage, storage)
示例#24
0
 def invoked(self, ctx):
     manager_list = []
     for submission in ctx.args.submission:
         tmpdir = TemporaryDirectory()
         self.job_list = []
         self.category_list = []
         session_title = self._parse_submission(submission, tmpdir)
         manager = SessionManager.create_with_unit_list(self.job_list +
                                                        self.category_list)
         manager.state.metadata.title = session_title
         for job in self.job_list:
             self._populate_session_state(job, manager.state)
         manager_list.append(manager)
     exporter = self._create_exporter(
         'com.canonical.plainbox::html-multi-page')
     with open(ctx.args.output_file, 'wb') as stream:
         exporter.dump_from_session_manager_list(manager_list, stream)
     print(ctx.args.output_file)
示例#25
0
 def test_load_session(self):
     """
     verify that SessionManager.load_session() correctly delegates the task
     to various other objects
     """
     # Mock SessionState and job list
     storage = mock.Mock(name="storage", spec=SessionStorage)
     job_list = mock.Mock(name='job_list')
     helper_name = "plainbox.impl.session.manager.SessionResumeHelper"
     with mock.patch(helper_name) as helper_cls:
         helper_cls().resume.return_value = mock.Mock(
             name="state", spec=SessionState)
         manager = SessionManager.load_session(job_list, storage)
     # Ensure that the storage object was used to load the session snapshot
     storage.load_checkpoint.assert_called_with()
     # Ensure that the helper was instantiated with the job list
     helper_cls.assert_called_with(job_list)
     # Ensure that the helper instance was asked to recreate session state
     helper_cls().resume.assert_called_with(storage.load_checkpoint(), None)
     # Ensure that the resulting manager has correct data inside
     self.assertEqual(manager.state, helper_cls().resume())
     self.assertEqual(manager.storage, storage)
示例#26
0
 def test_load_session(self):
     """
     verify that SessionManager.load_session() correctly delegates the task
     to various other objects
     """
     # Mock SessionState and job list
     storage = mock.Mock(name="storage", spec=SessionStorage)
     job_list = mock.Mock(name='job_list')
     helper_name = "plainbox.impl.session.manager.SessionResumeHelper"
     with mock.patch(helper_name) as helper_cls:
         helper_cls().resume.return_value = mock.Mock(name="state",
                                                      spec=SessionState)
         manager = SessionManager.load_session(job_list, storage)
     # Ensure that the storage object was used to load the session snapshot
     storage.load_checkpoint.assert_called_with()
     # Ensure that the helper was instantiated with the job list
     helper_cls.assert_called_with(job_list)
     # Ensure that the helper instance was asked to recreate session state
     helper_cls().resume.assert_called_with(storage.load_checkpoint(), None)
     # Ensure that the resulting manager has correct data inside
     self.assertEqual(manager.state, helper_cls().resume())
     self.assertEqual(manager.storage, storage)
示例#27
0
 def test_create_with_state(self, **mocks):
     """
     verify that SessionManager.create_with_state() correctly sets up
     storage repository and creates session directories
     """
     # Mock job list
     state = mock.Mock(name='state', spec=SessionState)
     # Create the new manager
     manager = SessionManager.create_with_state(state)
     # Ensure that a default repository was created
     mocks['SessionStorageRepository'].assert_called_with()
     repo = mocks['SessionStorageRepository']()
     # Ensure that a storage was created, with repository location and
     # without legacy mode turned on
     mocks['SessionStorage'].create.assert_called_with(repo.location, False)
     storage = mocks['SessionStorage'].create()
     # Ensure that a default directories were created
     mocks['WellKnownDirsHelper'].assert_called_with(storage)
     helper = mocks['WellKnownDirsHelper']()
     helper.populate.assert_called_with()
     # Ensure that the resulting manager has correct data inside
     self.assertEqual(manager.state, state)
     self.assertEqual(manager.storage, storage)
示例#28
0
 def _run_local_jobs(self):
     print(_("[Running Local Jobs]").center(80, '='))
     manager = SessionManager.create_with_state(self.session)
     try:
         manager.state.metadata.title = "plainbox dev analyze session"
         manager.state.metadata.flags = [SessionMetaData.FLAG_INCOMPLETE]
         manager.checkpoint()
         runner = JobRunner(
             manager.storage.location, self.provider_list,
             os.path.join(manager.storage.location, 'io-logs'),
             command_io_delegate=self)
         again = True
         while again:
             for job in self.session.run_list:
                 if job.plugin == 'local':
                     if self.session.job_state_map[job.id].result.outcome is None:
                         self._run_local_job(manager, runner, job)
                         break
             else:
                 again = False
         manager.state.metadata.flags = []
         manager.checkpoint()
     finally:
         manager.destroy()
示例#29
0
 def test_create(self, **mocks):
     """
     verify that SessionManager.create() correctly sets up
     storage repository and creates session directories
     """
     mocks['SessionStorage'].create.return_value = mock.MagicMock(
         spec_set=SessionStorage)
     # Create the new manager
     manager = SessionManager.create()
     # Ensure that a default repository was created
     mocks['SessionStorageRepository'].assert_called_with()
     repo = mocks['SessionStorageRepository']()
     # Ensure that a storage was created, with repository location and
     # without legacy mode turned on
     mocks['SessionStorage'].create.assert_called_with(
         repo.location, False, 'pbox-')
     storage = mocks['SessionStorage'].create()
     # Ensure that a default directories were created
     mocks['WellKnownDirsHelper'].assert_called_with(storage)
     helper = mocks['WellKnownDirsHelper']()
     helper.populate.assert_called_with()
     # Ensure that the resulting manager has correct data inside
     self.assertEqual(manager.device_context_list, [])
     self.assertEqual(manager.storage, storage)
示例#30
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
示例#31
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
示例#32
0
 def resume_session(self, storage):
     return SessionManager.load_session(
         self._get_all_units(), storage, flags=self.ns.flag)
示例#33
0
class SessionManagerTests(SignalTestCase):
    def setUp(self):
        self.storage = mock.Mock(name="storage", spec=SessionStorage)
        self.state = mock.Mock(name="state", spec=SessionState)
        self.context = mock.Mock(name="context", spec=SessionDeviceContext)
        self.context2 = mock.Mock(name='context2',
                                  spec_set=SessionDeviceContext)
        self.context_list = [self.context]  # NOTE: just the first context
        self.manager = SessionManager(self.context_list, self.storage)

    def test_device_context_list(self):
        """
        Verify that accessing SessionManager.device_context_list works okay
        """
        self.assertEqual(self.manager.device_context_list, self.context_list)

    def test_default_device_context__typical(self):
        """
        Verify that accessing SessionManager.default_device_context returns
        the first context from the context list
        """
        self.assertEqual(self.manager.default_device_context, self.context)

    def test_default_device_context__no_contexts(self):
        """
        Verify that accessing SessionManager.default_device_context returns
        None when the manager doesn't have any device context objects yet
        """
        manager = SessionManager([], self.storage)
        self.assertIsNone(manager.default_device_context, None)

    def test_state(self):
        """
        verify that accessing SessionManager.state works okay
        """
        self.assertIs(self.manager.state, self.context.state)

    def test_storage(self):
        """
        verify that accessing SessionManager.storage works okay
        """
        self.assertIs(self.manager.storage, self.storage)

    def test_checkpoint(self):
        """
        verify that SessionManager.checkpoint() creates an image of the
        suspended session and writes it using the storage system.
        """
        # Mock the suspend helper, we don't want to suspend our mock objects
        helper_name = "plainbox.impl.session.manager.SessionSuspendHelper"
        with mock.patch(helper_name, spec=SessionSuspendHelper) as helper_cls:
            # Call the tested method
            self.manager.checkpoint()
            # Ensure that a fresh instance of the suspend helper was used to
            # call the suspend() method and that the session state parameter
            # was passed to it.
            helper_cls().suspend.assert_called_with(self.context.state,
                                                    self.storage.location)
        # Ensure that save_checkpoint() was called on the storage object with
        # the return value of what the suspend helper produced.
        self.storage.save_checkpoint.assert_called_with(helper_cls().suspend(
            self.context.state))

    def test_load_session(self):
        """
        verify that SessionManager.load_session() correctly delegates the task
        to various other objects
        """
        job = mock.Mock(name='job', spec_set=JobDefinition)
        unit_list = [job]
        flags = None
        helper_name = "plainbox.impl.session.manager.SessionResumeHelper"
        with mock.patch(helper_name) as helper_cls:
            resumed_state = mock.Mock(spec_set=SessionState)
            resumed_state.unit_list = unit_list
            helper_cls().resume.return_value = resumed_state
            # NOTE: mock away _propagate_test_plans() so that we don't get
            # unwanted side effects we're not testing here.
            with mock.patch.object(SessionManager, '_propagate_test_plans'):
                manager = SessionManager.load_session(unit_list, self.storage)
        # Ensure that the storage object was used to load the session snapshot
        self.storage.load_checkpoint.assert_called_with()
        # Ensure that the helper was instantiated with the unit list, flags and
        # location
        helper_cls.assert_called_with(unit_list, flags, self.storage.location)
        # Ensure that the helper instance was asked to recreate session state
        helper_cls().resume.assert_called_with(self.storage.load_checkpoint(),
                                               None)
        # Ensure that the resulting manager has correct data inside
        self.assertEqual(manager.state, helper_cls().resume())
        self.assertEqual(manager.storage, self.storage)

    @mock.patch.multiple("plainbox.impl.session.manager",
                         spec_set=True,
                         SessionStorageRepository=mock.DEFAULT,
                         SessionStorage=mock.DEFAULT,
                         WellKnownDirsHelper=mock.DEFAULT)
    def test_create(self, **mocks):
        """
        verify that SessionManager.create() correctly sets up
        storage repository and creates session directories
        """
        mocks['SessionStorage'].create.return_value = mock.MagicMock(
            spec_set=SessionStorage)
        # Create the new manager
        manager = SessionManager.create()
        # Ensure that a default repository was created
        mocks['SessionStorageRepository'].assert_called_with()
        repo = mocks['SessionStorageRepository']()
        # Ensure that a storage was created, with repository location and
        # without legacy mode turned on
        mocks['SessionStorage'].create.assert_called_with(
            repo.location, 'pbox-')
        storage = mocks['SessionStorage'].create()
        # Ensure that a default directories were created
        mocks['WellKnownDirsHelper'].assert_called_with(storage)
        helper = mocks['WellKnownDirsHelper']()
        helper.populate.assert_called_with()
        # Ensure that the resulting manager has correct data inside
        self.assertEqual(manager.device_context_list, [])
        self.assertEqual(manager.storage, storage)

    @mock.patch.multiple("plainbox.impl.session.manager",
                         spec_set=True,
                         SessionStorageRepository=mock.DEFAULT,
                         SessionState=mock.DEFAULT,
                         SessionStorage=mock.DEFAULT,
                         WellKnownDirsHelper=mock.DEFAULT)
    def test_create_with_unit_list(self, **mocks):
        """
        verify that SessionManager.create_with_unit_list() correctly sets up
        storage repository and creates session directories
        """
        mocks['SessionStorage'].create.return_value = mock.MagicMock(
            spec_set=SessionStorage)
        # Mock unit list
        unit_list = mock.Mock(name='unit_list')
        # Create the new manager
        manager = SessionManager.create_with_unit_list(unit_list)
        # Ensure that a state object was created
        mocks['SessionState'].assert_called_with(unit_list)
        state = mocks['SessionState']()
        # Ensure that a default repository was created
        mocks['SessionStorageRepository'].assert_called_with()
        repo = mocks['SessionStorageRepository']()
        # Ensure that a storage was created, with repository location and
        # without legacy mode turned on
        mocks['SessionStorage'].create.assert_called_with(repo.location)
        storage = mocks['SessionStorage'].create()
        # Ensure that a default directories were created
        mocks['WellKnownDirsHelper'].assert_called_with(storage)
        helper = mocks['WellKnownDirsHelper']()
        helper.populate.assert_called_with()
        # Ensure that the resulting manager has correct data inside
        self.assertEqual(manager.state, state)
        self.assertEqual(manager.storage, storage)

    @mock.patch.multiple("plainbox.impl.session.manager",
                         spec_set=True,
                         SessionStorageRepository=mock.DEFAULT,
                         SessionState=mock.DEFAULT,
                         SessionStorage=mock.DEFAULT,
                         SessionDeviceContext=mock.DEFAULT,
                         WellKnownDirsHelper=mock.DEFAULT)
    def test_create_with_state(self, **mocks):
        """
        verify that SessionManager.create_with_state() correctly sets up
        storage repository and creates session directories
        """
        mocks['SessionStorage'].create.return_value = mock.MagicMock(
            spec_set=SessionStorage)
        # Mock an empty list of units in teh session state object
        self.state.unit_list = []
        # Create the new manager
        manager = SessionManager.create_with_state(self.state)
        # Ensure that a default repository was created
        mocks['SessionStorageRepository'].assert_called_with()
        repo = mocks['SessionStorageRepository']()
        # Ensure that a storage was created, with repository location and
        # without legacy mode turned on
        mocks['SessionStorage'].create.assert_called_with(repo.location)
        storage = mocks['SessionStorage'].create()
        # Ensure that a default directories were created
        mocks['WellKnownDirsHelper'].assert_called_with(storage)
        helper = mocks['WellKnownDirsHelper']()
        helper.populate.assert_called_with()
        # Ensure that the device context was created with the right state
        # object
        mocks['SessionDeviceContext'].assert_called_with(self.state)
        # Ensure that the resulting manager has correct data inside
        self.assertEqual(manager.device_context_list,
                         [mocks['SessionDeviceContext']()])
        # self.assertEqual(manager.state, self.state)
        self.assertEqual(manager.storage, storage)

    def test_add_device_context(self):
        """
        Ensure that adding a device context works
        """
        manager = SessionManager([], self.storage)
        manager.add_device_context(self.context)
        self.assertIn(self.context, manager.device_context_list)

    @expectedFailure
    def test_add_device_context__add_another(self):
        """
        Ensure that adding a second context also works
        """
        manager = SessionManager([], self.storage)
        manager.add_device_context(self.context)
        manager.add_device_context(self.context2)
        self.assertIn(self.context, manager.device_context_list)
        self.assertIn(self.context2, manager.device_context_list)

    def test_add_device_context__twice(self):
        """
        Ensure that you cannot add the same device context twice
        """
        manager = SessionManager([], self.storage)
        manager.add_device_context(self.context)
        with self.assertRaises(ValueError):
            manager.add_device_context(self.context)

    def test_remove_context(self):
        """
        Ensure that removing a device context works
        """
        manager = SessionManager([], self.storage)
        manager.add_device_context(self.context)
        manager.remove_device_context(self.context)
        self.assertNotIn(self.context, manager.device_context_list)

    def test_remove_context__missing(self):
        """
        Ensure that you cannot remove a device context that is not added first
        """
        with self.assertRaises(ValueError):
            self.manager.remove_device_context(self.context2)

    def test_on_device_context_added(self):
        """
        Ensure that adding a device context sends the appropriate signal
        """
        manager = SessionManager([], self.storage)
        self.watchSignal(manager.on_device_context_added)
        manager.add_device_context(self.context)
        self.assertSignalFired(manager.on_device_context_added, self.context)

    def test_on_device_context_removed(self):
        """
        Ensure that removing a device context sends the appropriate signal
        """
        manager = SessionManager([self.context], self.storage)
        self.watchSignal(manager.on_device_context_removed)
        manager.remove_device_context(self.context)
        self.assertSignalFired(manager.on_device_context_removed, self.context)

    def test_add_local_device_context(self):
        """
        Ensure that using add_local_device_context() adds a context with
        a special 'local' device and fires the appropriate signal
        """
        manager = SessionManager([], self.storage)
        self.watchSignal(manager.on_device_context_added)
        cls_name = "plainbox.impl.session.manager.SessionDeviceContext"
        with mock.patch(cls_name) as sdc:
            manager.add_local_device_context()
            self.assertSignalFired(manager.on_device_context_added, sdc())
            self.assertIn(sdc(), manager.device_context_list)