def test_get_environ_settings(self): job1 = JobDefinition({}) self.assertEqual(job1.get_environ_settings(), set()) job2 = JobDefinition({'environ': 'a b c'}) self.assertEqual(job2.get_environ_settings(), set(['a', 'b', 'c'])) job3 = JobDefinition({'environ': 'a,b,c'}) self.assertEqual(job3.get_environ_settings(), set(['a', 'b', 'c']))
def test_get_flag_set(self): job1 = JobDefinition({}) self.assertEqual(job1.get_flag_set(), set()) job2 = JobDefinition({'flags': 'a b c'}) self.assertEqual(job2.get_flag_set(), set(['a', 'b', 'c'])) job3 = JobDefinition({'flags': 'a,b,c'}) self.assertEqual(job3.get_flag_set(), set(['a', 'b', 'c']))
def test_get_record_value(self): """ Ensure that get_record_value() works okay """ job1 = JobDefinition({'key': 'value'}, raw_data={'key': 'raw-value'}) job2 = JobDefinition({'_key': 'value'}, raw_data={'_key': 'raw-value'}) self.assertEqual(job1.get_record_value('key'), 'value') self.assertEqual(job2.get_record_value('key'), 'value')
def test_summary(self): job1 = JobDefinition({}) self.assertEqual(job1.summary, None) job2 = JobDefinition({'name': 'name'}) self.assertEqual(job2.summary, 'name') job3 = JobDefinition({'summary': 'summary'}) self.assertEqual(job3.summary, 'summary') job4 = JobDefinition({'summary': 'summary', 'name': 'name'}) self.assertEqual(job4.summary, 'summary')
def test_checksum_smoke(self): job1 = JobDefinition({'plugin': 'plugin', 'user': '******'}) identical_to_job1 = JobDefinition({'plugin': 'plugin', 'user': '******'}) # Two distinct but identical jobs have the same checksum self.assertEqual(job1.checksum, identical_to_job1.checksum) job2 = JobDefinition({'plugin': 'plugin', 'user': '******'}) # Two jobs with different definitions have different checksum self.assertNotEqual(job1.checksum, job2.checksum) # The checksum is stable and does not change over time self.assertEqual( job1.checksum, "c47cc3719061e4df0010d061e6f20d3d046071fd467d02d093a03068d2f33400")
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_startup_user_interaction_required(self): job = JobDefinition({ 'id': 'id', 'plugin': self.parameters.plugin}) expected = self.parameters_keymap[self.parameters.plugin] observed = job.startup_user_interaction_required self.assertEqual(expected, observed)
def test_smoke_min_record(self): job = JobDefinition(self._min_record.data) self.assertEqual(job.plugin, "plugin") self.assertEqual(job.id, "id") self.assertEqual(job.requires, None) self.assertEqual(job.command, None) self.assertEqual(job.description, None)
def test_properties(self): """ Ensure that properties are looked up in the non-raw copy of the data """ job = JobDefinition({ 'plugin': 'plugin-value', 'command': 'command-value', 'environ': 'environ-value', 'user': '******', 'shell': 'shell-value', 'flags': 'flags-value', 'category_id': 'category_id-value', }, raw_data={ 'plugin': 'plugin-raw', 'command': 'command-raw', 'environ': 'environ-raw', 'user': '******', 'shell': 'shell-raw', 'flags': 'flags-raw', 'category_id': 'category_id-raw', }) self.assertEqual(job.plugin, "plugin-value") self.assertEqual(job.command, "command-value") self.assertEqual(job.environ, "environ-value") self.assertEqual(job.user, "user-value") self.assertEqual(job.shell, "shell-value") self.assertEqual(job.flags, "flags-value") self.assertEqual(job.category_id, "category_id-value")
def test_environ_parsing_empty(self): job = JobDefinition({ 'id': 'id', 'plugin': 'plugin'}) expected = set() observed = job.get_environ_settings() self.assertEqual(expected, observed)
def test_resource_parsing_empty(self): job = JobDefinition({ 'id': 'id', 'plugin': 'plugin'}) expected = set() observed = job.get_resource_dependencies() self.assertEqual(expected, observed)
def test_get_imported_jobs(self): job1 = JobDefinition({}) self.assertEqual(list(job1.get_imported_jobs()), []) job2 = JobDefinition({ 'imports': 'from com.canonical.certification import package' }) self.assertEqual(list(job2.get_imported_jobs()), [ ('com.canonical.certification::package', 'package') ]) job3 = JobDefinition({ 'imports': ('from com.canonical.certification' ' import package as pkg') }) self.assertEqual(list(job3.get_imported_jobs()), [ ('com.canonical.certification::package', 'pkg') ])
def test_tr_description_combining(self): """ Verify that translated description is properly generated """ job = JobDefinition(self._split_description_record.data) def side_effect(arg): return { 'description': None, 'PURPOSE': 'TR_PURPOSE', 'STEPS': 'TR_STEPS', 'VERIFICATION': 'TR_VERIFICATION', 'purpose': 'tr_purpose_value', 'steps': 'tr_steps_value', 'verification': 'tr_verification_value' }[arg] with mock.patch.object(job, "get_translated_record_value") as mgtrv: mgtrv.side_effect = side_effect with mock.patch('plainbox.impl.unit.job._') as mock_gettext: mock_gettext.side_effect = side_effect retval = job.tr_description() mgtrv.assert_any_call('description') mgtrv.assert_any_call('purpose') mgtrv.assert_any_call('steps') mgtrv.assert_any_call('verification') self.assertEqual(mgtrv.call_count, 4) mock_gettext.assert_any_call('PURPOSE') mock_gettext.assert_any_call('STEPS') mock_gettext.assert_any_call('VERIFICATION') self.assertEqual(mock_gettext.call_count, 3) expected = ("TR_PURPOSE:\ntr_purpose_value\nTR_STEPS:\n" "tr_steps_value\nTR_VERIFICATION:\ntr_verification_value") self.assertEqual(retval, expected)
def test_smoke_full_record(self): job = JobDefinition(self._full_record.data) self.assertEqual(job.plugin, "plugin") self.assertEqual(job.id, "id") self.assertEqual(job.requires, "requires") self.assertEqual(job.command, "command") self.assertEqual(job.description, "description-value")
def test_tr_summary__falls_back_to_id(self): """ Verify that Provider1.tr_summary() falls back to job.id, if summary is not defined """ job = JobDefinition({'id': 'id'}) self.assertEqual(job.tr_summary(), 'id')
def test_environ_parsing_single_word(self): job = JobDefinition({ 'id': 'id', 'plugin': 'plugin', 'environ': 'word'}) expected = set(['word']) observed = job.get_environ_settings() self.assertEqual(expected, observed)
def test_smoke_full_gettext_record(self): job = JobDefinition(self._full_gettext_record.data) self.assertEqual(job.plugin, "plugin") self.assertEqual(job.id, "id") self.assertEqual(job.requires, "requires") self.assertEqual(job.command, "command") self.assertEqual(job.description, "description-value") self.assertEqual(job.siblings, '[{"id": "foo", "depends": "bar"}]')
def test_resource_parsing_typical(self): job = JobDefinition({ 'id': 'id', 'plugin': 'plugin', 'requires': 'foo.bar == 10'}) expected = set(['foo']) observed = job.get_resource_dependencies() self.assertEqual(expected, observed)
def test_dependency_parsing_quoted_word(self): job = JobDefinition({ 'id': 'id', 'plugin': 'plugin', 'depends': '"quoted word"'}) expected = set(['quoted word']) observed = job.get_direct_dependencies() self.assertEqual(expected, observed)
def test_environ_parsing_with_various_separators(self): job = JobDefinition({ 'id': 'id', 'plugin': 'plugin', 'environ': self.parameters_keymap[ self.parameters.glue].join(['foo', 'bar', 'froz'])}) expected = set({'foo', 'bar', 'froz'}) observed = job.get_environ_settings() self.assertEqual(expected, observed)
def test_get_resource_program_using_imports(self): job = JobDefinition({ 'imports': ('from com.canonical.certification' ' import package as pkg'), 'requires': 'pkg.name == "checkbox"', }) prog = job.get_resource_program() self.assertEqual( prog.required_resources, {'com.canonical.certification::package'})
def test_resource_parsing_many(self): job = JobDefinition({ 'id': 'id', 'plugin': 'plugin', 'requires': ( "foo.bar == 10\n" "froz.bot == 10\n")}) expected = set(['foo', 'froz']) observed = job.get_resource_dependencies() self.assertEqual(expected, observed)
def test_tr_description(self): """ Verify that Provider1.tr_description() works as expected """ job = JobDefinition(self._full_record.data) with mock.patch.object(job, "get_translated_record_value") as mgtrv: retval = job.tr_description() # Ensure that get_translated_record_value() was called mgtrv.assert_called_once_with('description') # Ensure tr_description() returned its return value self.assertEqual(retval, mgtrv())
def test_checksum_smoke(self): job1 = JobDefinition({ 'id': 'id', 'plugin': 'plugin' }) identical_to_job1 = JobDefinition({ 'id': 'id', 'plugin': 'plugin' }) # Two distinct but identical jobs have the same checksum self.assertEqual(job1.checksum, identical_to_job1.checksum) job2 = JobDefinition({ 'id': 'other id', 'plugin': 'plugin' }) # Two jobs with different definitions have different checksum self.assertNotEqual(job1.checksum, job2.checksum) # The checksum is stable and does not change over time self.assertEqual( job1.checksum, "cd21b33e6a2f4d1291977b60d922bbd276775adce73fca8c69b4821c96d7314a")
def test_properties_default_values(self): """ Ensure that all properties default to None """ job = JobDefinition({}) self.assertEqual(job.plugin, None) self.assertEqual(job.command, None) self.assertEqual(job.environ, None) self.assertEqual(job.user, None) self.assertEqual(job.shell, 'bash') self.assertEqual(job.flags, None) self.assertEqual(job.category_id, 'com.canonical.plainbox::uncategorised')
def test_requires__refers_to_other_resource_jobs(self): other_unit = JobDefinition({ 'id': 'some_unit', 'plugin': 'shell' }, provider=self.provider) unit = self.unit_cls({ 'requires': 'some_unit.attr == "value"' }, provider=self.provider) message = "field 'requires', the referenced job is not a resource job" self.provider.unit_list = [unit, other_unit] context = UnitValidationContext([self.provider]) issue_list = unit.check(context=context) self.assertIssueFound( issue_list, self.unit_cls.Meta.fields.requires, Problem.bad_reference, Severity.error, message)
def test_1444242(self): """ Regression test for http://pad.lv/1444242/. """ provider = mock.Mock(spec_set=Provider1, name='provider') provider.namespace = 'com.canonical.certification' job = JobDefinition({ 'id': 'audio/playback_thunderbolt', 'imports': 'from com.canonical.plainbox import manifest', 'requires': ( "device.category == 'AUDIO'\n" "manifest.has_thunderbolt == 'True'\n"), }, provider=provider) prog = job.get_resource_program() self.assertEqual(prog.expression_list[-1].resource_id_list, ['com.canonical.plainbox::manifest'])
def _parse_submission(self, submission, tmpdir, mode="list"): try: with tarfile.open(submission) as tar: tar.extractall(tmpdir.name) with open(os.path.join(tmpdir.name, 'submission.json')) as f: data = json.load(f) for result in data['results']: result['plugin'] = 'shell' # Required so default to shell result['summary'] = result['name'] # 'id' field in json file only contains partial id result['id'] = result.get('full_id', result['id']) if "::" not in result['id']: result['id'] = CERTIFICATION_NS + result['id'] if mode == "list": self.job_list.append(JobDefinition(result)) elif mode == "dict": self.job_dict[result['id']] = JobDefinition(result) for result in data['resource-results']: result['plugin'] = 'resource' result['summary'] = result['name'] # 'id' field in json file only contains partial id result['id'] = result.get('full_id', result['id']) if "::" not in result['id']: result['id'] = CERTIFICATION_NS + result['id'] if mode == "list": self.job_list.append(JobDefinition(result)) elif mode == "dict": self.job_dict[result['id']] = JobDefinition(result) for result in data['attachment-results']: result['plugin'] = 'attachment' result['summary'] = result['name'] # 'id' field in json file only contains partial id result['id'] = result.get('full_id', result['id']) if "::" not in result['id']: result['id'] = CERTIFICATION_NS + result['id'] if mode == "list": self.job_list.append(JobDefinition(result)) elif mode == "dict": self.job_dict[result['id']] = JobDefinition(result) for cat_id, cat_name in data['category_map'].items(): if mode == "list": self.category_list.append( CategoryUnit({ 'id': cat_id, 'name': cat_name })) elif mode == "dict": self.category_dict[cat_id] = CategoryUnit({ 'id': cat_id, 'name': cat_name }) except OSError as e: raise SystemExit(e) except KeyError as e: self._output_potential_action(str(e)) raise SystemExit(e) return data['title']
def _make_cert_attachments(self): state = self.manager.default_device_context.state partial_id_list = [ 'dmi_attachment', 'sysfs_attachment', 'udev_attachment' ] for partial_id in partial_id_list: job = JobDefinition({ 'id': CERTIFICATION_NS + partial_id, 'plugin': 'attachment' }) result = JobResultBuilder(io_log=[( 0, 'stdout', 'STDOUT-{}\n'.format(partial_id).encode('utf-8') ), (1, 'stderr', 'STDERR-{}\n'.format(partial_id).encode('utf-8') )]).get_result() state.add_unit(job) state.update_job_result(job, result)
def test_estimated_duration(self): self.assertEqual(JobDefinition({}).estimated_duration, None) self.assertEqual(JobDefinition( {'estimated_duration': 'foo'}).estimated_duration, None) self.assertEqual(JobDefinition( {'estimated_duration': '123.5'}).estimated_duration, 123.5) self.assertEqual(JobDefinition( {'estimated_duration': '5s'}).estimated_duration, 5) self.assertEqual(JobDefinition( {'estimated_duration': '1m 5s'}).estimated_duration, 65) self.assertEqual(JobDefinition( {'estimated_duration': '1h 1m 5s'}).estimated_duration, 3665) self.assertEqual(JobDefinition( {'estimated_duration': '1h'}).estimated_duration, 3600) self.assertEqual(JobDefinition( {'estimated_duration': '2m'}).estimated_duration, 120) self.assertEqual(JobDefinition( {'estimated_duration': '1h 1s'}).estimated_duration, 3601) self.assertEqual(JobDefinition( {'estimated_duration': '1m:5s'}).estimated_duration, 65) self.assertEqual(JobDefinition( {'estimated_duration': '1h:1m:5s'}).estimated_duration, 3665) self.assertEqual(JobDefinition( {'estimated_duration': '1h:1s'}).estimated_duration, 3601)