def add_logs(): self.addDetail('daemon_log', content.Content( content.UTF8_TEXT, lambda: [daemon_log.getvalue()])) self.addDetail('client_log', content.Content( content.UTF8_TEXT, lambda: [client_log.getvalue().encode('utf-8')]))
def start_service_subprocess(self): # Make sure this plugin is exposed to the subprocess # SLOOWWW (~2 seconds, which is why we are doing the work anyway) fd, tempname = tempfile.mkstemp(prefix='tmp-log-bzr-lp-forking-') # I'm not 100% sure about when cleanup runs versus addDetail, but I # think this will work. self.addCleanup(os.remove, tempname) def read_log(): f = os.fdopen(fd) f.seek(0) content = f.read() f.close() return [content] self.addDetail('server-log', content.Content( content.ContentType('text', 'plain', {"charset": "utf8"}), read_log)) service_fd, path = tempfile.mkstemp(prefix='tmp-lp-service-', suffix='.sock') os.close(service_fd) # The service wants to create this file as a socket. os.remove(path) env_changes = { 'BZR_PLUGIN_PATH': lpserve.__path__[0], 'BZR_LOG': tempname, } proc = self._start_subprocess(path, env_changes) return proc, path
def setUp(self): fixtures.Fixture.setUp(self) self.addCleanup(delattr, self, 'content') self.content = [_b('content available until cleanUp')] self.addDetail( 'content', content.Content(content_type.UTF8_TEXT, self.get_content))
def test_foo(self): self.useFixture(fixture) # Add a colliding detail (both should show up) self.addDetail( 'content', content.Content(content_type.UTF8_TEXT, lambda: [_b('foo')]))
def test_get_details_success(self): parser = pysubunit.details.SimpleDetailsParser(None) expected = {} expected['message'] = content.Content( content_type.ContentType("text", "plain"), lambda: [compat._b("")]) found = parser.get_details("success") self.assertEqual(expected, found)
def get_details(self, style=None): result = {} if not style: # We know that subunit/testtools serialise [] formatted # tracebacks as utf8, but perhaps we need a ReplacingContent # or something like that. result['traceback'] = content.Content( content_type.ContentType("text", "x-traceback", {"charset": "utf8"}), lambda: [self._message]) else: if style == 'skip': name = 'reason' else: name = 'message' result[name] = content.Content( content_type.ContentType("text", "plain"), lambda: [self._message]) return result
def _feed_chunks(self, line): residue = self._chunk_parser.write(line) if residue is not None: # Line based use always ends on no residue. assert residue == '', 'residue: %r' % (residue, ) body = self._body self._details[self._name] = content.Content( self._content_type, lambda: [body.getvalue()]) self._chunk_parser.close() self._parse_state = self._look_for_content
def setUp(self): super(EtcdTestEnvironment, self).setUp() self.curl_log = [] self.addDetail( 'etcd-curl', content.Content( content_type.UTF8_TEXT, self._get_curl_calls, ), ) self.addCleanup(self.curl_delete, '/', skip_namespace=True)
def _exc_info_to_details(self, exc_info): """Translate 'exc_info' into a details dictionary usable with subunit. """ # In an ideal world, we'd use the pre-bundled 'TracebackContent' class # from testtools. However, 'OutputFormatter' contains special logic to # handle errors from doctests, so we have to use that and manually # create an object equivalent to an instance of 'TracebackContent'. formatter = OutputFormatter(None) traceback = formatter.format_traceback(exc_info) return { 'traceback': content.Content(self.TRACEBACK_CONTENT_TYPE, lambda: [traceback.encode('utf8')]) }
def _copy_content(content_object): """Make a copy of the given content object. The content within ``content_object`` is iterated and saved. This is useful when the source of the content is volatile, a log file in a temporary directory for example. :param content_object: A `content.Content` instance. :return: A `content.Content` instance with the same mime-type as ``content_object`` and a non-volatile copy of its content. """ content_bytes = list(content_object.iter_bytes()) content_callback = lambda: content_bytes return content.Content(content_object.content_type, content_callback)
def test_get_details(self): parser = pysubunit.details.SimpleDetailsParser(None) expected = {} expected['traceback'] = content.Content( content_type.ContentType("text", "x-traceback", {'charset': 'utf8'}), lambda: [compat._b("")]) found = parser.get_details() self.assertEqual(expected.keys(), found.keys()) self.assertEqual(expected['traceback'].content_type, found['traceback'].content_type) self.assertEqual( compat._b('').join(expected['traceback'].iter_bytes()), compat._b('').join(found['traceback'].iter_bytes()))
def _gather_details(self, getDetails): """Merge the details from getDetails() into self.getDetails().""" details = getDetails() my_details = self.getDetails() for name, content_object in details.items(): new_name = name disambiguator = itertools.count(1) while new_name in my_details: new_name = '%s-%d' % (name, advance_iterator(disambiguator)) name = new_name content_bytes = list(content_object.iter_bytes()) content_callback = lambda:content_bytes self.addDetail(name, content.Content(content_object.content_type, content_callback))
def test_parts(self): parser = pysubunit.details.MultipartDetailsParser(None) parser.lineReceived(compat._b("Content-Type: text/plain\n")) parser.lineReceived(compat._b("something\n")) parser.lineReceived(compat._b("F\r\n")) parser.lineReceived(compat._b("serialised\n")) parser.lineReceived(compat._b("form0\r\n")) expected = {} expected['something'] = content.Content( content_type.ContentType("text", "plain"), lambda: [compat._b("serialised\nform")]) found = parser.get_details() self.assertEqual(expected.keys(), found.keys()) self.assertEqual(expected['something'].content_type, found['something'].content_type) self.assertEqual( compat._b('').join(expected['something'].iter_bytes()), compat._b('').join(found['something'].iter_bytes()))
def details_content(content_id, content_type=None, get_bytes=None, get_text=None, get_json=None, get_yaml=None): content_type = content_type or content.UTF8_TEXT if get_bytes is None: if get_text: get_bytes = get_text_to_get_bytes(get_text=get_text) elif get_json: get_bytes = get_json_to_get_bytes(get_json=get_json) elif get_yaml: get_bytes = get_yaml_to_get_bytes(get_yaml=get_yaml) else: message = ("Any of get_bytes, get_text or get_json parameters has " "been specified") raise ValueError(message) content_object = content.Content(content_type=content_type, get_bytes=get_bytes) content_object.content_id = content_id return content_object
def check_forbidden_modules(self, err, forbidden_imports): """Check for forbidden modules in stderr. :param err: Standard error :param forbidden_imports: List of forbidden modules """ self.addDetail('subprocess_stderr', content.Content(content.ContentType("text", "plain"), lambda:[err])) bad_modules = [] for module_name in forbidden_imports: if err.find("\nimport %s " % module_name) != -1: bad_modules.append(module_name) if bad_modules: self.fail("command loaded forbidden modules %r" % (bad_modules,))
def profiler_stats(self, stats): """Report profiler stats.""" fd, filename = tempfile.mkstemp() os.close(fd) try: stats.dump_stats(filename) stats_dump = open(filename) try: profile_content = content.Content( self.PROFILE_CONTENT_TYPE, stats_dump.read) details = {'profiler-stats': profile_content} # Name the test 'zope:profiler_stats' just like its tag. self._emit_fake_test( self.TAG_PROFILER_STATS, self.TAG_PROFILER_STATS, details) finally: stats_dump.close() finally: os.unlink(filename)
def addSuccess(self, test, details=None): test = self._add_prefix(test) xfail_reason = find_in_list(self.expected_failures, test.id()) if xfail_reason is not None: self.uxsuccess_added += 1 self.total_uxsuccess += 1 if details is None: details = {} details['reason'] = content.Content( content_type.ContentType("text", "plain", {"charset": "utf8"}), lambda: xfail_reason) self._ops.addUnexpectedSuccess(test, details) if self.output: self._ops.output_msg(self.output) if self.fail_immediately: raise ImmediateFail() else: self._ops.addSuccess(test, details) self.output = None
def _exc_info_to_details(self, exc_info): """Translate 'exc_info' into a details dictionary usable with subunit. """ # In an ideal world, we'd use the pre-bundled 'TracebackContent' class # from testtools. However, 'OutputFormatter' contains special logic to # handle errors from doctests, so we have to use that and manually # create an object equivalent to an instance of 'TracebackContent'. formatter = OutputFormatter(None) traceback = formatter.format_traceback(exc_info) # We have no idea if the traceback is a unicode object or a bytestring # with non-ASCII characters. We had best be careful when handling it. if isinstance(traceback, unicode): unicode_tb = traceback else: # Assume the traceback was utf-8 encoded, but still be careful. unicode_tb = traceback.decode('utf8', 'replace') return { 'traceback': content.Content( self.TRACEBACK_CONTENT_TYPE, lambda: [unicode_tb.encode('utf8')])}
def get_content(self): return content.Content( content.ContentType("text", "foo"), lambda: ['foo'])
def test_foo(self): self.addDetail( 'foo', content.Content('text/plain', lambda: 'foo'))
def _add_reason(self, reason): self.addDetail('reason', content.Content( content.ContentType('text', 'plain'), lambda: [reason.encode('utf8')]))
def _get_text_details(self, name, text): """Get a details dictionary that just has some plain text.""" return { name: content.Content( self.PLAIN_TEXT, lambda: [text.encode('utf8')])}