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 dump_from_session_manager(self, manager, stream): """ Extract data from session manager and dump it into the stream. :param session_manager: SessionManager instance that manages session to be exported by this exporter :param stream: Byte stream to write to. """ preset = None mem_bytes = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES') mem_mib = mem_bytes / (1024.**2) # On systems with less than 1GiB of RAM, create the submission tarball # without any compression level (i.e preset=0). # See https://docs.python.org/3/library/lzma.html # With preset 9 for example, the overhead for an LZMACompressor object # can be as high as 800 MiB. if mem_mib < 1200: preset = 0 job_state_map = manager.default_device_context.state.job_state_map with tarfile.TarFile.open(None, 'w:xz', stream, preset=preset) as tar: for fmt in ('html', 'json', 'junit'): unit = self._get_all_exporter_units()[ 'com.canonical.plainbox::{}'.format(fmt)] exporter = Jinja2SessionStateExporter(exporter_unit=unit) with SpooledTemporaryFile(max_size=102400, mode='w+b') as _s: exporter.dump_from_session_manager(manager, _s) tarinfo = tarfile.TarInfo(name="submission.{}".format(fmt)) tarinfo.size = _s.tell() tarinfo.mtime = time.time() _s.seek(0) # Need to rewind the file, puagh tar.addfile(tarinfo, _s) for job_id in manager.default_device_context.state.job_state_map: job_state = job_state_map[job_id] try: recordname = job_state.result.io_log_filename except AttributeError: continue for stdstream in ('stdout', 'stderr'): filename = recordname.replace('record.gz', stdstream) folder = 'test_output' if job_state.job.plugin == 'attachment': folder = 'attachment_files' if os.path.exists(filename) and os.path.getsize(filename): arcname = os.path.basename(filename) if stdstream == 'stdout': arcname = os.path.splitext(arcname)[0] tar.add(filename, os.path.join(folder, arcname), recursive=False)
def test_validation_json(self): template_filename = 'template.json' with TemporaryDirectory() as tmp: tmpl = '{"valid": "json"}' pathname = os.path.join(tmp, template_filename) with open(pathname, 'w') as f: f.write(tmpl) data = {"template": template_filename, "extra_paths": [tmp]} exporter_unit = mock.Mock(spec=ExporterUnitSupport, data=data) exporter_unit.file_extension = 'json' exporter_unit.data_dir = tmp exporter_unit.template = template_filename exporter = Jinja2SessionStateExporter(exporter_unit=exporter_unit) stream = BytesIO() exporter.dump_from_session_manager(self.manager_single_job, stream)
def test_validation_chooses_json(self): template_filename = 'template.json' with TemporaryDirectory() as tmp: tmpl = '{}' pathname = os.path.join(tmp, template_filename) with open(pathname, 'w') as f: f.write(tmpl) data = {"template": template_filename, "extra_paths": [tmp]} exporter_unit = mock.Mock(spec=ExporterUnitSupport, data=data) exporter_unit.file_extension = 'json' exporter_unit.data_dir = tmp exporter_unit.template = template_filename exporter = Jinja2SessionStateExporter(exporter_unit=exporter_unit) exporter.validate_json = mock.Mock(return_value=[]) stream = BytesIO() exporter.validate(stream) exporter.validate_json.assert_called_once_with(stream)
def test_perfect_match_with_both_certification_status(self): """ Test that output from the exporter exactly matches known good HTML output, inlining and everything included. """ exporter = Jinja2SessionStateExporter(system_id="", timestamp="2012-12-21T12:00:00", client_version="Checkbox 1.0", exporter_unit=self.exporter_unit) stream = io.BytesIO() exporter.dump_from_session_manager( self.prepare_manager_with_both_certification_status(), stream) actual_result = stream.getvalue() # This is bytes self.assertIsInstance(actual_result, bytes) expected_result = resource_string( "plainbox", "test-data/html-exporter/with_both_certification_status.html" ) # unintuitively, resource_string returns bytes self.assertEqual(actual_result, expected_result)
def test_template(self): with TemporaryDirectory() as tmp: template_filename = 'template.html' pathname = os.path.join(tmp, template_filename) tmpl = dedent( "{% for job in manager.state.job_state_map %}" "{{'{:^15}: {}'.format(" "manager.state.job_state_map[job].result.tr_outcome()," "manager.state.job_state_map[job].job.tr_summary()) }}\n" "{% endfor %}") data = {"template": template_filename, "extra_paths": [tmp]} exporter_unit = mock.Mock(spec_set=ExporterUnitSupport, data=data) exporter_unit.data_dir = tmp exporter_unit.template = template_filename with open(pathname, 'w') as f: f.write(tmpl) exporter = Jinja2SessionStateExporter(exporter_unit=exporter_unit) stream = BytesIO() exporter.dump_from_session_manager(self.manager_single_job, stream) expected_bytes = ' fail : job name\n'.encode('UTF-8') self.assertEqual(stream.getvalue(), expected_bytes)
def dump_from_session_manager(self, manager, stream): """ Extract data from session manager and dump it into the stream. :param session_manager: SessionManager instance that manages session to be exported by this exporter :param stream: Byte stream to write to. """ html_stream = io.BytesIO() options_list = [ SessionStateExporterBase.OPTION_WITH_COMMENTS, SessionStateExporterBase.OPTION_WITH_IO_LOG, SessionStateExporterBase.OPTION_FLATTEN_IO_LOG, SessionStateExporterBase.OPTION_WITH_JOB_DEFS, SessionStateExporterBase.OPTION_WITH_RESOURCE_MAP, SessionStateExporterBase.OPTION_WITH_CATEGORY_MAP, SessionStateExporterBase.OPTION_WITH_CERTIFICATION_STATUS ] exporter_unit = self._get_all_exporter_units( )['com.canonical.plainbox::html'] html_exporter = Jinja2SessionStateExporter(exporter_unit=exporter_unit) html_exporter.dump_from_session_manager(manager, html_stream) html_tarinfo = tarfile.TarInfo(name="submission.html") html_tarinfo.size = html_stream.tell() html_tarinfo.mtime = time.time() html_stream.seek(0) # Need to rewind the file, puagh json_stream = io.BytesIO() options_list = [ SessionStateExporterBase.OPTION_WITH_COMMENTS, SessionStateExporterBase.OPTION_WITH_IO_LOG, SessionStateExporterBase.OPTION_FLATTEN_IO_LOG, SessionStateExporterBase.OPTION_WITH_JOB_DEFS, SessionStateExporterBase.OPTION_WITH_RESOURCE_MAP, SessionStateExporterBase.OPTION_WITH_CATEGORY_MAP, SessionStateExporterBase.OPTION_WITH_CERTIFICATION_STATUS ] exporter_unit = self._get_all_exporter_units( )['com.canonical.plainbox::json'] json_exporter = Jinja2SessionStateExporter(exporter_unit=exporter_unit) json_exporter.dump_from_session_manager(manager, json_stream) json_tarinfo = tarfile.TarInfo(name="submission.json") json_tarinfo.size = json_stream.tell() json_tarinfo.mtime = time.time() json_stream.seek(0) # Need to rewind the file, puagh xlsx_stream = io.BytesIO() options_list = [ XLSXSessionStateExporter.OPTION_WITH_SYSTEM_INFO, XLSXSessionStateExporter.OPTION_WITH_SUMMARY, XLSXSessionStateExporter.OPTION_WITH_DESCRIPTION, XLSXSessionStateExporter.OPTION_WITH_TEXT_ATTACHMENTS, ] xlsx_exporter = XLSXSessionStateExporter(options_list) xlsx_exporter.dump_from_session_manager(manager, xlsx_stream) xlsx_tarinfo = tarfile.TarInfo(name="submission.xlsx") xlsx_tarinfo.size = xlsx_stream.tell() xlsx_tarinfo.mtime = time.time() xlsx_stream.seek(0) # Need to rewind the file, puagh job_state_map = manager.default_device_context.state.job_state_map with tarfile.TarFile.open(None, 'w|xz', stream) as tar: tar.addfile(html_tarinfo, html_stream) tar.addfile(json_tarinfo, json_stream) tar.addfile(xlsx_tarinfo, xlsx_stream) for job_id in manager.default_device_context.state.job_state_map: job_state = job_state_map[job_id] try: recordname = job_state.result.io_log_filename except AttributeError: continue for stdstream in ('stdout', 'stderr'): filename = recordname.replace('record.gz', stdstream) folder = 'test_output' if job_state.job.plugin == 'attachment': folder = 'attachment_files' if os.path.exists(filename) and os.path.getsize(filename): arcname = os.path.basename(filename) if stdstream == 'stdout': arcname = os.path.splitext(arcname)[0] tar.add(filename, os.path.join(folder, arcname), recursive=False)