1# Copyright (c) 2008-2011 testtools developers. See LICENSE for details. 2 3import os 4import tempfile 5import unittest 6 7from testtools import TestCase 8from testtools.compat import ( 9 _b, 10 _u, 11 StringIO, 12 ) 13from testtools.content import ( 14 attach_file, 15 Content, 16 content_from_file, 17 content_from_stream, 18 TracebackContent, 19 text_content, 20 ) 21from testtools.content_type import ( 22 ContentType, 23 UTF8_TEXT, 24 ) 25from testtools.matchers import ( 26 Equals, 27 MatchesException, 28 Raises, 29 raises, 30 ) 31from testtools.tests.helpers import an_exc_info 32 33 34raises_value_error = Raises(MatchesException(ValueError)) 35 36 37class TestContent(TestCase): 38 39 def test___init___None_errors(self): 40 self.assertThat(lambda: Content(None, None), raises_value_error) 41 self.assertThat( 42 lambda: Content(None, lambda: ["traceback"]), raises_value_error) 43 self.assertThat( 44 lambda: Content(ContentType("text", "traceback"), None), 45 raises_value_error) 46 47 def test___init___sets_ivars(self): 48 content_type = ContentType("foo", "bar") 49 content = Content(content_type, lambda: ["bytes"]) 50 self.assertEqual(content_type, content.content_type) 51 self.assertEqual(["bytes"], list(content.iter_bytes())) 52 53 def test___eq__(self): 54 content_type = ContentType("foo", "bar") 55 one_chunk = lambda: [_b("bytes")] 56 two_chunk = lambda: [_b("by"), _b("tes")] 57 content1 = Content(content_type, one_chunk) 58 content2 = Content(content_type, one_chunk) 59 content3 = Content(content_type, two_chunk) 60 content4 = Content(content_type, lambda: [_b("by"), _b("te")]) 61 content5 = Content(ContentType("f", "b"), two_chunk) 62 self.assertEqual(content1, content2) 63 self.assertEqual(content1, content3) 64 self.assertNotEqual(content1, content4) 65 self.assertNotEqual(content1, content5) 66 67 def test___repr__(self): 68 content = Content(ContentType("application", "octet-stream"), 69 lambda: [_b("\x00bin"), _b("ary\xff")]) 70 self.assertIn("\\x00binary\\xff", repr(content)) 71 72 def test_iter_text_not_text_errors(self): 73 content_type = ContentType("foo", "bar") 74 content = Content(content_type, lambda: ["bytes"]) 75 self.assertThat(content.iter_text, raises_value_error) 76 77 def test_iter_text_decodes(self): 78 content_type = ContentType("text", "strange", {"charset": "utf8"}) 79 content = Content( 80 content_type, lambda: [_u("bytes\xea").encode("utf8")]) 81 self.assertEqual([_u("bytes\xea")], list(content.iter_text())) 82 83 def test_iter_text_default_charset_iso_8859_1(self): 84 content_type = ContentType("text", "strange") 85 text = _u("bytes\xea") 86 iso_version = text.encode("ISO-8859-1") 87 content = Content(content_type, lambda: [iso_version]) 88 self.assertEqual([text], list(content.iter_text())) 89 90 def test_from_file(self): 91 fd, path = tempfile.mkstemp() 92 self.addCleanup(os.remove, path) 93 os.write(fd, 'some data') 94 os.close(fd) 95 content = content_from_file(path, UTF8_TEXT, chunk_size=2) 96 self.assertThat( 97 list(content.iter_bytes()), Equals(['so', 'me', ' d', 'at', 'a'])) 98 99 def test_from_nonexistent_file(self): 100 directory = tempfile.mkdtemp() 101 nonexistent = os.path.join(directory, 'nonexistent-file') 102 content = content_from_file(nonexistent) 103 self.assertThat(content.iter_bytes, raises(IOError)) 104 105 def test_from_file_default_type(self): 106 content = content_from_file('/nonexistent/path') 107 self.assertThat(content.content_type, Equals(UTF8_TEXT)) 108 109 def test_from_file_eager_loading(self): 110 fd, path = tempfile.mkstemp() 111 os.write(fd, 'some data') 112 os.close(fd) 113 content = content_from_file(path, UTF8_TEXT, buffer_now=True) 114 os.remove(path) 115 self.assertThat( 116 _b('').join(content.iter_bytes()), Equals('some data')) 117 118 def test_from_stream(self): 119 data = StringIO('some data') 120 content = content_from_stream(data, UTF8_TEXT, chunk_size=2) 121 self.assertThat( 122 list(content.iter_bytes()), Equals(['so', 'me', ' d', 'at', 'a'])) 123 124 def test_from_stream_default_type(self): 125 data = StringIO('some data') 126 content = content_from_stream(data) 127 self.assertThat(content.content_type, Equals(UTF8_TEXT)) 128 129 def test_from_stream_eager_loading(self): 130 fd, path = tempfile.mkstemp() 131 self.addCleanup(os.remove, path) 132 os.write(fd, 'some data') 133 stream = open(path, 'rb') 134 content = content_from_stream(stream, UTF8_TEXT, buffer_now=True) 135 os.write(fd, 'more data') 136 os.close(fd) 137 self.assertThat( 138 _b('').join(content.iter_bytes()), Equals('some data')) 139 140 def test_from_text(self): 141 data = _u("some data") 142 expected = Content(UTF8_TEXT, lambda: [data.encode('utf8')]) 143 self.assertEqual(expected, text_content(data)) 144 145 146class TestTracebackContent(TestCase): 147 148 def test___init___None_errors(self): 149 self.assertThat( 150 lambda: TracebackContent(None, None), raises_value_error) 151 152 def test___init___sets_ivars(self): 153 content = TracebackContent(an_exc_info, self) 154 content_type = ContentType("text", "x-traceback", 155 {"language": "python", "charset": "utf8"}) 156 self.assertEqual(content_type, content.content_type) 157 result = unittest.TestResult() 158 expected = result._exc_info_to_string(an_exc_info, self) 159 self.assertEqual(expected, ''.join(list(content.iter_text()))) 160 161 162class TestAttachFile(TestCase): 163 164 def make_file(self, data): 165 fd, path = tempfile.mkstemp() 166 self.addCleanup(os.remove, path) 167 os.write(fd, data) 168 os.close(fd) 169 return path 170 171 def test_simple(self): 172 class SomeTest(TestCase): 173 def test_foo(self): 174 pass 175 test = SomeTest('test_foo') 176 data = 'some data' 177 path = self.make_file(data) 178 my_content = text_content(data) 179 attach_file(test, path, name='foo') 180 self.assertEqual({'foo': my_content}, test.getDetails()) 181 182 def test_optional_name(self): 183 # If no name is provided, attach_file just uses the base name of the 184 # file. 185 class SomeTest(TestCase): 186 def test_foo(self): 187 pass 188 test = SomeTest('test_foo') 189 path = self.make_file('some data') 190 base_path = os.path.basename(path) 191 attach_file(test, path) 192 self.assertEqual([base_path], list(test.getDetails())) 193 194 def test_lazy_read(self): 195 class SomeTest(TestCase): 196 def test_foo(self): 197 pass 198 test = SomeTest('test_foo') 199 path = self.make_file('some data') 200 attach_file(test, path, name='foo', buffer_now=False) 201 content = test.getDetails()['foo'] 202 content_file = open(path, 'w') 203 content_file.write('new data') 204 content_file.close() 205 self.assertEqual(''.join(content.iter_bytes()), 'new data') 206 207 def test_eager_read_by_default(self): 208 class SomeTest(TestCase): 209 def test_foo(self): 210 pass 211 test = SomeTest('test_foo') 212 path = self.make_file('some data') 213 attach_file(test, path, name='foo') 214 content = test.getDetails()['foo'] 215 content_file = open(path, 'w') 216 content_file.write('new data') 217 content_file.close() 218 self.assertEqual(''.join(content.iter_bytes()), 'some data') 219 220 221def test_suite(): 222 from unittest import TestLoader 223 return TestLoader().loadTestsFromName(__name__) 224