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)
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 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_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)
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)
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)
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)
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 _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()
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
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()
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 _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)
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)
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))
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()
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 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())
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 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)
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)
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)
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)
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)
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)
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()
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)
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
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
def resume_session(self, storage): return SessionManager.load_session( self._get_all_units(), storage, flags=self.ns.flag)
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)