1import unittest 2from email import _encoded_words as _ew 3from email import errors 4from test.test_email import TestEmailBase 5 6 7class TestDecodeQ(TestEmailBase): 8 9 def _test(self, source, ex_result, ex_defects=[]): 10 result, defects = _ew.decode_q(source) 11 self.assertEqual(result, ex_result) 12 self.assertDefectsEqual(defects, ex_defects) 13 14 def test_no_encoded(self): 15 self._test(b'foobar', b'foobar') 16 17 def test_spaces(self): 18 self._test(b'foo=20bar=20', b'foo bar ') 19 self._test(b'foo_bar_', b'foo bar ') 20 21 def test_run_of_encoded(self): 22 self._test(b'foo=20=20=21=2Cbar', b'foo !,bar') 23 24 25class TestDecodeB(TestEmailBase): 26 27 def _test(self, source, ex_result, ex_defects=[]): 28 result, defects = _ew.decode_b(source) 29 self.assertEqual(result, ex_result) 30 self.assertDefectsEqual(defects, ex_defects) 31 32 def test_simple(self): 33 self._test(b'Zm9v', b'foo') 34 35 def test_missing_padding(self): 36 # 1 missing padding character 37 self._test(b'dmk', b'vi', [errors.InvalidBase64PaddingDefect]) 38 # 2 missing padding characters 39 self._test(b'dg', b'v', [errors.InvalidBase64PaddingDefect]) 40 41 def test_invalid_character(self): 42 self._test(b'dm\x01k===', b'vi', [errors.InvalidBase64CharactersDefect]) 43 44 def test_invalid_character_and_bad_padding(self): 45 self._test(b'dm\x01k', b'vi', [errors.InvalidBase64CharactersDefect, 46 errors.InvalidBase64PaddingDefect]) 47 48 def test_invalid_length(self): 49 self._test(b'abcde', b'abcde', [errors.InvalidBase64LengthDefect]) 50 51 52class TestDecode(TestEmailBase): 53 54 def test_wrong_format_input_raises(self): 55 with self.assertRaises(ValueError): 56 _ew.decode('=?badone?=') 57 with self.assertRaises(ValueError): 58 _ew.decode('=?') 59 with self.assertRaises(ValueError): 60 _ew.decode('') 61 with self.assertRaises(KeyError): 62 _ew.decode('=?utf-8?X?somevalue?=') 63 64 def _test(self, source, result, charset='us-ascii', lang='', defects=[]): 65 res, char, l, d = _ew.decode(source) 66 self.assertEqual(res, result) 67 self.assertEqual(char, charset) 68 self.assertEqual(l, lang) 69 self.assertDefectsEqual(d, defects) 70 71 def test_simple_q(self): 72 self._test('=?us-ascii?q?foo?=', 'foo') 73 74 def test_simple_b(self): 75 self._test('=?us-ascii?b?dmk=?=', 'vi') 76 77 def test_q_case_ignored(self): 78 self._test('=?us-ascii?Q?foo?=', 'foo') 79 80 def test_b_case_ignored(self): 81 self._test('=?us-ascii?B?dmk=?=', 'vi') 82 83 def test_non_trivial_q(self): 84 self._test('=?latin-1?q?=20F=fcr=20Elise=20?=', ' Für Elise ', 'latin-1') 85 86 def test_q_escaped_bytes_preserved(self): 87 self._test(b'=?us-ascii?q?=20\xACfoo?='.decode('us-ascii', 88 'surrogateescape'), 89 ' \uDCACfoo', 90 defects = [errors.UndecodableBytesDefect]) 91 92 def test_b_undecodable_bytes_ignored_with_defect(self): 93 self._test(b'=?us-ascii?b?dm\xACk?='.decode('us-ascii', 94 'surrogateescape'), 95 'vi', 96 defects = [ 97 errors.InvalidBase64CharactersDefect, 98 errors.InvalidBase64PaddingDefect]) 99 100 def test_b_invalid_bytes_ignored_with_defect(self): 101 self._test('=?us-ascii?b?dm\x01k===?=', 102 'vi', 103 defects = [errors.InvalidBase64CharactersDefect]) 104 105 def test_b_invalid_bytes_incorrect_padding(self): 106 self._test('=?us-ascii?b?dm\x01k?=', 107 'vi', 108 defects = [ 109 errors.InvalidBase64CharactersDefect, 110 errors.InvalidBase64PaddingDefect]) 111 112 def test_b_padding_defect(self): 113 self._test('=?us-ascii?b?dmk?=', 114 'vi', 115 defects = [errors.InvalidBase64PaddingDefect]) 116 117 def test_nonnull_lang(self): 118 self._test('=?us-ascii*jive?q?test?=', 'test', lang='jive') 119 120 def test_unknown_8bit_charset(self): 121 self._test('=?unknown-8bit?q?foo=ACbar?=', 122 b'foo\xacbar'.decode('ascii', 'surrogateescape'), 123 charset = 'unknown-8bit', 124 defects = []) 125 126 def test_unknown_charset(self): 127 self._test('=?foobar?q?foo=ACbar?=', 128 b'foo\xacbar'.decode('ascii', 'surrogateescape'), 129 charset = 'foobar', 130 # XXX Should this be a new Defect instead? 131 defects = [errors.CharsetError]) 132 133 def test_q_nonascii(self): 134 self._test('=?utf-8?q?=C3=89ric?=', 135 'Éric', 136 charset='utf-8') 137 138 139class TestEncodeQ(TestEmailBase): 140 141 def _test(self, src, expected): 142 self.assertEqual(_ew.encode_q(src), expected) 143 144 def test_all_safe(self): 145 self._test(b'foobar', 'foobar') 146 147 def test_spaces(self): 148 self._test(b'foo bar ', 'foo_bar_') 149 150 def test_run_of_encodables(self): 151 self._test(b'foo ,,bar', 'foo__=2C=2Cbar') 152 153 154class TestEncodeB(TestEmailBase): 155 156 def test_simple(self): 157 self.assertEqual(_ew.encode_b(b'foo'), 'Zm9v') 158 159 def test_padding(self): 160 self.assertEqual(_ew.encode_b(b'vi'), 'dmk=') 161 162 163class TestEncode(TestEmailBase): 164 165 def test_q(self): 166 self.assertEqual(_ew.encode('foo', 'utf-8', 'q'), '=?utf-8?q?foo?=') 167 168 def test_b(self): 169 self.assertEqual(_ew.encode('foo', 'utf-8', 'b'), '=?utf-8?b?Zm9v?=') 170 171 def test_auto_q(self): 172 self.assertEqual(_ew.encode('foo', 'utf-8'), '=?utf-8?q?foo?=') 173 174 def test_auto_q_if_short_mostly_safe(self): 175 self.assertEqual(_ew.encode('vi.', 'utf-8'), '=?utf-8?q?vi=2E?=') 176 177 def test_auto_b_if_enough_unsafe(self): 178 self.assertEqual(_ew.encode('.....', 'utf-8'), '=?utf-8?b?Li4uLi4=?=') 179 180 def test_auto_b_if_long_unsafe(self): 181 self.assertEqual(_ew.encode('vi.vi.vi.vi.vi.', 'utf-8'), 182 '=?utf-8?b?dmkudmkudmkudmkudmku?=') 183 184 def test_auto_q_if_long_mostly_safe(self): 185 self.assertEqual(_ew.encode('vi vi vi.vi ', 'utf-8'), 186 '=?utf-8?q?vi_vi_vi=2Evi_?=') 187 188 def test_utf8_default(self): 189 self.assertEqual(_ew.encode('foo'), '=?utf-8?q?foo?=') 190 191 def test_lang(self): 192 self.assertEqual(_ew.encode('foo', lang='jive'), '=?utf-8*jive?q?foo?=') 193 194 def test_unknown_8bit(self): 195 self.assertEqual(_ew.encode('foo\uDCACbar', charset='unknown-8bit'), 196 '=?unknown-8bit?q?foo=ACbar?=') 197 198 199if __name__ == '__main__': 200 unittest.main() 201