• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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        self._test(b'dmk', b'vi', [errors.InvalidBase64PaddingDefect])
37
38    def test_invalid_character(self):
39        self._test(b'dm\x01k===', b'vi', [errors.InvalidBase64CharactersDefect])
40
41    def test_invalid_character_and_bad_padding(self):
42        self._test(b'dm\x01k', b'vi', [errors.InvalidBase64CharactersDefect,
43                                       errors.InvalidBase64PaddingDefect])
44
45
46class TestDecode(TestEmailBase):
47
48    def test_wrong_format_input_raises(self):
49        with self.assertRaises(ValueError):
50            _ew.decode('=?badone?=')
51        with self.assertRaises(ValueError):
52            _ew.decode('=?')
53        with self.assertRaises(ValueError):
54            _ew.decode('')
55
56    def _test(self, source, result, charset='us-ascii', lang='', defects=[]):
57        res, char, l, d = _ew.decode(source)
58        self.assertEqual(res, result)
59        self.assertEqual(char, charset)
60        self.assertEqual(l, lang)
61        self.assertDefectsEqual(d, defects)
62
63    def test_simple_q(self):
64        self._test('=?us-ascii?q?foo?=', 'foo')
65
66    def test_simple_b(self):
67        self._test('=?us-ascii?b?dmk=?=', 'vi')
68
69    def test_q_case_ignored(self):
70        self._test('=?us-ascii?Q?foo?=', 'foo')
71
72    def test_b_case_ignored(self):
73        self._test('=?us-ascii?B?dmk=?=', 'vi')
74
75    def test_non_trivial_q(self):
76        self._test('=?latin-1?q?=20F=fcr=20Elise=20?=', ' Für Elise ', 'latin-1')
77
78    def test_q_escaped_bytes_preserved(self):
79        self._test(b'=?us-ascii?q?=20\xACfoo?='.decode('us-ascii',
80                                                       'surrogateescape'),
81                   ' \uDCACfoo',
82                   defects = [errors.UndecodableBytesDefect])
83
84    def test_b_undecodable_bytes_ignored_with_defect(self):
85        self._test(b'=?us-ascii?b?dm\xACk?='.decode('us-ascii',
86                                                   'surrogateescape'),
87                   'vi',
88                   defects = [
89                    errors.InvalidBase64CharactersDefect,
90                    errors.InvalidBase64PaddingDefect])
91
92    def test_b_invalid_bytes_ignored_with_defect(self):
93        self._test('=?us-ascii?b?dm\x01k===?=',
94                   'vi',
95                   defects = [errors.InvalidBase64CharactersDefect])
96
97    def test_b_invalid_bytes_incorrect_padding(self):
98        self._test('=?us-ascii?b?dm\x01k?=',
99                   'vi',
100                   defects = [
101                    errors.InvalidBase64CharactersDefect,
102                    errors.InvalidBase64PaddingDefect])
103
104    def test_b_padding_defect(self):
105        self._test('=?us-ascii?b?dmk?=',
106                   'vi',
107                    defects = [errors.InvalidBase64PaddingDefect])
108
109    def test_nonnull_lang(self):
110        self._test('=?us-ascii*jive?q?test?=', 'test', lang='jive')
111
112    def test_unknown_8bit_charset(self):
113        self._test('=?unknown-8bit?q?foo=ACbar?=',
114                   b'foo\xacbar'.decode('ascii', 'surrogateescape'),
115                   charset = 'unknown-8bit',
116                   defects = [])
117
118    def test_unknown_charset(self):
119        self._test('=?foobar?q?foo=ACbar?=',
120                   b'foo\xacbar'.decode('ascii', 'surrogateescape'),
121                   charset = 'foobar',
122                   # XXX Should this be a new Defect instead?
123                   defects = [errors.CharsetError])
124
125    def test_q_nonascii(self):
126        self._test('=?utf-8?q?=C3=89ric?=',
127                   'Éric',
128                   charset='utf-8')
129
130
131class TestEncodeQ(TestEmailBase):
132
133    def _test(self, src, expected):
134        self.assertEqual(_ew.encode_q(src), expected)
135
136    def test_all_safe(self):
137        self._test(b'foobar', 'foobar')
138
139    def test_spaces(self):
140        self._test(b'foo bar ', 'foo_bar_')
141
142    def test_run_of_encodables(self):
143        self._test(b'foo  ,,bar', 'foo__=2C=2Cbar')
144
145
146class TestEncodeB(TestEmailBase):
147
148    def test_simple(self):
149        self.assertEqual(_ew.encode_b(b'foo'), 'Zm9v')
150
151    def test_padding(self):
152        self.assertEqual(_ew.encode_b(b'vi'), 'dmk=')
153
154
155class TestEncode(TestEmailBase):
156
157    def test_q(self):
158        self.assertEqual(_ew.encode('foo', 'utf-8', 'q'), '=?utf-8?q?foo?=')
159
160    def test_b(self):
161        self.assertEqual(_ew.encode('foo', 'utf-8', 'b'), '=?utf-8?b?Zm9v?=')
162
163    def test_auto_q(self):
164        self.assertEqual(_ew.encode('foo', 'utf-8'), '=?utf-8?q?foo?=')
165
166    def test_auto_q_if_short_mostly_safe(self):
167        self.assertEqual(_ew.encode('vi.', 'utf-8'), '=?utf-8?q?vi=2E?=')
168
169    def test_auto_b_if_enough_unsafe(self):
170        self.assertEqual(_ew.encode('.....', 'utf-8'), '=?utf-8?b?Li4uLi4=?=')
171
172    def test_auto_b_if_long_unsafe(self):
173        self.assertEqual(_ew.encode('vi.vi.vi.vi.vi.', 'utf-8'),
174                         '=?utf-8?b?dmkudmkudmkudmkudmku?=')
175
176    def test_auto_q_if_long_mostly_safe(self):
177        self.assertEqual(_ew.encode('vi vi vi.vi ', 'utf-8'),
178                         '=?utf-8?q?vi_vi_vi=2Evi_?=')
179
180    def test_utf8_default(self):
181        self.assertEqual(_ew.encode('foo'), '=?utf-8?q?foo?=')
182
183    def test_lang(self):
184        self.assertEqual(_ew.encode('foo', lang='jive'), '=?utf-8*jive?q?foo?=')
185
186    def test_unknown_8bit(self):
187        self.assertEqual(_ew.encode('foo\uDCACbar', charset='unknown-8bit'),
188                         '=?unknown-8bit?q?foo=ACbar?=')
189
190
191if __name__ == '__main__':
192    unittest.main()
193