blob: 2161af1d71c522f4e55e5ee00b19b9a703ce77cd [file] [log] [blame]
R David Murray0b6f6c82012-05-25 18:42:14 -04001import string
2import unittest
3from email import _header_value_parser as parser
4from email import errors
5from email import policy
6from test.test_email import TestEmailBase
7
8class TestTokens(TestEmailBase):
9
10 # EWWhiteSpaceTerminal
11
12 def test_EWWhiteSpaceTerminal(self):
13 x = parser.EWWhiteSpaceTerminal(' \t', 'fws')
14 self.assertEqual(x, ' \t')
15 self.assertEqual(str(x), '')
16 self.assertEqual(x.value, '')
17 self.assertEqual(x.encoded, ' \t')
18
19 # UnstructuredTokenList
20
21 def test_undecodable_bytes_error_preserved(self):
22 badstr = b"le pouf c\xaflebre".decode('ascii', 'surrogateescape')
23 unst = parser.get_unstructured(badstr)
24 self.assertDefectsEqual(unst.all_defects, [errors.UndecodableBytesDefect])
25 parts = list(unst.parts)
26 self.assertDefectsEqual(parts[0].all_defects, [])
27 self.assertDefectsEqual(parts[1].all_defects, [])
28 self.assertDefectsEqual(parts[2].all_defects, [errors.UndecodableBytesDefect])
29
30
31class TestParser(TestEmailBase):
32
33 # _wsp_splitter
34
35 rfc_printable_ascii = bytes(range(33, 127)).decode('ascii')
36 rfc_atext_chars = (string.ascii_letters + string.digits +
37 "!#$%&\'*+-/=?^_`{}|~")
38 rfc_dtext_chars = rfc_printable_ascii.translate(str.maketrans('','',r'\[]'))
39
40 def test__wsp_splitter_one_word(self):
41 self.assertEqual(parser._wsp_splitter('foo', 1), ['foo'])
42
43 def test__wsp_splitter_two_words(self):
44 self.assertEqual(parser._wsp_splitter('foo def', 1),
45 ['foo', ' ', 'def'])
46
47 def test__wsp_splitter_ws_runs(self):
48 self.assertEqual(parser._wsp_splitter('foo \t def jik', 1),
49 ['foo', ' \t ', 'def jik'])
50
51
52 # test harness
53
54 def _test_get_x(self, method, input, string, value, defects,
55 remainder, comments=None):
56 token, rest = method(input)
57 self.assertEqual(str(token), string)
58 self.assertEqual(token.value, value)
59 self.assertDefectsEqual(token.all_defects, defects)
60 self.assertEqual(rest, remainder)
61 if comments is not None:
62 self.assertEqual(token.comments, comments)
63 return token
64
65 # get_fws
66
67 def test_get_fws_only(self):
68 fws = self._test_get_x(parser.get_fws, ' \t ', ' \t ', ' ', [], '')
69 self.assertEqual(fws.token_type, 'fws')
70
71 def test_get_fws_space(self):
72 self._test_get_x(parser.get_fws, ' foo', ' ', ' ', [], 'foo')
73
74 def test_get_fws_ws_run(self):
75 self._test_get_x(parser.get_fws, ' \t foo ', ' \t ', ' ', [], 'foo ')
76
77 # get_encoded_word
78
79 def test_get_encoded_word_missing_start_raises(self):
80 with self.assertRaises(errors.HeaderParseError):
81 parser.get_encoded_word('abc')
82
83 def test_get_encoded_word_missing_end_raises(self):
84 with self.assertRaises(errors.HeaderParseError):
85 parser.get_encoded_word('=?abc')
86
87 def test_get_encoded_word_missing_middle_raises(self):
88 with self.assertRaises(errors.HeaderParseError):
89 parser.get_encoded_word('=?abc?=')
90
91 def test_get_encoded_word_valid_ew(self):
92 self._test_get_x(parser.get_encoded_word,
93 '=?us-ascii?q?this_is_a_test?= bird',
94 'this is a test',
95 'this is a test',
96 [],
97 ' bird')
98
99 def test_get_encoded_word_internal_spaces(self):
100 self._test_get_x(parser.get_encoded_word,
101 '=?us-ascii?q?this is a test?= bird',
102 'this is a test',
103 'this is a test',
104 [errors.InvalidHeaderDefect],
105 ' bird')
106
107 def test_get_encoded_word_gets_first(self):
108 self._test_get_x(parser.get_encoded_word,
109 '=?us-ascii?q?first?= =?utf-8?q?second?=',
110 'first',
111 'first',
112 [],
113 ' =?utf-8?q?second?=')
114
115 def test_get_encoded_word_gets_first_even_if_no_space(self):
116 self._test_get_x(parser.get_encoded_word,
117 '=?us-ascii?q?first?==?utf-8?q?second?=',
118 'first',
119 'first',
120 [],
121 '=?utf-8?q?second?=')
122
123 def test_get_encoded_word_sets_extra_attributes(self):
124 ew = self._test_get_x(parser.get_encoded_word,
125 '=?us-ascii*jive?q?first_second?=',
126 'first second',
127 'first second',
128 [],
129 '')
130 self.assertEqual(ew.encoded, '=?us-ascii*jive?q?first_second?=')
131 self.assertEqual(ew.charset, 'us-ascii')
132 self.assertEqual(ew.lang, 'jive')
133
134 def test_get_encoded_word_lang_default_is_blank(self):
135 ew = self._test_get_x(parser.get_encoded_word,
136 '=?us-ascii?q?first_second?=',
137 'first second',
138 'first second',
139 [],
140 '')
141 self.assertEqual(ew.encoded, '=?us-ascii?q?first_second?=')
142 self.assertEqual(ew.charset, 'us-ascii')
143 self.assertEqual(ew.lang, '')
144
145 def test_get_encoded_word_non_printable_defect(self):
146 self._test_get_x(parser.get_encoded_word,
147 '=?us-ascii?q?first\x02second?=',
148 'first\x02second',
149 'first\x02second',
150 [errors.NonPrintableDefect],
151 '')
152
153 def test_get_encoded_word_leading_internal_space(self):
154 self._test_get_x(parser.get_encoded_word,
155 '=?us-ascii?q?=20foo?=',
156 ' foo',
157 ' foo',
158 [],
159 '')
160
161 # get_unstructured
162
163 def _get_unst(self, value):
164 token = parser.get_unstructured(value)
165 return token, ''
166
167 def test_get_unstructured_null(self):
168 self._test_get_x(self._get_unst, '', '', '', [], '')
169
170 def test_get_unstructured_one_word(self):
171 self._test_get_x(self._get_unst, 'foo', 'foo', 'foo', [], '')
172
173 def test_get_unstructured_normal_phrase(self):
174 self._test_get_x(self._get_unst, 'foo bar bird',
175 'foo bar bird',
176 'foo bar bird',
177 [],
178 '')
179
180 def test_get_unstructured_normal_phrase_with_whitespace(self):
181 self._test_get_x(self._get_unst, 'foo \t bar bird',
182 'foo \t bar bird',
183 'foo bar bird',
184 [],
185 '')
186
187 def test_get_unstructured_leading_whitespace(self):
188 self._test_get_x(self._get_unst, ' foo bar',
189 ' foo bar',
190 ' foo bar',
191 [],
192 '')
193
194 def test_get_unstructured_trailing_whitespace(self):
195 self._test_get_x(self._get_unst, 'foo bar ',
196 'foo bar ',
197 'foo bar ',
198 [],
199 '')
200
201 def test_get_unstructured_leading_and_trailing_whitespace(self):
202 self._test_get_x(self._get_unst, ' foo bar ',
203 ' foo bar ',
204 ' foo bar ',
205 [],
206 '')
207
208 def test_get_unstructured_one_valid_ew_no_ws(self):
209 self._test_get_x(self._get_unst, '=?us-ascii?q?bar?=',
210 'bar',
211 'bar',
212 [],
213 '')
214
215 def test_get_unstructured_one_ew_trailing_ws(self):
216 self._test_get_x(self._get_unst, '=?us-ascii?q?bar?= ',
217 'bar ',
218 'bar ',
219 [],
220 '')
221
222 def test_get_unstructured_one_valid_ew_trailing_text(self):
223 self._test_get_x(self._get_unst, '=?us-ascii?q?bar?= bird',
224 'bar bird',
225 'bar bird',
226 [],
227 '')
228
229 def test_get_unstructured_phrase_with_ew_in_middle_of_text(self):
230 self._test_get_x(self._get_unst, 'foo =?us-ascii?q?bar?= bird',
231 'foo bar bird',
232 'foo bar bird',
233 [],
234 '')
235
236 def test_get_unstructured_phrase_with_two_ew(self):
237 self._test_get_x(self._get_unst,
238 'foo =?us-ascii?q?bar?= =?us-ascii?q?bird?=',
239 'foo barbird',
240 'foo barbird',
241 [],
242 '')
243
244 def test_get_unstructured_phrase_with_two_ew_trailing_ws(self):
245 self._test_get_x(self._get_unst,
246 'foo =?us-ascii?q?bar?= =?us-ascii?q?bird?= ',
247 'foo barbird ',
248 'foo barbird ',
249 [],
250 '')
251
252 def test_get_unstructured_phrase_with_ew_with_leading_ws(self):
253 self._test_get_x(self._get_unst,
254 ' =?us-ascii?q?bar?=',
255 ' bar',
256 ' bar',
257 [],
258 '')
259
260 def test_get_unstructured_phrase_with_two_ew_extra_ws(self):
261 self._test_get_x(self._get_unst,
262 'foo =?us-ascii?q?bar?= \t =?us-ascii?q?bird?=',
263 'foo barbird',
264 'foo barbird',
265 [],
266 '')
267
268 def test_get_unstructured_two_ew_extra_ws_trailing_text(self):
269 self._test_get_x(self._get_unst,
270 '=?us-ascii?q?test?= =?us-ascii?q?foo?= val',
271 'testfoo val',
272 'testfoo val',
273 [],
274 '')
275
276 def test_get_unstructured_ew_with_internal_ws(self):
277 self._test_get_x(self._get_unst,
278 '=?iso-8859-1?q?hello=20world?=',
279 'hello world',
280 'hello world',
281 [],
282 '')
283
284 def test_get_unstructured_ew_with_internal_leading_ws(self):
285 self._test_get_x(self._get_unst,
286 ' =?us-ascii?q?=20test?= =?us-ascii?q?=20foo?= val',
287 ' test foo val',
288 ' test foo val',
289 [],
290 '')
291
292 def test_get_unstructured_invaild_ew(self):
293 self._test_get_x(self._get_unst,
294 '=?test val',
295 '=?test val',
296 '=?test val',
297 [],
298 '')
299
300 def test_get_unstructured_undecodable_bytes(self):
301 self._test_get_x(self._get_unst,
302 b'test \xACfoo val'.decode('ascii', 'surrogateescape'),
303 'test \uDCACfoo val',
304 'test \uDCACfoo val',
305 [errors.UndecodableBytesDefect],
306 '')
307
308 def test_get_unstructured_undecodable_bytes_in_EW(self):
309 self._test_get_x(self._get_unst,
310 (b'=?us-ascii?q?=20test?= =?us-ascii?q?=20\xACfoo?='
311 b' val').decode('ascii', 'surrogateescape'),
312 ' test \uDCACfoo val',
313 ' test \uDCACfoo val',
314 [errors.UndecodableBytesDefect]*2,
315 '')
316
317 def test_get_unstructured_missing_base64_padding(self):
318 self._test_get_x(self._get_unst,
319 '=?utf-8?b?dmk?=',
320 'vi',
321 'vi',
322 [errors.InvalidBase64PaddingDefect],
323 '')
324
325 def test_get_unstructured_invalid_base64_character(self):
326 self._test_get_x(self._get_unst,
327 '=?utf-8?b?dm\x01k===?=',
328 'vi',
329 'vi',
330 [errors.InvalidBase64CharactersDefect],
331 '')
332
333 def test_get_unstructured_invalid_base64_character_and_bad_padding(self):
334 self._test_get_x(self._get_unst,
335 '=?utf-8?b?dm\x01k?=',
336 'vi',
337 'vi',
338 [errors.InvalidBase64CharactersDefect,
339 errors.InvalidBase64PaddingDefect],
340 '')
341
342 def test_get_unstructured_no_whitespace_between_ews(self):
343 self._test_get_x(self._get_unst,
344 '=?utf-8?q?foo?==?utf-8?q?bar?=',
345 'foobar',
346 'foobar',
347 [errors.InvalidHeaderDefect],
348 '')
349
350 # get_qp_ctext
351
352 def test_get_qp_ctext_only(self):
353 ptext = self._test_get_x(parser.get_qp_ctext,
354 'foobar', 'foobar', ' ', [], '')
355 self.assertEqual(ptext.token_type, 'ptext')
356
357 def test_get_qp_ctext_all_printables(self):
358 with_qp = self.rfc_printable_ascii.replace('\\', '\\\\')
359 with_qp = with_qp. replace('(', r'\(')
360 with_qp = with_qp.replace(')', r'\)')
361 ptext = self._test_get_x(parser.get_qp_ctext,
362 with_qp, self.rfc_printable_ascii, ' ', [], '')
363
364 def test_get_qp_ctext_two_words_gets_first(self):
365 self._test_get_x(parser.get_qp_ctext,
366 'foo de', 'foo', ' ', [], ' de')
367
368 def test_get_qp_ctext_following_wsp_preserved(self):
369 self._test_get_x(parser.get_qp_ctext,
370 'foo \t\tde', 'foo', ' ', [], ' \t\tde')
371
372 def test_get_qp_ctext_up_to_close_paren_only(self):
373 self._test_get_x(parser.get_qp_ctext,
374 'foo)', 'foo', ' ', [], ')')
375
376 def test_get_qp_ctext_wsp_before_close_paren_preserved(self):
377 self._test_get_x(parser.get_qp_ctext,
378 'foo )', 'foo', ' ', [], ' )')
379
380 def test_get_qp_ctext_close_paren_mid_word(self):
381 self._test_get_x(parser.get_qp_ctext,
382 'foo)bar', 'foo', ' ', [], ')bar')
383
384 def test_get_qp_ctext_up_to_open_paren_only(self):
385 self._test_get_x(parser.get_qp_ctext,
386 'foo(', 'foo', ' ', [], '(')
387
388 def test_get_qp_ctext_wsp_before_open_paren_preserved(self):
389 self._test_get_x(parser.get_qp_ctext,
390 'foo (', 'foo', ' ', [], ' (')
391
392 def test_get_qp_ctext_open_paren_mid_word(self):
393 self._test_get_x(parser.get_qp_ctext,
394 'foo(bar', 'foo', ' ', [], '(bar')
395
396 def test_get_qp_ctext_non_printables(self):
397 ptext = self._test_get_x(parser.get_qp_ctext,
398 'foo\x00bar)', 'foo\x00bar', ' ',
399 [errors.NonPrintableDefect], ')')
400 self.assertEqual(ptext.defects[0].non_printables[0], '\x00')
401
402 # get_qcontent
403
404 def test_get_qcontent_only(self):
405 ptext = self._test_get_x(parser.get_qcontent,
406 'foobar', 'foobar', 'foobar', [], '')
407 self.assertEqual(ptext.token_type, 'ptext')
408
409 def test_get_qcontent_all_printables(self):
410 with_qp = self.rfc_printable_ascii.replace('\\', '\\\\')
411 with_qp = with_qp. replace('"', r'\"')
412 ptext = self._test_get_x(parser.get_qcontent, with_qp,
413 self.rfc_printable_ascii,
414 self.rfc_printable_ascii, [], '')
415
416 def test_get_qcontent_two_words_gets_first(self):
417 self._test_get_x(parser.get_qcontent,
418 'foo de', 'foo', 'foo', [], ' de')
419
420 def test_get_qcontent_following_wsp_preserved(self):
421 self._test_get_x(parser.get_qcontent,
422 'foo \t\tde', 'foo', 'foo', [], ' \t\tde')
423
424 def test_get_qcontent_up_to_dquote_only(self):
425 self._test_get_x(parser.get_qcontent,
426 'foo"', 'foo', 'foo', [], '"')
427
428 def test_get_qcontent_wsp_before_close_paren_preserved(self):
429 self._test_get_x(parser.get_qcontent,
430 'foo "', 'foo', 'foo', [], ' "')
431
432 def test_get_qcontent_close_paren_mid_word(self):
433 self._test_get_x(parser.get_qcontent,
434 'foo"bar', 'foo', 'foo', [], '"bar')
435
436 def test_get_qcontent_non_printables(self):
437 ptext = self._test_get_x(parser.get_qcontent,
438 'foo\x00fg"', 'foo\x00fg', 'foo\x00fg',
439 [errors.NonPrintableDefect], '"')
440 self.assertEqual(ptext.defects[0].non_printables[0], '\x00')
441
442 # get_atext
443
444 def test_get_atext_only(self):
445 atext = self._test_get_x(parser.get_atext,
446 'foobar', 'foobar', 'foobar', [], '')
447 self.assertEqual(atext.token_type, 'atext')
448
449 def test_get_atext_all_atext(self):
450 atext = self._test_get_x(parser.get_atext, self.rfc_atext_chars,
451 self.rfc_atext_chars,
452 self.rfc_atext_chars, [], '')
453
454 def test_get_atext_two_words_gets_first(self):
455 self._test_get_x(parser.get_atext,
456 'foo bar', 'foo', 'foo', [], ' bar')
457
458 def test_get_atext_following_wsp_preserved(self):
459 self._test_get_x(parser.get_atext,
460 'foo \t\tbar', 'foo', 'foo', [], ' \t\tbar')
461
462 def test_get_atext_up_to_special(self):
463 self._test_get_x(parser.get_atext,
464 'foo@bar', 'foo', 'foo', [], '@bar')
465
466 def test_get_atext_non_printables(self):
467 atext = self._test_get_x(parser.get_atext,
468 'foo\x00bar(', 'foo\x00bar', 'foo\x00bar',
469 [errors.NonPrintableDefect], '(')
470 self.assertEqual(atext.defects[0].non_printables[0], '\x00')
471
472 # get_bare_quoted_string
473
474 def test_get_bare_quoted_string_only(self):
475 bqs = self._test_get_x(parser.get_bare_quoted_string,
476 '"foo"', '"foo"', 'foo', [], '')
477 self.assertEqual(bqs.token_type, 'bare-quoted-string')
478
479 def test_get_bare_quoted_string_must_start_with_dquote(self):
480 with self.assertRaises(errors.HeaderParseError):
481 parser.get_bare_quoted_string('foo"')
482 with self.assertRaises(errors.HeaderParseError):
483 parser.get_bare_quoted_string(' "foo"')
484
485 def test_get_bare_quoted_string_following_wsp_preserved(self):
486 self._test_get_x(parser.get_bare_quoted_string,
487 '"foo"\t bar', '"foo"', 'foo', [], '\t bar')
488
489 def test_get_bare_quoted_string_multiple_words(self):
490 self._test_get_x(parser.get_bare_quoted_string,
491 '"foo bar moo"', '"foo bar moo"', 'foo bar moo', [], '')
492
493 def test_get_bare_quoted_string_multiple_words_wsp_preserved(self):
494 self._test_get_x(parser.get_bare_quoted_string,
495 '" foo moo\t"', '" foo moo\t"', ' foo moo\t', [], '')
496
497 def test_get_bare_quoted_string_end_dquote_mid_word(self):
498 self._test_get_x(parser.get_bare_quoted_string,
499 '"foo"bar', '"foo"', 'foo', [], 'bar')
500
501 def test_get_bare_quoted_string_quoted_dquote(self):
502 self._test_get_x(parser.get_bare_quoted_string,
503 r'"foo\"in"a', r'"foo\"in"', 'foo"in', [], 'a')
504
505 def test_get_bare_quoted_string_non_printables(self):
506 self._test_get_x(parser.get_bare_quoted_string,
507 '"a\x01a"', '"a\x01a"', 'a\x01a',
508 [errors.NonPrintableDefect], '')
509
510 def test_get_bare_quoted_string_no_end_dquote(self):
511 self._test_get_x(parser.get_bare_quoted_string,
512 '"foo', '"foo"', 'foo',
513 [errors.InvalidHeaderDefect], '')
514 self._test_get_x(parser.get_bare_quoted_string,
515 '"foo ', '"foo "', 'foo ',
516 [errors.InvalidHeaderDefect], '')
517
518 def test_get_bare_quoted_string_empty_quotes(self):
519 self._test_get_x(parser.get_bare_quoted_string,
520 '""', '""', '', [], '')
521
522 # get_comment
523
524 def test_get_comment_only(self):
525 comment = self._test_get_x(parser.get_comment,
526 '(comment)', '(comment)', ' ', [], '', ['comment'])
527 self.assertEqual(comment.token_type, 'comment')
528
529 def test_get_comment_must_start_with_paren(self):
530 with self.assertRaises(errors.HeaderParseError):
531 parser.get_comment('foo"')
532 with self.assertRaises(errors.HeaderParseError):
533 parser.get_comment(' (foo"')
534
535 def test_get_comment_following_wsp_preserved(self):
536 self._test_get_x(parser.get_comment,
537 '(comment) \t', '(comment)', ' ', [], ' \t', ['comment'])
538
539 def test_get_comment_multiple_words(self):
540 self._test_get_x(parser.get_comment,
541 '(foo bar) \t', '(foo bar)', ' ', [], ' \t', ['foo bar'])
542
543 def test_get_comment_multiple_words_wsp_preserved(self):
544 self._test_get_x(parser.get_comment,
545 '( foo bar\t ) \t', '( foo bar\t )', ' ', [], ' \t',
546 [' foo bar\t '])
547
548 def test_get_comment_end_paren_mid_word(self):
549 self._test_get_x(parser.get_comment,
550 '(foo)bar', '(foo)', ' ', [], 'bar', ['foo'])
551
552 def test_get_comment_quoted_parens(self):
553 self._test_get_x(parser.get_comment,
554 '(foo\) \(\)bar)', '(foo\) \(\)bar)', ' ', [], '', ['foo) ()bar'])
555
556 def test_get_comment_non_printable(self):
557 self._test_get_x(parser.get_comment,
558 '(foo\x7Fbar)', '(foo\x7Fbar)', ' ',
559 [errors.NonPrintableDefect], '', ['foo\x7Fbar'])
560
561 def test_get_comment_no_end_paren(self):
562 self._test_get_x(parser.get_comment,
563 '(foo bar', '(foo bar)', ' ',
564 [errors.InvalidHeaderDefect], '', ['foo bar'])
565 self._test_get_x(parser.get_comment,
566 '(foo bar ', '(foo bar )', ' ',
567 [errors.InvalidHeaderDefect], '', ['foo bar '])
568
569 def test_get_comment_nested_comment(self):
570 comment = self._test_get_x(parser.get_comment,
571 '(foo(bar))', '(foo(bar))', ' ', [], '', ['foo(bar)'])
572 self.assertEqual(comment[1].content, 'bar')
573
574 def test_get_comment_nested_comment_wsp(self):
575 comment = self._test_get_x(parser.get_comment,
576 '(foo ( bar ) )', '(foo ( bar ) )', ' ', [], '', ['foo ( bar ) '])
577 self.assertEqual(comment[2].content, ' bar ')
578
579 def test_get_comment_empty_comment(self):
580 self._test_get_x(parser.get_comment,
581 '()', '()', ' ', [], '', [''])
582
583 def test_get_comment_multiple_nesting(self):
584 comment = self._test_get_x(parser.get_comment,
585 '(((((foo)))))', '(((((foo)))))', ' ', [], '', ['((((foo))))'])
586 for i in range(4, 0, -1):
587 self.assertEqual(comment[0].content, '('*(i-1)+'foo'+')'*(i-1))
588 comment = comment[0]
589 self.assertEqual(comment.content, 'foo')
590
591 def test_get_comment_missing_end_of_nesting(self):
592 self._test_get_x(parser.get_comment,
593 '(((((foo)))', '(((((foo)))))', ' ',
594 [errors.InvalidHeaderDefect]*2, '', ['((((foo))))'])
595
596 def test_get_comment_qs_in_nested_comment(self):
597 comment = self._test_get_x(parser.get_comment,
598 '(foo (b\)))', '(foo (b\)))', ' ', [], '', ['foo (b\))'])
599 self.assertEqual(comment[2].content, 'b)')
600
601 # get_cfws
602
603 def test_get_cfws_only_ws(self):
604 cfws = self._test_get_x(parser.get_cfws,
605 ' \t \t', ' \t \t', ' ', [], '', [])
606 self.assertEqual(cfws.token_type, 'cfws')
607
608 def test_get_cfws_only_comment(self):
609 cfws = self._test_get_x(parser.get_cfws,
610 '(foo)', '(foo)', ' ', [], '', ['foo'])
611 self.assertEqual(cfws[0].content, 'foo')
612
613 def test_get_cfws_only_mixed(self):
614 cfws = self._test_get_x(parser.get_cfws,
615 ' (foo ) ( bar) ', ' (foo ) ( bar) ', ' ', [], '',
616 ['foo ', ' bar'])
617 self.assertEqual(cfws[1].content, 'foo ')
618 self.assertEqual(cfws[3].content, ' bar')
619
620 def test_get_cfws_ends_at_non_leader(self):
621 cfws = self._test_get_x(parser.get_cfws,
622 '(foo) bar', '(foo) ', ' ', [], 'bar', ['foo'])
623 self.assertEqual(cfws[0].content, 'foo')
624
625 def test_get_cfws_ends_at_non_printable(self):
626 cfws = self._test_get_x(parser.get_cfws,
627 '(foo) \x07', '(foo) ', ' ', [], '\x07', ['foo'])
628 self.assertEqual(cfws[0].content, 'foo')
629
630 def test_get_cfws_non_printable_in_comment(self):
631 cfws = self._test_get_x(parser.get_cfws,
632 '(foo \x07) "test"', '(foo \x07) ', ' ',
633 [errors.NonPrintableDefect], '"test"', ['foo \x07'])
634 self.assertEqual(cfws[0].content, 'foo \x07')
635
636 def test_get_cfws_header_ends_in_comment(self):
637 cfws = self._test_get_x(parser.get_cfws,
638 ' (foo ', ' (foo )', ' ',
639 [errors.InvalidHeaderDefect], '', ['foo '])
640 self.assertEqual(cfws[1].content, 'foo ')
641
642 def test_get_cfws_multiple_nested_comments(self):
643 cfws = self._test_get_x(parser.get_cfws,
644 '(foo (bar)) ((a)(a))', '(foo (bar)) ((a)(a))', ' ', [],
645 '', ['foo (bar)', '(a)(a)'])
646 self.assertEqual(cfws[0].comments, ['foo (bar)'])
647 self.assertEqual(cfws[2].comments, ['(a)(a)'])
648
649 # get_quoted_string
650
651 def test_get_quoted_string_only(self):
652 qs = self._test_get_x(parser.get_quoted_string,
653 '"bob"', '"bob"', 'bob', [], '')
654 self.assertEqual(qs.token_type, 'quoted-string')
655 self.assertEqual(qs.quoted_value, '"bob"')
656 self.assertEqual(qs.content, 'bob')
657
658 def test_get_quoted_string_with_wsp(self):
659 qs = self._test_get_x(parser.get_quoted_string,
660 '\t "bob" ', '\t "bob" ', ' bob ', [], '')
661 self.assertEqual(qs.quoted_value, ' "bob" ')
662 self.assertEqual(qs.content, 'bob')
663
664 def test_get_quoted_string_with_comments_and_wsp(self):
665 qs = self._test_get_x(parser.get_quoted_string,
666 ' (foo) "bob"(bar)', ' (foo) "bob"(bar)', ' bob ', [], '')
667 self.assertEqual(qs[0][1].content, 'foo')
668 self.assertEqual(qs[2][0].content, 'bar')
669 self.assertEqual(qs.content, 'bob')
670 self.assertEqual(qs.quoted_value, ' "bob" ')
671
672 def test_get_quoted_string_with_multiple_comments(self):
673 qs = self._test_get_x(parser.get_quoted_string,
674 ' (foo) (bar) "bob"(bird)', ' (foo) (bar) "bob"(bird)', ' bob ',
675 [], '')
676 self.assertEqual(qs[0].comments, ['foo', 'bar'])
677 self.assertEqual(qs[2].comments, ['bird'])
678 self.assertEqual(qs.content, 'bob')
679 self.assertEqual(qs.quoted_value, ' "bob" ')
680
681 def test_get_quoted_string_non_printable_in_comment(self):
682 qs = self._test_get_x(parser.get_quoted_string,
683 ' (\x0A) "bob"', ' (\x0A) "bob"', ' bob',
684 [errors.NonPrintableDefect], '')
685 self.assertEqual(qs[0].comments, ['\x0A'])
686 self.assertEqual(qs.content, 'bob')
687 self.assertEqual(qs.quoted_value, ' "bob"')
688
689 def test_get_quoted_string_non_printable_in_qcontent(self):
690 qs = self._test_get_x(parser.get_quoted_string,
691 ' (a) "a\x0B"', ' (a) "a\x0B"', ' a\x0B',
692 [errors.NonPrintableDefect], '')
693 self.assertEqual(qs[0].comments, ['a'])
694 self.assertEqual(qs.content, 'a\x0B')
695 self.assertEqual(qs.quoted_value, ' "a\x0B"')
696
697 def test_get_quoted_string_internal_ws(self):
698 qs = self._test_get_x(parser.get_quoted_string,
699 ' (a) "foo bar "', ' (a) "foo bar "', ' foo bar ',
700 [], '')
701 self.assertEqual(qs[0].comments, ['a'])
702 self.assertEqual(qs.content, 'foo bar ')
703 self.assertEqual(qs.quoted_value, ' "foo bar "')
704
705 def test_get_quoted_string_header_ends_in_comment(self):
706 qs = self._test_get_x(parser.get_quoted_string,
707 ' (a) "bob" (a', ' (a) "bob" (a)', ' bob ',
708 [errors.InvalidHeaderDefect], '')
709 self.assertEqual(qs[0].comments, ['a'])
710 self.assertEqual(qs[2].comments, ['a'])
711 self.assertEqual(qs.content, 'bob')
712 self.assertEqual(qs.quoted_value, ' "bob" ')
713
714 def test_get_quoted_string_header_ends_in_qcontent(self):
715 qs = self._test_get_x(parser.get_quoted_string,
716 ' (a) "bob', ' (a) "bob"', ' bob',
717 [errors.InvalidHeaderDefect], '')
718 self.assertEqual(qs[0].comments, ['a'])
719 self.assertEqual(qs.content, 'bob')
720 self.assertEqual(qs.quoted_value, ' "bob"')
721
722 def test_get_quoted_string_no_quoted_string(self):
723 with self.assertRaises(errors.HeaderParseError):
724 parser.get_quoted_string(' (ab) xyz')
725
726 def test_get_quoted_string_qs_ends_at_noncfws(self):
727 qs = self._test_get_x(parser.get_quoted_string,
728 '\t "bob" fee', '\t "bob" ', ' bob ', [], 'fee')
729 self.assertEqual(qs.content, 'bob')
730 self.assertEqual(qs.quoted_value, ' "bob" ')
731
732 # get_atom
733
734 def test_get_atom_only(self):
735 atom = self._test_get_x(parser.get_atom,
736 'bob', 'bob', 'bob', [], '')
737 self.assertEqual(atom.token_type, 'atom')
738
739 def test_get_atom_with_wsp(self):
740 self._test_get_x(parser.get_atom,
741 '\t bob ', '\t bob ', ' bob ', [], '')
742
743 def test_get_atom_with_comments_and_wsp(self):
744 atom = self._test_get_x(parser.get_atom,
745 ' (foo) bob(bar)', ' (foo) bob(bar)', ' bob ', [], '')
746 self.assertEqual(atom[0][1].content, 'foo')
747 self.assertEqual(atom[2][0].content, 'bar')
748
749 def test_get_atom_with_multiple_comments(self):
750 atom = self._test_get_x(parser.get_atom,
751 ' (foo) (bar) bob(bird)', ' (foo) (bar) bob(bird)', ' bob ',
752 [], '')
753 self.assertEqual(atom[0].comments, ['foo', 'bar'])
754 self.assertEqual(atom[2].comments, ['bird'])
755
756 def test_get_atom_non_printable_in_comment(self):
757 atom = self._test_get_x(parser.get_atom,
758 ' (\x0A) bob', ' (\x0A) bob', ' bob',
759 [errors.NonPrintableDefect], '')
760 self.assertEqual(atom[0].comments, ['\x0A'])
761
762 def test_get_atom_non_printable_in_atext(self):
763 atom = self._test_get_x(parser.get_atom,
764 ' (a) a\x0B', ' (a) a\x0B', ' a\x0B',
765 [errors.NonPrintableDefect], '')
766 self.assertEqual(atom[0].comments, ['a'])
767
768 def test_get_atom_header_ends_in_comment(self):
769 atom = self._test_get_x(parser.get_atom,
770 ' (a) bob (a', ' (a) bob (a)', ' bob ',
771 [errors.InvalidHeaderDefect], '')
772 self.assertEqual(atom[0].comments, ['a'])
773 self.assertEqual(atom[2].comments, ['a'])
774
775 def test_get_atom_no_atom(self):
776 with self.assertRaises(errors.HeaderParseError):
777 parser.get_atom(' (ab) ')
778
779 def test_get_atom_no_atom_before_special(self):
780 with self.assertRaises(errors.HeaderParseError):
781 parser.get_atom(' (ab) @')
782
783 def test_get_atom_atom_ends_at_special(self):
784 atom = self._test_get_x(parser.get_atom,
785 ' (foo) bob(bar) @bang', ' (foo) bob(bar) ', ' bob ', [], '@bang')
786 self.assertEqual(atom[0].comments, ['foo'])
787 self.assertEqual(atom[2].comments, ['bar'])
788
789 def test_get_atom_atom_ends_at_noncfws(self):
790 atom = self._test_get_x(parser.get_atom,
791 'bob fred', 'bob ', 'bob ', [], 'fred')
792
793 # get_dot_atom_text
794
795 def test_get_dot_atom_text(self):
796 dot_atom_text = self._test_get_x(parser.get_dot_atom_text,
797 'foo.bar.bang', 'foo.bar.bang', 'foo.bar.bang', [], '')
798 self.assertEqual(dot_atom_text.token_type, 'dot-atom-text')
799 self.assertEqual(len(dot_atom_text), 5)
800
801 def test_get_dot_atom_text_lone_atom_is_valid(self):
802 dot_atom_text = self._test_get_x(parser.get_dot_atom_text,
803 'foo', 'foo', 'foo', [], '')
804
805 def test_get_dot_atom_text_raises_on_leading_dot(self):
806 with self.assertRaises(errors.HeaderParseError):
807 parser.get_dot_atom_text('.foo.bar')
808
809 def test_get_dot_atom_text_raises_on_trailing_dot(self):
810 with self.assertRaises(errors.HeaderParseError):
811 parser.get_dot_atom_text('foo.bar.')
812
813 def test_get_dot_atom_text_raises_on_leading_non_atext(self):
814 with self.assertRaises(errors.HeaderParseError):
815 parser.get_dot_atom_text(' foo.bar')
816 with self.assertRaises(errors.HeaderParseError):
817 parser.get_dot_atom_text('@foo.bar')
818 with self.assertRaises(errors.HeaderParseError):
819 parser.get_dot_atom_text('"foo.bar"')
820
821 def test_get_dot_atom_text_trailing_text_preserved(self):
822 dot_atom_text = self._test_get_x(parser.get_dot_atom_text,
823 'foo@bar', 'foo', 'foo', [], '@bar')
824
825 def test_get_dot_atom_text_trailing_ws_preserved(self):
826 dot_atom_text = self._test_get_x(parser.get_dot_atom_text,
827 'foo .bar', 'foo', 'foo', [], ' .bar')
828
829 # get_dot_atom
830
831 def test_get_dot_atom_only(self):
832 dot_atom = self._test_get_x(parser.get_dot_atom,
833 'foo.bar.bing', 'foo.bar.bing', 'foo.bar.bing', [], '')
834 self.assertEqual(dot_atom.token_type, 'dot-atom')
835 self.assertEqual(len(dot_atom), 1)
836
837 def test_get_dot_atom_with_wsp(self):
838 self._test_get_x(parser.get_dot_atom,
839 '\t foo.bar.bing ', '\t foo.bar.bing ', ' foo.bar.bing ', [], '')
840
841 def test_get_dot_atom_with_comments_and_wsp(self):
842 self._test_get_x(parser.get_dot_atom,
843 ' (sing) foo.bar.bing (here) ', ' (sing) foo.bar.bing (here) ',
844 ' foo.bar.bing ', [], '')
845
846 def test_get_dot_atom_space_ends_dot_atom(self):
847 self._test_get_x(parser.get_dot_atom,
848 ' (sing) foo.bar .bing (here) ', ' (sing) foo.bar ',
849 ' foo.bar ', [], '.bing (here) ')
850
851 def test_get_dot_atom_no_atom_raises(self):
852 with self.assertRaises(errors.HeaderParseError):
853 parser.get_dot_atom(' (foo) ')
854
855 def test_get_dot_atom_leading_dot_raises(self):
856 with self.assertRaises(errors.HeaderParseError):
857 parser.get_dot_atom(' (foo) .bar')
858
859 def test_get_dot_atom_two_dots_raises(self):
860 with self.assertRaises(errors.HeaderParseError):
861 parser.get_dot_atom('bar..bang')
862
863 def test_get_dot_atom_trailing_dot_raises(self):
864 with self.assertRaises(errors.HeaderParseError):
865 parser.get_dot_atom(' (foo) bar.bang. foo')
866
867 # get_word (if this were black box we'd repeat all the qs/atom tests)
868
869 def test_get_word_atom_yields_atom(self):
870 word = self._test_get_x(parser.get_word,
871 ' (foo) bar (bang) :ah', ' (foo) bar (bang) ', ' bar ', [], ':ah')
872 self.assertEqual(word.token_type, 'atom')
873 self.assertEqual(word[0].token_type, 'cfws')
874
875 def test_get_word_qs_yields_qs(self):
876 word = self._test_get_x(parser.get_word,
877 '"bar " (bang) ah', '"bar " (bang) ', 'bar ', [], 'ah')
878 self.assertEqual(word.token_type, 'quoted-string')
879 self.assertEqual(word[0].token_type, 'bare-quoted-string')
880 self.assertEqual(word[0].value, 'bar ')
881 self.assertEqual(word.content, 'bar ')
882
883 def test_get_word_ends_at_dot(self):
884 self._test_get_x(parser.get_word,
885 'foo.', 'foo', 'foo', [], '.')
886
887 # get_phrase
888
889 def test_get_phrase_simple(self):
890 phrase = self._test_get_x(parser.get_phrase,
891 '"Fred A. Johnson" is his name, oh.',
892 '"Fred A. Johnson" is his name',
893 'Fred A. Johnson is his name',
894 [],
895 ', oh.')
896 self.assertEqual(phrase.token_type, 'phrase')
897
898 def test_get_phrase_complex(self):
899 phrase = self._test_get_x(parser.get_phrase,
900 ' (A) bird (in (my|your)) "hand " is messy\t<>\t',
901 ' (A) bird (in (my|your)) "hand " is messy\t',
902 ' bird hand is messy ',
903 [],
904 '<>\t')
905 self.assertEqual(phrase[0][0].comments, ['A'])
906 self.assertEqual(phrase[0][2].comments, ['in (my|your)'])
907
908 def test_get_phrase_obsolete(self):
909 phrase = self._test_get_x(parser.get_phrase,
910 'Fred A.(weird).O Johnson',
911 'Fred A.(weird).O Johnson',
912 'Fred A. .O Johnson',
913 [errors.ObsoleteHeaderDefect]*3,
914 '')
915 self.assertEqual(len(phrase), 7)
916 self.assertEqual(phrase[3].comments, ['weird'])
917
918 def test_get_phrase_pharse_must_start_with_word(self):
919 phrase = self._test_get_x(parser.get_phrase,
920 '(even weirder).name',
921 '(even weirder).name',
922 ' .name',
923 [errors.InvalidHeaderDefect] + [errors.ObsoleteHeaderDefect]*2,
924 '')
925 self.assertEqual(len(phrase), 3)
926 self.assertEqual(phrase[0].comments, ['even weirder'])
927
928 def test_get_phrase_ending_with_obsolete(self):
929 phrase = self._test_get_x(parser.get_phrase,
930 'simple phrase.(with trailing comment):boo',
931 'simple phrase.(with trailing comment)',
932 'simple phrase. ',
933 [errors.ObsoleteHeaderDefect]*2,
934 ':boo')
935 self.assertEqual(len(phrase), 4)
936 self.assertEqual(phrase[3].comments, ['with trailing comment'])
937
938 def get_phrase_cfws_only_raises(self):
939 with self.assertRaises(errors.HeaderParseError):
940 parser.get_phrase(' (foo) ')
941
942 # get_local_part
943
944 def test_get_local_part_simple(self):
945 local_part = self._test_get_x(parser.get_local_part,
946 'dinsdale@python.org', 'dinsdale', 'dinsdale', [], '@python.org')
947 self.assertEqual(local_part.token_type, 'local-part')
948 self.assertEqual(local_part.local_part, 'dinsdale')
949
950 def test_get_local_part_with_dot(self):
951 local_part = self._test_get_x(parser.get_local_part,
952 'Fred.A.Johnson@python.org',
953 'Fred.A.Johnson',
954 'Fred.A.Johnson',
955 [],
956 '@python.org')
957 self.assertEqual(local_part.local_part, 'Fred.A.Johnson')
958
959 def test_get_local_part_with_whitespace(self):
960 local_part = self._test_get_x(parser.get_local_part,
961 ' Fred.A.Johnson @python.org',
962 ' Fred.A.Johnson ',
963 ' Fred.A.Johnson ',
964 [],
965 '@python.org')
966 self.assertEqual(local_part.local_part, 'Fred.A.Johnson')
967
968 def test_get_local_part_with_cfws(self):
969 local_part = self._test_get_x(parser.get_local_part,
970 ' (foo) Fred.A.Johnson (bar (bird)) @python.org',
971 ' (foo) Fred.A.Johnson (bar (bird)) ',
972 ' Fred.A.Johnson ',
973 [],
974 '@python.org')
975 self.assertEqual(local_part.local_part, 'Fred.A.Johnson')
976 self.assertEqual(local_part[0][0].comments, ['foo'])
977 self.assertEqual(local_part[0][2].comments, ['bar (bird)'])
978
979 def test_get_local_part_simple_quoted(self):
980 local_part = self._test_get_x(parser.get_local_part,
981 '"dinsdale"@python.org', '"dinsdale"', '"dinsdale"', [], '@python.org')
982 self.assertEqual(local_part.token_type, 'local-part')
983 self.assertEqual(local_part.local_part, 'dinsdale')
984
985 def test_get_local_part_with_quoted_dot(self):
986 local_part = self._test_get_x(parser.get_local_part,
987 '"Fred.A.Johnson"@python.org',
988 '"Fred.A.Johnson"',
989 '"Fred.A.Johnson"',
990 [],
991 '@python.org')
992 self.assertEqual(local_part.local_part, 'Fred.A.Johnson')
993
994 def test_get_local_part_quoted_with_whitespace(self):
995 local_part = self._test_get_x(parser.get_local_part,
996 ' "Fred A. Johnson" @python.org',
997 ' "Fred A. Johnson" ',
998 ' "Fred A. Johnson" ',
999 [],
1000 '@python.org')
1001 self.assertEqual(local_part.local_part, 'Fred A. Johnson')
1002
1003 def test_get_local_part_quoted_with_cfws(self):
1004 local_part = self._test_get_x(parser.get_local_part,
1005 ' (foo) " Fred A. Johnson " (bar (bird)) @python.org',
1006 ' (foo) " Fred A. Johnson " (bar (bird)) ',
1007 ' " Fred A. Johnson " ',
1008 [],
1009 '@python.org')
1010 self.assertEqual(local_part.local_part, ' Fred A. Johnson ')
1011 self.assertEqual(local_part[0][0].comments, ['foo'])
1012 self.assertEqual(local_part[0][2].comments, ['bar (bird)'])
1013
1014
1015 def test_get_local_part_simple_obsolete(self):
1016 local_part = self._test_get_x(parser.get_local_part,
1017 'Fred. A.Johnson@python.org',
1018 'Fred. A.Johnson',
1019 'Fred. A.Johnson',
1020 [errors.ObsoleteHeaderDefect],
1021 '@python.org')
1022 self.assertEqual(local_part.local_part, 'Fred.A.Johnson')
1023
1024 def test_get_local_part_complex_obsolete_1(self):
1025 local_part = self._test_get_x(parser.get_local_part,
1026 ' (foo )Fred (bar).(bird) A.(sheep)Johnson."and dogs "@python.org',
1027 ' (foo )Fred (bar).(bird) A.(sheep)Johnson."and dogs "',
1028 ' Fred . A. Johnson.and dogs ',
1029 [errors.ObsoleteHeaderDefect],
1030 '@python.org')
1031 self.assertEqual(local_part.local_part, 'Fred.A.Johnson.and dogs ')
1032
1033 def test_get_local_part_complex_obsolete_invalid(self):
1034 local_part = self._test_get_x(parser.get_local_part,
1035 ' (foo )Fred (bar).(bird) A.(sheep)Johnson "and dogs"@python.org',
1036 ' (foo )Fred (bar).(bird) A.(sheep)Johnson "and dogs"',
1037 ' Fred . A. Johnson and dogs',
1038 [errors.InvalidHeaderDefect]*2,
1039 '@python.org')
1040 self.assertEqual(local_part.local_part, 'Fred.A.Johnson and dogs')
1041
1042 def test_get_local_part_no_part_raises(self):
1043 with self.assertRaises(errors.HeaderParseError):
1044 parser.get_local_part(' (foo) ')
1045
1046 def test_get_local_part_special_instead_raises(self):
1047 with self.assertRaises(errors.HeaderParseError):
1048 parser.get_local_part(' (foo) @python.org')
1049
1050 def test_get_local_part_trailing_dot(self):
1051 local_part = self._test_get_x(parser.get_local_part,
1052 ' borris.@python.org',
1053 ' borris.',
1054 ' borris.',
1055 [errors.InvalidHeaderDefect]*2,
1056 '@python.org')
1057 self.assertEqual(local_part.local_part, 'borris.')
1058
1059 def test_get_local_part_trailing_dot_with_ws(self):
1060 local_part = self._test_get_x(parser.get_local_part,
1061 ' borris. @python.org',
1062 ' borris. ',
1063 ' borris. ',
1064 [errors.InvalidHeaderDefect]*2,
1065 '@python.org')
1066 self.assertEqual(local_part.local_part, 'borris.')
1067
1068 def test_get_local_part_leading_dot(self):
1069 local_part = self._test_get_x(parser.get_local_part,
1070 '.borris@python.org',
1071 '.borris',
1072 '.borris',
1073 [errors.InvalidHeaderDefect]*2,
1074 '@python.org')
1075 self.assertEqual(local_part.local_part, '.borris')
1076
1077 def test_get_local_part_leading_dot_after_ws(self):
1078 local_part = self._test_get_x(parser.get_local_part,
1079 ' .borris@python.org',
1080 ' .borris',
1081 ' .borris',
1082 [errors.InvalidHeaderDefect]*2,
1083 '@python.org')
1084 self.assertEqual(local_part.local_part, '.borris')
1085
1086 def test_get_local_part_double_dot_raises(self):
1087 local_part = self._test_get_x(parser.get_local_part,
1088 ' borris.(foo).natasha@python.org',
1089 ' borris.(foo).natasha',
1090 ' borris. .natasha',
1091 [errors.InvalidHeaderDefect]*2,
1092 '@python.org')
1093 self.assertEqual(local_part.local_part, 'borris..natasha')
1094
1095 def test_get_local_part_quoted_strings_in_atom_list(self):
1096 local_part = self._test_get_x(parser.get_local_part,
1097 '""example" example"@example.com',
1098 '""example" example"',
1099 'example example',
1100 [errors.InvalidHeaderDefect]*3,
1101 '@example.com')
1102 self.assertEqual(local_part.local_part, 'example example')
1103
1104 def test_get_local_part_valid_and_invalid_qp_in_atom_list(self):
1105 local_part = self._test_get_x(parser.get_local_part,
1106 r'"\\"example\\" example"@example.com',
1107 r'"\\"example\\" example"',
1108 r'\example\\ example',
1109 [errors.InvalidHeaderDefect]*5,
1110 '@example.com')
1111 self.assertEqual(local_part.local_part, r'\example\\ example')
1112
1113 def test_get_local_part_unicode_defect(self):
1114 # Currently this only happens when parsing unicode, not when parsing
1115 # stuff that was originally binary.
1116 local_part = self._test_get_x(parser.get_local_part,
1117 'exámple@example.com',
1118 'exámple',
1119 'exámple',
1120 [errors.NonASCIILocalPartDefect],
1121 '@example.com')
1122 self.assertEqual(local_part.local_part, 'exámple')
1123
1124 # get_dtext
1125
1126 def test_get_dtext_only(self):
1127 dtext = self._test_get_x(parser.get_dtext,
1128 'foobar', 'foobar', 'foobar', [], '')
1129 self.assertEqual(dtext.token_type, 'ptext')
1130
1131 def test_get_dtext_all_dtext(self):
1132 dtext = self._test_get_x(parser.get_dtext, self.rfc_dtext_chars,
1133 self.rfc_dtext_chars,
1134 self.rfc_dtext_chars, [], '')
1135
1136 def test_get_dtext_two_words_gets_first(self):
1137 self._test_get_x(parser.get_dtext,
1138 'foo bar', 'foo', 'foo', [], ' bar')
1139
1140 def test_get_dtext_following_wsp_preserved(self):
1141 self._test_get_x(parser.get_dtext,
1142 'foo \t\tbar', 'foo', 'foo', [], ' \t\tbar')
1143
1144 def test_get_dtext_non_printables(self):
1145 dtext = self._test_get_x(parser.get_dtext,
1146 'foo\x00bar]', 'foo\x00bar', 'foo\x00bar',
1147 [errors.NonPrintableDefect], ']')
1148 self.assertEqual(dtext.defects[0].non_printables[0], '\x00')
1149
1150 def test_get_dtext_with_qp(self):
1151 ptext = self._test_get_x(parser.get_dtext,
1152 r'foo\]\[\\bar\b\e\l\l',
1153 r'foo][\barbell',
1154 r'foo][\barbell',
1155 [errors.ObsoleteHeaderDefect],
1156 '')
1157
1158 def test_get_dtext_up_to_close_bracket_only(self):
1159 self._test_get_x(parser.get_dtext,
1160 'foo]', 'foo', 'foo', [], ']')
1161
1162 def test_get_dtext_wsp_before_close_bracket_preserved(self):
1163 self._test_get_x(parser.get_dtext,
1164 'foo ]', 'foo', 'foo', [], ' ]')
1165
1166 def test_get_dtext_close_bracket_mid_word(self):
1167 self._test_get_x(parser.get_dtext,
1168 'foo]bar', 'foo', 'foo', [], ']bar')
1169
1170 def test_get_dtext_up_to_open_bracket_only(self):
1171 self._test_get_x(parser.get_dtext,
1172 'foo[', 'foo', 'foo', [], '[')
1173
1174 def test_get_dtext_wsp_before_open_bracket_preserved(self):
1175 self._test_get_x(parser.get_dtext,
1176 'foo [', 'foo', 'foo', [], ' [')
1177
1178 def test_get_dtext_open_bracket_mid_word(self):
1179 self._test_get_x(parser.get_dtext,
1180 'foo[bar', 'foo', 'foo', [], '[bar')
1181
1182 # get_domain_literal
1183
1184 def test_get_domain_literal_only(self):
1185 domain_literal = domain_literal = self._test_get_x(parser.get_domain_literal,
1186 '[127.0.0.1]',
1187 '[127.0.0.1]',
1188 '[127.0.0.1]',
1189 [],
1190 '')
1191 self.assertEqual(domain_literal.token_type, 'domain-literal')
1192 self.assertEqual(domain_literal.domain, '[127.0.0.1]')
1193 self.assertEqual(domain_literal.ip, '127.0.0.1')
1194
1195 def test_get_domain_literal_with_internal_ws(self):
1196 domain_literal = self._test_get_x(parser.get_domain_literal,
1197 '[ 127.0.0.1\t ]',
1198 '[ 127.0.0.1\t ]',
1199 '[ 127.0.0.1 ]',
1200 [],
1201 '')
1202 self.assertEqual(domain_literal.domain, '[127.0.0.1]')
1203 self.assertEqual(domain_literal.ip, '127.0.0.1')
1204
1205 def test_get_domain_literal_with_surrounding_cfws(self):
1206 domain_literal = self._test_get_x(parser.get_domain_literal,
1207 '(foo)[ 127.0.0.1] (bar)',
1208 '(foo)[ 127.0.0.1] (bar)',
1209 ' [ 127.0.0.1] ',
1210 [],
1211 '')
1212 self.assertEqual(domain_literal.domain, '[127.0.0.1]')
1213 self.assertEqual(domain_literal.ip, '127.0.0.1')
1214
1215 def test_get_domain_literal_no_start_char_raises(self):
1216 with self.assertRaises(errors.HeaderParseError):
1217 parser.get_domain_literal('(foo) ')
1218
1219 def test_get_domain_literal_no_start_char_before_special_raises(self):
1220 with self.assertRaises(errors.HeaderParseError):
1221 parser.get_domain_literal('(foo) @')
1222
1223 def test_get_domain_literal_bad_dtext_char_before_special_raises(self):
1224 with self.assertRaises(errors.HeaderParseError):
1225 parser.get_domain_literal('(foo) [abc[@')
1226
1227 # get_domain
1228
1229 def test_get_domain_regular_domain_only(self):
1230 domain = self._test_get_x(parser.get_domain,
1231 'example.com',
1232 'example.com',
1233 'example.com',
1234 [],
1235 '')
1236 self.assertEqual(domain.token_type, 'domain')
1237 self.assertEqual(domain.domain, 'example.com')
1238
1239 def test_get_domain_domain_literal_only(self):
1240 domain = self._test_get_x(parser.get_domain,
1241 '[127.0.0.1]',
1242 '[127.0.0.1]',
1243 '[127.0.0.1]',
1244 [],
1245 '')
1246 self.assertEqual(domain.token_type, 'domain')
1247 self.assertEqual(domain.domain, '[127.0.0.1]')
1248
1249 def test_get_domain_with_cfws(self):
1250 domain = self._test_get_x(parser.get_domain,
1251 '(foo) example.com(bar)\t',
1252 '(foo) example.com(bar)\t',
1253 ' example.com ',
1254 [],
1255 '')
1256 self.assertEqual(domain.domain, 'example.com')
1257
1258 def test_get_domain_domain_literal_with_cfws(self):
1259 domain = self._test_get_x(parser.get_domain,
1260 '(foo)[127.0.0.1]\t(bar)',
1261 '(foo)[127.0.0.1]\t(bar)',
1262 ' [127.0.0.1] ',
1263 [],
1264 '')
1265 self.assertEqual(domain.domain, '[127.0.0.1]')
1266
1267 def test_get_domain_domain_with_cfws_ends_at_special(self):
1268 domain = self._test_get_x(parser.get_domain,
1269 '(foo)example.com\t(bar), next',
1270 '(foo)example.com\t(bar)',
1271 ' example.com ',
1272 [],
1273 ', next')
1274 self.assertEqual(domain.domain, 'example.com')
1275
1276 def test_get_domain_domain_literal_with_cfws_ends_at_special(self):
1277 domain = self._test_get_x(parser.get_domain,
1278 '(foo)[127.0.0.1]\t(bar), next',
1279 '(foo)[127.0.0.1]\t(bar)',
1280 ' [127.0.0.1] ',
1281 [],
1282 ', next')
1283 self.assertEqual(domain.domain, '[127.0.0.1]')
1284
1285 def test_get_domain_obsolete(self):
1286 domain = self._test_get_x(parser.get_domain,
1287 '(foo) example . (bird)com(bar)\t',
1288 '(foo) example . (bird)com(bar)\t',
1289 ' example . com ',
1290 [errors.ObsoleteHeaderDefect],
1291 '')
1292 self.assertEqual(domain.domain, 'example.com')
1293
1294 def test_get_domain_no_non_cfws_raises(self):
1295 with self.assertRaises(errors.HeaderParseError):
1296 parser.get_domain(" (foo)\t")
1297
1298 def test_get_domain_no_atom_raises(self):
1299 with self.assertRaises(errors.HeaderParseError):
1300 parser.get_domain(" (foo)\t, broken")
1301
1302
1303 # get_addr_spec
1304
1305 def test_get_addr_spec_normal(self):
1306 addr_spec = self._test_get_x(parser.get_addr_spec,
1307 'dinsdale@example.com',
1308 'dinsdale@example.com',
1309 'dinsdale@example.com',
1310 [],
1311 '')
1312 self.assertEqual(addr_spec.token_type, 'addr-spec')
1313 self.assertEqual(addr_spec.local_part, 'dinsdale')
1314 self.assertEqual(addr_spec.domain, 'example.com')
1315 self.assertEqual(addr_spec.addr_spec, 'dinsdale@example.com')
1316
1317 def test_get_addr_spec_with_doamin_literal(self):
1318 addr_spec = self._test_get_x(parser.get_addr_spec,
1319 'dinsdale@[127.0.0.1]',
1320 'dinsdale@[127.0.0.1]',
1321 'dinsdale@[127.0.0.1]',
1322 [],
1323 '')
1324 self.assertEqual(addr_spec.local_part, 'dinsdale')
1325 self.assertEqual(addr_spec.domain, '[127.0.0.1]')
1326 self.assertEqual(addr_spec.addr_spec, 'dinsdale@[127.0.0.1]')
1327
1328 def test_get_addr_spec_with_cfws(self):
1329 addr_spec = self._test_get_x(parser.get_addr_spec,
1330 '(foo) dinsdale(bar)@ (bird) example.com (bog)',
1331 '(foo) dinsdale(bar)@ (bird) example.com (bog)',
1332 ' dinsdale@example.com ',
1333 [],
1334 '')
1335 self.assertEqual(addr_spec.local_part, 'dinsdale')
1336 self.assertEqual(addr_spec.domain, 'example.com')
1337 self.assertEqual(addr_spec.addr_spec, 'dinsdale@example.com')
1338
1339 def test_get_addr_spec_with_qouoted_string_and_cfws(self):
1340 addr_spec = self._test_get_x(parser.get_addr_spec,
1341 '(foo) "roy a bug"(bar)@ (bird) example.com (bog)',
1342 '(foo) "roy a bug"(bar)@ (bird) example.com (bog)',
1343 ' "roy a bug"@example.com ',
1344 [],
1345 '')
1346 self.assertEqual(addr_spec.local_part, 'roy a bug')
1347 self.assertEqual(addr_spec.domain, 'example.com')
1348 self.assertEqual(addr_spec.addr_spec, '"roy a bug"@example.com')
1349
1350 def test_get_addr_spec_ends_at_special(self):
1351 addr_spec = self._test_get_x(parser.get_addr_spec,
1352 '(foo) "roy a bug"(bar)@ (bird) example.com (bog) , next',
1353 '(foo) "roy a bug"(bar)@ (bird) example.com (bog) ',
1354 ' "roy a bug"@example.com ',
1355 [],
1356 ', next')
1357 self.assertEqual(addr_spec.local_part, 'roy a bug')
1358 self.assertEqual(addr_spec.domain, 'example.com')
1359 self.assertEqual(addr_spec.addr_spec, '"roy a bug"@example.com')
1360
1361 def test_get_addr_spec_quoted_strings_in_atom_list(self):
1362 addr_spec = self._test_get_x(parser.get_addr_spec,
1363 '""example" example"@example.com',
1364 '""example" example"@example.com',
1365 'example example@example.com',
1366 [errors.InvalidHeaderDefect]*3,
1367 '')
1368 self.assertEqual(addr_spec.local_part, 'example example')
1369 self.assertEqual(addr_spec.domain, 'example.com')
1370 self.assertEqual(addr_spec.addr_spec, '"example example"@example.com')
1371
1372 def test_get_addr_spec_dot_atom(self):
1373 addr_spec = self._test_get_x(parser.get_addr_spec,
1374 'star.a.star@example.com',
1375 'star.a.star@example.com',
1376 'star.a.star@example.com',
1377 [],
1378 '')
1379 self.assertEqual(addr_spec.local_part, 'star.a.star')
1380 self.assertEqual(addr_spec.domain, 'example.com')
1381 self.assertEqual(addr_spec.addr_spec, 'star.a.star@example.com')
1382
1383 # get_obs_route
1384
1385 def test_get_obs_route_simple(self):
1386 obs_route = self._test_get_x(parser.get_obs_route,
1387 '@example.com, @two.example.com:',
1388 '@example.com, @two.example.com:',
1389 '@example.com, @two.example.com:',
1390 [],
1391 '')
1392 self.assertEqual(obs_route.token_type, 'obs-route')
1393 self.assertEqual(obs_route.domains, ['example.com', 'two.example.com'])
1394
1395 def test_get_obs_route_complex(self):
1396 obs_route = self._test_get_x(parser.get_obs_route,
1397 '(foo),, (blue)@example.com (bar),@two.(foo) example.com (bird):',
1398 '(foo),, (blue)@example.com (bar),@two.(foo) example.com (bird):',
1399 ' ,, @example.com ,@two. example.com :',
1400 [errors.ObsoleteHeaderDefect], # This is the obs-domain
1401 '')
1402 self.assertEqual(obs_route.token_type, 'obs-route')
1403 self.assertEqual(obs_route.domains, ['example.com', 'two.example.com'])
1404
1405 def test_get_obs_route_no_route_before_end_raises(self):
1406 with self.assertRaises(errors.HeaderParseError):
1407 parser.get_obs_route('(foo) @example.com,')
1408
1409 def test_get_obs_route_no_route_before_special_raises(self):
1410 with self.assertRaises(errors.HeaderParseError):
1411 parser.get_obs_route('(foo) [abc],')
1412
1413 def test_get_obs_route_no_route_before_special_raises2(self):
1414 with self.assertRaises(errors.HeaderParseError):
1415 parser.get_obs_route('(foo) @example.com [abc],')
1416
1417 # get_angle_addr
1418
1419 def test_get_angle_addr_simple(self):
1420 angle_addr = self._test_get_x(parser.get_angle_addr,
1421 '<dinsdale@example.com>',
1422 '<dinsdale@example.com>',
1423 '<dinsdale@example.com>',
1424 [],
1425 '')
1426 self.assertEqual(angle_addr.token_type, 'angle-addr')
1427 self.assertEqual(angle_addr.local_part, 'dinsdale')
1428 self.assertEqual(angle_addr.domain, 'example.com')
1429 self.assertIsNone(angle_addr.route)
1430 self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1431
R David Murray032eed32012-05-26 14:31:12 -04001432 def test_get_angle_addr_empty(self):
1433 angle_addr = self._test_get_x(parser.get_angle_addr,
1434 '<>',
1435 '<>',
1436 '<>',
1437 [errors.InvalidHeaderDefect],
1438 '')
1439 self.assertEqual(angle_addr.token_type, 'angle-addr')
1440 self.assertIsNone(angle_addr.local_part)
1441 self.assertIsNone(angle_addr.domain)
1442 self.assertIsNone(angle_addr.route)
1443 self.assertEqual(angle_addr.addr_spec, '<>')
1444
R David Murray0b6f6c82012-05-25 18:42:14 -04001445 def test_get_angle_addr_with_cfws(self):
1446 angle_addr = self._test_get_x(parser.get_angle_addr,
1447 ' (foo) <dinsdale@example.com>(bar)',
1448 ' (foo) <dinsdale@example.com>(bar)',
1449 ' <dinsdale@example.com> ',
1450 [],
1451 '')
1452 self.assertEqual(angle_addr.token_type, 'angle-addr')
1453 self.assertEqual(angle_addr.local_part, 'dinsdale')
1454 self.assertEqual(angle_addr.domain, 'example.com')
1455 self.assertIsNone(angle_addr.route)
1456 self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1457
1458 def test_get_angle_addr_qs_and_domain_literal(self):
1459 angle_addr = self._test_get_x(parser.get_angle_addr,
1460 '<"Fred Perfect"@[127.0.0.1]>',
1461 '<"Fred Perfect"@[127.0.0.1]>',
1462 '<"Fred Perfect"@[127.0.0.1]>',
1463 [],
1464 '')
1465 self.assertEqual(angle_addr.local_part, 'Fred Perfect')
1466 self.assertEqual(angle_addr.domain, '[127.0.0.1]')
1467 self.assertIsNone(angle_addr.route)
1468 self.assertEqual(angle_addr.addr_spec, '"Fred Perfect"@[127.0.0.1]')
1469
1470 def test_get_angle_addr_internal_cfws(self):
1471 angle_addr = self._test_get_x(parser.get_angle_addr,
1472 '<(foo) dinsdale@example.com(bar)>',
1473 '<(foo) dinsdale@example.com(bar)>',
1474 '< dinsdale@example.com >',
1475 [],
1476 '')
1477 self.assertEqual(angle_addr.local_part, 'dinsdale')
1478 self.assertEqual(angle_addr.domain, 'example.com')
1479 self.assertIsNone(angle_addr.route)
1480 self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1481
1482 def test_get_angle_addr_obs_route(self):
1483 angle_addr = self._test_get_x(parser.get_angle_addr,
1484 '(foo)<@example.com, (bird) @two.example.com: dinsdale@example.com> (bar) ',
1485 '(foo)<@example.com, (bird) @two.example.com: dinsdale@example.com> (bar) ',
1486 ' <@example.com, @two.example.com: dinsdale@example.com> ',
1487 [errors.ObsoleteHeaderDefect],
1488 '')
1489 self.assertEqual(angle_addr.local_part, 'dinsdale')
1490 self.assertEqual(angle_addr.domain, 'example.com')
1491 self.assertEqual(angle_addr.route, ['example.com', 'two.example.com'])
1492 self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1493
1494 def test_get_angle_addr_missing_closing_angle(self):
1495 angle_addr = self._test_get_x(parser.get_angle_addr,
1496 '<dinsdale@example.com',
1497 '<dinsdale@example.com>',
1498 '<dinsdale@example.com>',
1499 [errors.InvalidHeaderDefect],
1500 '')
1501 self.assertEqual(angle_addr.local_part, 'dinsdale')
1502 self.assertEqual(angle_addr.domain, 'example.com')
1503 self.assertIsNone(angle_addr.route)
1504 self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1505
1506 def test_get_angle_addr_missing_closing_angle_with_cfws(self):
1507 angle_addr = self._test_get_x(parser.get_angle_addr,
1508 '<dinsdale@example.com (foo)',
1509 '<dinsdale@example.com (foo)>',
1510 '<dinsdale@example.com >',
1511 [errors.InvalidHeaderDefect],
1512 '')
1513 self.assertEqual(angle_addr.local_part, 'dinsdale')
1514 self.assertEqual(angle_addr.domain, 'example.com')
1515 self.assertIsNone(angle_addr.route)
1516 self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1517
1518 def test_get_angle_addr_ends_at_special(self):
1519 angle_addr = self._test_get_x(parser.get_angle_addr,
1520 '<dinsdale@example.com> (foo), next',
1521 '<dinsdale@example.com> (foo)',
1522 '<dinsdale@example.com> ',
1523 [],
1524 ', next')
1525 self.assertEqual(angle_addr.local_part, 'dinsdale')
1526 self.assertEqual(angle_addr.domain, 'example.com')
1527 self.assertIsNone(angle_addr.route)
1528 self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1529
1530 def test_get_angle_addr_no_angle_raise(self):
1531 with self.assertRaises(errors.HeaderParseError):
1532 parser.get_angle_addr('(foo) ')
1533
1534 def test_get_angle_addr_no_angle_before_special_raises(self):
1535 with self.assertRaises(errors.HeaderParseError):
1536 parser.get_angle_addr('(foo) , next')
1537
1538 def test_get_angle_addr_no_angle_raises(self):
1539 with self.assertRaises(errors.HeaderParseError):
1540 parser.get_angle_addr('bar')
1541
1542 def test_get_angle_addr_special_after_angle_raises(self):
1543 with self.assertRaises(errors.HeaderParseError):
1544 parser.get_angle_addr('(foo) <, bar')
1545
1546 # get_display_name This is phrase but with a different value.
1547
1548 def test_get_display_name_simple(self):
1549 display_name = self._test_get_x(parser.get_display_name,
1550 'Fred A Johnson',
1551 'Fred A Johnson',
1552 'Fred A Johnson',
1553 [],
1554 '')
1555 self.assertEqual(display_name.token_type, 'display-name')
1556 self.assertEqual(display_name.display_name, 'Fred A Johnson')
1557
1558 def test_get_display_name_complex1(self):
1559 display_name = self._test_get_x(parser.get_display_name,
1560 '"Fred A. Johnson" is his name, oh.',
1561 '"Fred A. Johnson" is his name',
1562 '"Fred A. Johnson is his name"',
1563 [],
1564 ', oh.')
1565 self.assertEqual(display_name.token_type, 'display-name')
1566 self.assertEqual(display_name.display_name, 'Fred A. Johnson is his name')
1567
1568 def test_get_display_name_complex2(self):
1569 display_name = self._test_get_x(parser.get_display_name,
1570 ' (A) bird (in (my|your)) "hand " is messy\t<>\t',
1571 ' (A) bird (in (my|your)) "hand " is messy\t',
1572 ' "bird hand is messy" ',
1573 [],
1574 '<>\t')
1575 self.assertEqual(display_name[0][0].comments, ['A'])
1576 self.assertEqual(display_name[0][2].comments, ['in (my|your)'])
1577 self.assertEqual(display_name.display_name, 'bird hand is messy')
1578
1579 def test_get_display_name_obsolete(self):
1580 display_name = self._test_get_x(parser.get_display_name,
1581 'Fred A.(weird).O Johnson',
1582 'Fred A.(weird).O Johnson',
1583 '"Fred A. .O Johnson"',
1584 [errors.ObsoleteHeaderDefect]*3,
1585 '')
1586 self.assertEqual(len(display_name), 7)
1587 self.assertEqual(display_name[3].comments, ['weird'])
1588 self.assertEqual(display_name.display_name, 'Fred A. .O Johnson')
1589
1590 def test_get_display_name_pharse_must_start_with_word(self):
1591 display_name = self._test_get_x(parser.get_display_name,
1592 '(even weirder).name',
1593 '(even weirder).name',
1594 ' ".name"',
1595 [errors.InvalidHeaderDefect] + [errors.ObsoleteHeaderDefect]*2,
1596 '')
1597 self.assertEqual(len(display_name), 3)
1598 self.assertEqual(display_name[0].comments, ['even weirder'])
1599 self.assertEqual(display_name.display_name, '.name')
1600
1601 def test_get_display_name_ending_with_obsolete(self):
1602 display_name = self._test_get_x(parser.get_display_name,
1603 'simple phrase.(with trailing comment):boo',
1604 'simple phrase.(with trailing comment)',
1605 '"simple phrase." ',
1606 [errors.ObsoleteHeaderDefect]*2,
1607 ':boo')
1608 self.assertEqual(len(display_name), 4)
1609 self.assertEqual(display_name[3].comments, ['with trailing comment'])
1610 self.assertEqual(display_name.display_name, 'simple phrase.')
1611
1612 # get_name_addr
1613
1614 def test_get_name_addr_angle_addr_only(self):
1615 name_addr = self._test_get_x(parser.get_name_addr,
1616 '<dinsdale@example.com>',
1617 '<dinsdale@example.com>',
1618 '<dinsdale@example.com>',
1619 [],
1620 '')
1621 self.assertEqual(name_addr.token_type, 'name-addr')
1622 self.assertIsNone(name_addr.display_name)
1623 self.assertEqual(name_addr.local_part, 'dinsdale')
1624 self.assertEqual(name_addr.domain, 'example.com')
1625 self.assertIsNone(name_addr.route)
1626 self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1627
1628 def test_get_name_addr_atom_name(self):
1629 name_addr = self._test_get_x(parser.get_name_addr,
1630 'Dinsdale <dinsdale@example.com>',
1631 'Dinsdale <dinsdale@example.com>',
1632 'Dinsdale <dinsdale@example.com>',
1633 [],
1634 '')
1635 self.assertEqual(name_addr.token_type, 'name-addr')
1636 self.assertEqual(name_addr.display_name, 'Dinsdale')
1637 self.assertEqual(name_addr.local_part, 'dinsdale')
1638 self.assertEqual(name_addr.domain, 'example.com')
1639 self.assertIsNone(name_addr.route)
1640 self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1641
1642 def test_get_name_addr_atom_name_with_cfws(self):
1643 name_addr = self._test_get_x(parser.get_name_addr,
1644 '(foo) Dinsdale (bar) <dinsdale@example.com> (bird)',
1645 '(foo) Dinsdale (bar) <dinsdale@example.com> (bird)',
1646 ' Dinsdale <dinsdale@example.com> ',
1647 [],
1648 '')
1649 self.assertEqual(name_addr.display_name, 'Dinsdale')
1650 self.assertEqual(name_addr.local_part, 'dinsdale')
1651 self.assertEqual(name_addr.domain, 'example.com')
1652 self.assertIsNone(name_addr.route)
1653 self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1654
1655 def test_get_name_addr_name_with_cfws_and_dots(self):
1656 name_addr = self._test_get_x(parser.get_name_addr,
1657 '(foo) Roy.A.Bear (bar) <dinsdale@example.com> (bird)',
1658 '(foo) Roy.A.Bear (bar) <dinsdale@example.com> (bird)',
1659 ' "Roy.A.Bear" <dinsdale@example.com> ',
1660 [errors.ObsoleteHeaderDefect]*2,
1661 '')
1662 self.assertEqual(name_addr.display_name, 'Roy.A.Bear')
1663 self.assertEqual(name_addr.local_part, 'dinsdale')
1664 self.assertEqual(name_addr.domain, 'example.com')
1665 self.assertIsNone(name_addr.route)
1666 self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1667
1668 def test_get_name_addr_qs_name(self):
1669 name_addr = self._test_get_x(parser.get_name_addr,
1670 '"Roy.A.Bear" <dinsdale@example.com>',
1671 '"Roy.A.Bear" <dinsdale@example.com>',
1672 '"Roy.A.Bear" <dinsdale@example.com>',
1673 [],
1674 '')
1675 self.assertEqual(name_addr.display_name, 'Roy.A.Bear')
1676 self.assertEqual(name_addr.local_part, 'dinsdale')
1677 self.assertEqual(name_addr.domain, 'example.com')
1678 self.assertIsNone(name_addr.route)
1679 self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1680
1681 def test_get_name_addr_with_route(self):
1682 name_addr = self._test_get_x(parser.get_name_addr,
1683 '"Roy.A.Bear" <@two.example.com: dinsdale@example.com>',
1684 '"Roy.A.Bear" <@two.example.com: dinsdale@example.com>',
1685 '"Roy.A.Bear" <@two.example.com: dinsdale@example.com>',
1686 [errors.ObsoleteHeaderDefect],
1687 '')
1688 self.assertEqual(name_addr.display_name, 'Roy.A.Bear')
1689 self.assertEqual(name_addr.local_part, 'dinsdale')
1690 self.assertEqual(name_addr.domain, 'example.com')
1691 self.assertEqual(name_addr.route, ['two.example.com'])
1692 self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1693
1694 def test_get_name_addr_ends_at_special(self):
1695 name_addr = self._test_get_x(parser.get_name_addr,
1696 '"Roy.A.Bear" <dinsdale@example.com>, next',
1697 '"Roy.A.Bear" <dinsdale@example.com>',
1698 '"Roy.A.Bear" <dinsdale@example.com>',
1699 [],
1700 ', next')
1701 self.assertEqual(name_addr.display_name, 'Roy.A.Bear')
1702 self.assertEqual(name_addr.local_part, 'dinsdale')
1703 self.assertEqual(name_addr.domain, 'example.com')
1704 self.assertIsNone(name_addr.route)
1705 self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1706
1707 def test_get_name_addr_no_content_raises(self):
1708 with self.assertRaises(errors.HeaderParseError):
1709 parser.get_name_addr(' (foo) ')
1710
1711 def test_get_name_addr_no_content_before_special_raises(self):
1712 with self.assertRaises(errors.HeaderParseError):
1713 parser.get_name_addr(' (foo) ,')
1714
1715 def test_get_name_addr_no_angle_after_display_name_raises(self):
1716 with self.assertRaises(errors.HeaderParseError):
1717 parser.get_name_addr('foo bar')
1718
1719 # get_mailbox
1720
1721 def test_get_mailbox_addr_spec_only(self):
1722 mailbox = self._test_get_x(parser.get_mailbox,
1723 'dinsdale@example.com',
1724 'dinsdale@example.com',
1725 'dinsdale@example.com',
1726 [],
1727 '')
1728 self.assertEqual(mailbox.token_type, 'mailbox')
1729 self.assertIsNone(mailbox.display_name)
1730 self.assertEqual(mailbox.local_part, 'dinsdale')
1731 self.assertEqual(mailbox.domain, 'example.com')
1732 self.assertIsNone(mailbox.route)
1733 self.assertEqual(mailbox.addr_spec, 'dinsdale@example.com')
1734
1735 def test_get_mailbox_angle_addr_only(self):
1736 mailbox = self._test_get_x(parser.get_mailbox,
1737 '<dinsdale@example.com>',
1738 '<dinsdale@example.com>',
1739 '<dinsdale@example.com>',
1740 [],
1741 '')
1742 self.assertEqual(mailbox.token_type, 'mailbox')
1743 self.assertIsNone(mailbox.display_name)
1744 self.assertEqual(mailbox.local_part, 'dinsdale')
1745 self.assertEqual(mailbox.domain, 'example.com')
1746 self.assertIsNone(mailbox.route)
1747 self.assertEqual(mailbox.addr_spec, 'dinsdale@example.com')
1748
1749 def test_get_mailbox_name_addr(self):
1750 mailbox = self._test_get_x(parser.get_mailbox,
1751 '"Roy A. Bear" <dinsdale@example.com>',
1752 '"Roy A. Bear" <dinsdale@example.com>',
1753 '"Roy A. Bear" <dinsdale@example.com>',
1754 [],
1755 '')
1756 self.assertEqual(mailbox.token_type, 'mailbox')
1757 self.assertEqual(mailbox.display_name, 'Roy A. Bear')
1758 self.assertEqual(mailbox.local_part, 'dinsdale')
1759 self.assertEqual(mailbox.domain, 'example.com')
1760 self.assertIsNone(mailbox.route)
1761 self.assertEqual(mailbox.addr_spec, 'dinsdale@example.com')
1762
1763 def test_get_mailbox_ends_at_special(self):
1764 mailbox = self._test_get_x(parser.get_mailbox,
1765 '"Roy A. Bear" <dinsdale@example.com>, rest',
1766 '"Roy A. Bear" <dinsdale@example.com>',
1767 '"Roy A. Bear" <dinsdale@example.com>',
1768 [],
1769 ', rest')
1770 self.assertEqual(mailbox.token_type, 'mailbox')
1771 self.assertEqual(mailbox.display_name, 'Roy A. Bear')
1772 self.assertEqual(mailbox.local_part, 'dinsdale')
1773 self.assertEqual(mailbox.domain, 'example.com')
1774 self.assertIsNone(mailbox.route)
1775 self.assertEqual(mailbox.addr_spec, 'dinsdale@example.com')
1776
1777 def test_get_mailbox_quoted_strings_in_atom_list(self):
1778 mailbox = self._test_get_x(parser.get_mailbox,
1779 '""example" example"@example.com',
1780 '""example" example"@example.com',
1781 'example example@example.com',
1782 [errors.InvalidHeaderDefect]*3,
1783 '')
1784 self.assertEqual(mailbox.local_part, 'example example')
1785 self.assertEqual(mailbox.domain, 'example.com')
1786 self.assertEqual(mailbox.addr_spec, '"example example"@example.com')
1787
1788 # get_mailbox_list
1789
1790 def test_get_mailbox_list_single_addr(self):
1791 mailbox_list = self._test_get_x(parser.get_mailbox_list,
1792 'dinsdale@example.com',
1793 'dinsdale@example.com',
1794 'dinsdale@example.com',
1795 [],
1796 '')
1797 self.assertEqual(mailbox_list.token_type, 'mailbox-list')
1798 self.assertEqual(len(mailbox_list.mailboxes), 1)
1799 mailbox = mailbox_list.mailboxes[0]
1800 self.assertIsNone(mailbox.display_name)
1801 self.assertEqual(mailbox.local_part, 'dinsdale')
1802 self.assertEqual(mailbox.domain, 'example.com')
1803 self.assertIsNone(mailbox.route)
1804 self.assertEqual(mailbox.addr_spec, 'dinsdale@example.com')
1805 self.assertEqual(mailbox_list.mailboxes,
1806 mailbox_list.all_mailboxes)
1807
1808 def test_get_mailbox_list_two_simple_addr(self):
1809 mailbox_list = self._test_get_x(parser.get_mailbox_list,
1810 'dinsdale@example.com, dinsdale@test.example.com',
1811 'dinsdale@example.com, dinsdale@test.example.com',
1812 'dinsdale@example.com, dinsdale@test.example.com',
1813 [],
1814 '')
1815 self.assertEqual(mailbox_list.token_type, 'mailbox-list')
1816 self.assertEqual(len(mailbox_list.mailboxes), 2)
1817 self.assertEqual(mailbox_list.mailboxes[0].addr_spec,
1818 'dinsdale@example.com')
1819 self.assertEqual(mailbox_list.mailboxes[1].addr_spec,
1820 'dinsdale@test.example.com')
1821 self.assertEqual(mailbox_list.mailboxes,
1822 mailbox_list.all_mailboxes)
1823
1824 def test_get_mailbox_list_two_name_addr(self):
1825 mailbox_list = self._test_get_x(parser.get_mailbox_list,
1826 ('"Roy A. Bear" <dinsdale@example.com>,'
1827 ' "Fred Flintstone" <dinsdale@test.example.com>'),
1828 ('"Roy A. Bear" <dinsdale@example.com>,'
1829 ' "Fred Flintstone" <dinsdale@test.example.com>'),
1830 ('"Roy A. Bear" <dinsdale@example.com>,'
1831 ' "Fred Flintstone" <dinsdale@test.example.com>'),
1832 [],
1833 '')
1834 self.assertEqual(len(mailbox_list.mailboxes), 2)
1835 self.assertEqual(mailbox_list.mailboxes[0].addr_spec,
1836 'dinsdale@example.com')
1837 self.assertEqual(mailbox_list.mailboxes[0].display_name,
1838 'Roy A. Bear')
1839 self.assertEqual(mailbox_list.mailboxes[1].addr_spec,
1840 'dinsdale@test.example.com')
1841 self.assertEqual(mailbox_list.mailboxes[1].display_name,
1842 'Fred Flintstone')
1843 self.assertEqual(mailbox_list.mailboxes,
1844 mailbox_list.all_mailboxes)
1845
1846 def test_get_mailbox_list_two_complex(self):
1847 mailbox_list = self._test_get_x(parser.get_mailbox_list,
1848 ('(foo) "Roy A. Bear" <dinsdale@example.com>(bar),'
1849 ' "Fred Flintstone" <dinsdale@test.(bird)example.com>'),
1850 ('(foo) "Roy A. Bear" <dinsdale@example.com>(bar),'
1851 ' "Fred Flintstone" <dinsdale@test.(bird)example.com>'),
1852 (' "Roy A. Bear" <dinsdale@example.com> ,'
1853 ' "Fred Flintstone" <dinsdale@test. example.com>'),
1854 [errors.ObsoleteHeaderDefect],
1855 '')
1856 self.assertEqual(len(mailbox_list.mailboxes), 2)
1857 self.assertEqual(mailbox_list.mailboxes[0].addr_spec,
1858 'dinsdale@example.com')
1859 self.assertEqual(mailbox_list.mailboxes[0].display_name,
1860 'Roy A. Bear')
1861 self.assertEqual(mailbox_list.mailboxes[1].addr_spec,
1862 'dinsdale@test.example.com')
1863 self.assertEqual(mailbox_list.mailboxes[1].display_name,
1864 'Fred Flintstone')
1865 self.assertEqual(mailbox_list.mailboxes,
1866 mailbox_list.all_mailboxes)
1867
1868 def test_get_mailbox_list_unparseable_mailbox_null(self):
1869 mailbox_list = self._test_get_x(parser.get_mailbox_list,
1870 ('"Roy A. Bear"[] dinsdale@example.com,'
1871 ' "Fred Flintstone" <dinsdale@test.(bird)example.com>'),
1872 ('"Roy A. Bear"[] dinsdale@example.com,'
1873 ' "Fred Flintstone" <dinsdale@test.(bird)example.com>'),
1874 ('"Roy A. Bear"[] dinsdale@example.com,'
1875 ' "Fred Flintstone" <dinsdale@test. example.com>'),
1876 [errors.InvalidHeaderDefect, # the 'extra' text after the local part
1877 errors.InvalidHeaderDefect, # the local part with no angle-addr
1878 errors.ObsoleteHeaderDefect, # period in extra text (example.com)
1879 errors.ObsoleteHeaderDefect], # (bird) in valid address.
1880 '')
1881 self.assertEqual(len(mailbox_list.mailboxes), 1)
1882 self.assertEqual(len(mailbox_list.all_mailboxes), 2)
1883 self.assertEqual(mailbox_list.all_mailboxes[0].token_type,
1884 'invalid-mailbox')
1885 self.assertIsNone(mailbox_list.all_mailboxes[0].display_name)
1886 self.assertEqual(mailbox_list.all_mailboxes[0].local_part,
1887 'Roy A. Bear')
1888 self.assertIsNone(mailbox_list.all_mailboxes[0].domain)
1889 self.assertEqual(mailbox_list.all_mailboxes[0].addr_spec,
1890 '"Roy A. Bear"')
1891 self.assertIs(mailbox_list.all_mailboxes[1],
1892 mailbox_list.mailboxes[0])
1893 self.assertEqual(mailbox_list.mailboxes[0].addr_spec,
1894 'dinsdale@test.example.com')
1895 self.assertEqual(mailbox_list.mailboxes[0].display_name,
1896 'Fred Flintstone')
1897
1898 def test_get_mailbox_list_junk_after_valid_address(self):
1899 mailbox_list = self._test_get_x(parser.get_mailbox_list,
1900 ('"Roy A. Bear" <dinsdale@example.com>@@,'
1901 ' "Fred Flintstone" <dinsdale@test.example.com>'),
1902 ('"Roy A. Bear" <dinsdale@example.com>@@,'
1903 ' "Fred Flintstone" <dinsdale@test.example.com>'),
1904 ('"Roy A. Bear" <dinsdale@example.com>@@,'
1905 ' "Fred Flintstone" <dinsdale@test.example.com>'),
1906 [errors.InvalidHeaderDefect],
1907 '')
1908 self.assertEqual(len(mailbox_list.mailboxes), 1)
1909 self.assertEqual(len(mailbox_list.all_mailboxes), 2)
1910 self.assertEqual(mailbox_list.all_mailboxes[0].addr_spec,
1911 'dinsdale@example.com')
1912 self.assertEqual(mailbox_list.all_mailboxes[0].display_name,
1913 'Roy A. Bear')
1914 self.assertEqual(mailbox_list.all_mailboxes[0].token_type,
1915 'invalid-mailbox')
1916 self.assertIs(mailbox_list.all_mailboxes[1],
1917 mailbox_list.mailboxes[0])
1918 self.assertEqual(mailbox_list.mailboxes[0].addr_spec,
1919 'dinsdale@test.example.com')
1920 self.assertEqual(mailbox_list.mailboxes[0].display_name,
1921 'Fred Flintstone')
1922
1923 def test_get_mailbox_list_empty_list_element(self):
1924 mailbox_list = self._test_get_x(parser.get_mailbox_list,
1925 ('"Roy A. Bear" <dinsdale@example.com>, (bird),,'
1926 ' "Fred Flintstone" <dinsdale@test.example.com>'),
1927 ('"Roy A. Bear" <dinsdale@example.com>, (bird),,'
1928 ' "Fred Flintstone" <dinsdale@test.example.com>'),
1929 ('"Roy A. Bear" <dinsdale@example.com>, ,,'
1930 ' "Fred Flintstone" <dinsdale@test.example.com>'),
1931 [errors.ObsoleteHeaderDefect]*2,
1932 '')
1933 self.assertEqual(len(mailbox_list.mailboxes), 2)
1934 self.assertEqual(mailbox_list.all_mailboxes,
1935 mailbox_list.mailboxes)
1936 self.assertEqual(mailbox_list.all_mailboxes[0].addr_spec,
1937 'dinsdale@example.com')
1938 self.assertEqual(mailbox_list.all_mailboxes[0].display_name,
1939 'Roy A. Bear')
1940 self.assertEqual(mailbox_list.mailboxes[1].addr_spec,
1941 'dinsdale@test.example.com')
1942 self.assertEqual(mailbox_list.mailboxes[1].display_name,
1943 'Fred Flintstone')
1944
1945 def test_get_mailbox_list_only_empty_elements(self):
1946 mailbox_list = self._test_get_x(parser.get_mailbox_list,
1947 '(foo),, (bar)',
1948 '(foo),, (bar)',
1949 ' ,, ',
1950 [errors.ObsoleteHeaderDefect]*3,
1951 '')
1952 self.assertEqual(len(mailbox_list.mailboxes), 0)
1953 self.assertEqual(mailbox_list.all_mailboxes,
1954 mailbox_list.mailboxes)
1955
1956 # get_group_list
1957
1958 def test_get_group_list_cfws_only(self):
1959 group_list = self._test_get_x(parser.get_group_list,
1960 '(hidden);',
1961 '(hidden)',
1962 ' ',
1963 [],
1964 ';')
1965 self.assertEqual(group_list.token_type, 'group-list')
1966 self.assertEqual(len(group_list.mailboxes), 0)
1967 self.assertEqual(group_list.mailboxes,
1968 group_list.all_mailboxes)
1969
1970 def test_get_group_list_mailbox_list(self):
1971 group_list = self._test_get_x(parser.get_group_list,
1972 'dinsdale@example.org, "Fred A. Bear" <dinsdale@example.org>',
1973 'dinsdale@example.org, "Fred A. Bear" <dinsdale@example.org>',
1974 'dinsdale@example.org, "Fred A. Bear" <dinsdale@example.org>',
1975 [],
1976 '')
1977 self.assertEqual(group_list.token_type, 'group-list')
1978 self.assertEqual(len(group_list.mailboxes), 2)
1979 self.assertEqual(group_list.mailboxes,
1980 group_list.all_mailboxes)
1981 self.assertEqual(group_list.mailboxes[1].display_name,
1982 'Fred A. Bear')
1983
1984 def test_get_group_list_obs_group_list(self):
1985 group_list = self._test_get_x(parser.get_group_list,
1986 ', (foo),,(bar)',
1987 ', (foo),,(bar)',
1988 ', ,, ',
1989 [errors.ObsoleteHeaderDefect],
1990 '')
1991 self.assertEqual(group_list.token_type, 'group-list')
1992 self.assertEqual(len(group_list.mailboxes), 0)
1993 self.assertEqual(group_list.mailboxes,
1994 group_list.all_mailboxes)
1995
1996 def test_get_group_list_comment_only_invalid(self):
1997 group_list = self._test_get_x(parser.get_group_list,
1998 '(bar)',
1999 '(bar)',
2000 ' ',
2001 [errors.InvalidHeaderDefect],
2002 '')
2003 self.assertEqual(group_list.token_type, 'group-list')
2004 self.assertEqual(len(group_list.mailboxes), 0)
2005 self.assertEqual(group_list.mailboxes,
2006 group_list.all_mailboxes)
2007
2008 # get_group
2009
2010 def test_get_group_empty(self):
2011 group = self._test_get_x(parser.get_group,
2012 'Monty Python:;',
2013 'Monty Python:;',
2014 'Monty Python:;',
2015 [],
2016 '')
2017 self.assertEqual(group.token_type, 'group')
2018 self.assertEqual(group.display_name, 'Monty Python')
2019 self.assertEqual(len(group.mailboxes), 0)
2020 self.assertEqual(group.mailboxes,
2021 group.all_mailboxes)
2022
R David Murray032eed32012-05-26 14:31:12 -04002023 def test_get_group_null_addr_spec(self):
R David Murray0b6f6c82012-05-25 18:42:14 -04002024 group = self._test_get_x(parser.get_group,
2025 'foo: <>;',
2026 'foo: <>;',
2027 'foo: <>;',
2028 [errors.InvalidHeaderDefect],
2029 '')
2030 self.assertEqual(group.display_name, 'foo')
2031 self.assertEqual(len(group.mailboxes), 0)
2032 self.assertEqual(len(group.all_mailboxes), 1)
2033 self.assertEqual(group.all_mailboxes[0].value, '<>')
2034
2035 def test_get_group_cfws_only(self):
2036 group = self._test_get_x(parser.get_group,
2037 'Monty Python: (hidden);',
2038 'Monty Python: (hidden);',
2039 'Monty Python: ;',
2040 [],
2041 '')
2042 self.assertEqual(group.token_type, 'group')
2043 self.assertEqual(group.display_name, 'Monty Python')
2044 self.assertEqual(len(group.mailboxes), 0)
2045 self.assertEqual(group.mailboxes,
2046 group.all_mailboxes)
2047
2048 def test_get_group_single_mailbox(self):
2049 group = self._test_get_x(parser.get_group,
2050 'Monty Python: "Fred A. Bear" <dinsdale@example.com>;',
2051 'Monty Python: "Fred A. Bear" <dinsdale@example.com>;',
2052 'Monty Python: "Fred A. Bear" <dinsdale@example.com>;',
2053 [],
2054 '')
2055 self.assertEqual(group.token_type, 'group')
2056 self.assertEqual(group.display_name, 'Monty Python')
2057 self.assertEqual(len(group.mailboxes), 1)
2058 self.assertEqual(group.mailboxes,
2059 group.all_mailboxes)
2060 self.assertEqual(group.mailboxes[0].addr_spec,
2061 'dinsdale@example.com')
2062
2063 def test_get_group_mixed_list(self):
2064 group = self._test_get_x(parser.get_group,
2065 ('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2066 '(foo) Roger <ping@exampele.com>, x@test.example.com;'),
2067 ('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2068 '(foo) Roger <ping@exampele.com>, x@test.example.com;'),
2069 ('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2070 ' Roger <ping@exampele.com>, x@test.example.com;'),
2071 [],
2072 '')
2073 self.assertEqual(group.token_type, 'group')
2074 self.assertEqual(group.display_name, 'Monty Python')
2075 self.assertEqual(len(group.mailboxes), 3)
2076 self.assertEqual(group.mailboxes,
2077 group.all_mailboxes)
2078 self.assertEqual(group.mailboxes[0].display_name,
2079 'Fred A. Bear')
2080 self.assertEqual(group.mailboxes[1].display_name,
2081 'Roger')
2082 self.assertEqual(group.mailboxes[2].local_part, 'x')
2083
2084 def test_get_group_one_invalid(self):
2085 group = self._test_get_x(parser.get_group,
2086 ('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2087 '(foo) Roger ping@exampele.com, x@test.example.com;'),
2088 ('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2089 '(foo) Roger ping@exampele.com, x@test.example.com;'),
2090 ('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2091 ' Roger ping@exampele.com, x@test.example.com;'),
2092 [errors.InvalidHeaderDefect, # non-angle addr makes local part invalid
2093 errors.InvalidHeaderDefect], # and its not obs-local either: no dots.
2094 '')
2095 self.assertEqual(group.token_type, 'group')
2096 self.assertEqual(group.display_name, 'Monty Python')
2097 self.assertEqual(len(group.mailboxes), 2)
2098 self.assertEqual(len(group.all_mailboxes), 3)
2099 self.assertEqual(group.mailboxes[0].display_name,
2100 'Fred A. Bear')
2101 self.assertEqual(group.mailboxes[1].local_part, 'x')
2102 self.assertIsNone(group.all_mailboxes[1].display_name)
2103
2104 # get_address
2105
2106 def test_get_address_simple(self):
2107 address = self._test_get_x(parser.get_address,
2108 'dinsdale@example.com',
2109 'dinsdale@example.com',
2110 'dinsdale@example.com',
2111 [],
2112 '')
2113 self.assertEqual(address.token_type, 'address')
2114 self.assertEqual(len(address.mailboxes), 1)
2115 self.assertEqual(address.mailboxes,
2116 address.all_mailboxes)
2117 self.assertEqual(address.mailboxes[0].domain,
2118 'example.com')
2119 self.assertEqual(address[0].token_type,
2120 'mailbox')
2121
2122 def test_get_address_complex(self):
2123 address = self._test_get_x(parser.get_address,
2124 '(foo) "Fred A. Bear" <(bird)dinsdale@example.com>',
2125 '(foo) "Fred A. Bear" <(bird)dinsdale@example.com>',
2126 ' "Fred A. Bear" < dinsdale@example.com>',
2127 [],
2128 '')
2129 self.assertEqual(address.token_type, 'address')
2130 self.assertEqual(len(address.mailboxes), 1)
2131 self.assertEqual(address.mailboxes,
2132 address.all_mailboxes)
2133 self.assertEqual(address.mailboxes[0].display_name,
2134 'Fred A. Bear')
2135 self.assertEqual(address[0].token_type,
2136 'mailbox')
2137
2138 def test_get_address_empty_group(self):
2139 address = self._test_get_x(parser.get_address,
2140 'Monty Python:;',
2141 'Monty Python:;',
2142 'Monty Python:;',
2143 [],
2144 '')
2145 self.assertEqual(address.token_type, 'address')
2146 self.assertEqual(len(address.mailboxes), 0)
2147 self.assertEqual(address.mailboxes,
2148 address.all_mailboxes)
2149 self.assertEqual(address[0].token_type,
2150 'group')
2151 self.assertEqual(address[0].display_name,
2152 'Monty Python')
2153
2154 def test_get_address_group(self):
2155 address = self._test_get_x(parser.get_address,
2156 'Monty Python: x@example.com, y@example.com;',
2157 'Monty Python: x@example.com, y@example.com;',
2158 'Monty Python: x@example.com, y@example.com;',
2159 [],
2160 '')
2161 self.assertEqual(address.token_type, 'address')
2162 self.assertEqual(len(address.mailboxes), 2)
2163 self.assertEqual(address.mailboxes,
2164 address.all_mailboxes)
2165 self.assertEqual(address[0].token_type,
2166 'group')
2167 self.assertEqual(address[0].display_name,
2168 'Monty Python')
2169 self.assertEqual(address.mailboxes[0].local_part, 'x')
2170
2171 def test_get_address_quoted_local_part(self):
2172 address = self._test_get_x(parser.get_address,
2173 '"foo bar"@example.com',
2174 '"foo bar"@example.com',
2175 '"foo bar"@example.com',
2176 [],
2177 '')
2178 self.assertEqual(address.token_type, 'address')
2179 self.assertEqual(len(address.mailboxes), 1)
2180 self.assertEqual(address.mailboxes,
2181 address.all_mailboxes)
2182 self.assertEqual(address.mailboxes[0].domain,
2183 'example.com')
2184 self.assertEqual(address.mailboxes[0].local_part,
2185 'foo bar')
2186 self.assertEqual(address[0].token_type, 'mailbox')
2187
2188 def test_get_address_ends_at_special(self):
2189 address = self._test_get_x(parser.get_address,
2190 'dinsdale@example.com, next',
2191 'dinsdale@example.com',
2192 'dinsdale@example.com',
2193 [],
2194 ', next')
2195 self.assertEqual(address.token_type, 'address')
2196 self.assertEqual(len(address.mailboxes), 1)
2197 self.assertEqual(address.mailboxes,
2198 address.all_mailboxes)
2199 self.assertEqual(address.mailboxes[0].domain,
2200 'example.com')
2201 self.assertEqual(address[0].token_type, 'mailbox')
2202
2203 def test_get_address_invalid_mailbox_invalid(self):
2204 address = self._test_get_x(parser.get_address,
2205 'ping example.com, next',
2206 'ping example.com',
2207 'ping example.com',
2208 [errors.InvalidHeaderDefect, # addr-spec with no domain
2209 errors.InvalidHeaderDefect, # invalid local-part
2210 errors.InvalidHeaderDefect, # missing .s in local-part
2211 ],
2212 ', next')
2213 self.assertEqual(address.token_type, 'address')
2214 self.assertEqual(len(address.mailboxes), 0)
2215 self.assertEqual(len(address.all_mailboxes), 1)
2216 self.assertIsNone(address.all_mailboxes[0].domain)
2217 self.assertEqual(address.all_mailboxes[0].local_part, 'ping example.com')
2218 self.assertEqual(address[0].token_type, 'invalid-mailbox')
2219
2220 def test_get_address_quoted_strings_in_atom_list(self):
2221 address = self._test_get_x(parser.get_address,
2222 '""example" example"@example.com',
2223 '""example" example"@example.com',
2224 'example example@example.com',
2225 [errors.InvalidHeaderDefect]*3,
2226 '')
2227 self.assertEqual(address.all_mailboxes[0].local_part, 'example example')
2228 self.assertEqual(address.all_mailboxes[0].domain, 'example.com')
2229 self.assertEqual(address.all_mailboxes[0].addr_spec, '"example example"@example.com')
2230
2231
2232 # get_address_list
2233
2234 def test_get_address_list_mailboxes_simple(self):
2235 address_list = self._test_get_x(parser.get_address_list,
2236 'dinsdale@example.com',
2237 'dinsdale@example.com',
2238 'dinsdale@example.com',
2239 [],
2240 '')
2241 self.assertEqual(address_list.token_type, 'address-list')
2242 self.assertEqual(len(address_list.mailboxes), 1)
2243 self.assertEqual(address_list.mailboxes,
2244 address_list.all_mailboxes)
2245 self.assertEqual([str(x) for x in address_list.mailboxes],
2246 [str(x) for x in address_list.addresses])
2247 self.assertEqual(address_list.mailboxes[0].domain, 'example.com')
2248 self.assertEqual(address_list[0].token_type, 'address')
2249 self.assertIsNone(address_list[0].display_name)
2250
2251 def test_get_address_list_mailboxes_two_simple(self):
2252 address_list = self._test_get_x(parser.get_address_list,
2253 'foo@example.com, "Fred A. Bar" <bar@example.com>',
2254 'foo@example.com, "Fred A. Bar" <bar@example.com>',
2255 'foo@example.com, "Fred A. Bar" <bar@example.com>',
2256 [],
2257 '')
2258 self.assertEqual(address_list.token_type, 'address-list')
2259 self.assertEqual(len(address_list.mailboxes), 2)
2260 self.assertEqual(address_list.mailboxes,
2261 address_list.all_mailboxes)
2262 self.assertEqual([str(x) for x in address_list.mailboxes],
2263 [str(x) for x in address_list.addresses])
2264 self.assertEqual(address_list.mailboxes[0].local_part, 'foo')
2265 self.assertEqual(address_list.mailboxes[1].display_name, "Fred A. Bar")
2266
2267 def test_get_address_list_mailboxes_complex(self):
2268 address_list = self._test_get_x(parser.get_address_list,
2269 ('"Roy A. Bear" <dinsdale@example.com>, '
2270 '(ping) Foo <x@example.com>,'
2271 'Nobody Is. Special <y@(bird)example.(bad)com>'),
2272 ('"Roy A. Bear" <dinsdale@example.com>, '
2273 '(ping) Foo <x@example.com>,'
2274 'Nobody Is. Special <y@(bird)example.(bad)com>'),
2275 ('"Roy A. Bear" <dinsdale@example.com>, '
2276 'Foo <x@example.com>,'
2277 '"Nobody Is. Special" <y@example. com>'),
2278 [errors.ObsoleteHeaderDefect, # period in Is.
2279 errors.ObsoleteHeaderDefect], # cfws in domain
2280 '')
2281 self.assertEqual(address_list.token_type, 'address-list')
2282 self.assertEqual(len(address_list.mailboxes), 3)
2283 self.assertEqual(address_list.mailboxes,
2284 address_list.all_mailboxes)
2285 self.assertEqual([str(x) for x in address_list.mailboxes],
2286 [str(x) for x in address_list.addresses])
2287 self.assertEqual(address_list.mailboxes[0].domain, 'example.com')
2288 self.assertEqual(address_list.mailboxes[0].token_type, 'mailbox')
2289 self.assertEqual(address_list.addresses[0].token_type, 'address')
2290 self.assertEqual(address_list.mailboxes[1].local_part, 'x')
2291 self.assertEqual(address_list.mailboxes[2].display_name,
2292 'Nobody Is. Special')
2293
2294 def test_get_address_list_mailboxes_invalid_addresses(self):
2295 address_list = self._test_get_x(parser.get_address_list,
2296 ('"Roy A. Bear" <dinsdale@example.com>, '
2297 '(ping) Foo x@example.com[],'
2298 'Nobody Is. Special <(bird)example.(bad)com>'),
2299 ('"Roy A. Bear" <dinsdale@example.com>, '
2300 '(ping) Foo x@example.com[],'
2301 'Nobody Is. Special <(bird)example.(bad)com>'),
2302 ('"Roy A. Bear" <dinsdale@example.com>, '
2303 'Foo x@example.com[],'
2304 '"Nobody Is. Special" < example. com>'),
2305 [errors.InvalidHeaderDefect, # invalid address in list
2306 errors.InvalidHeaderDefect, # 'Foo x' local part invalid.
2307 errors.InvalidHeaderDefect, # Missing . in 'Foo x' local part
2308 errors.ObsoleteHeaderDefect, # period in 'Is.' disp-name phrase
2309 errors.InvalidHeaderDefect, # no domain part in addr-spec
2310 errors.ObsoleteHeaderDefect], # addr-spec has comment in it
2311 '')
2312 self.assertEqual(address_list.token_type, 'address-list')
2313 self.assertEqual(len(address_list.mailboxes), 1)
2314 self.assertEqual(len(address_list.all_mailboxes), 3)
2315 self.assertEqual([str(x) for x in address_list.all_mailboxes],
2316 [str(x) for x in address_list.addresses])
2317 self.assertEqual(address_list.mailboxes[0].domain, 'example.com')
2318 self.assertEqual(address_list.mailboxes[0].token_type, 'mailbox')
2319 self.assertEqual(address_list.addresses[0].token_type, 'address')
2320 self.assertEqual(address_list.addresses[1].token_type, 'address')
2321 self.assertEqual(len(address_list.addresses[0].mailboxes), 1)
2322 self.assertEqual(len(address_list.addresses[1].mailboxes), 0)
2323 self.assertEqual(len(address_list.addresses[1].mailboxes), 0)
2324 self.assertEqual(
2325 address_list.addresses[1].all_mailboxes[0].local_part, 'Foo x')
2326 self.assertEqual(
2327 address_list.addresses[2].all_mailboxes[0].display_name,
2328 "Nobody Is. Special")
2329
2330 def test_get_address_list_group_empty(self):
2331 address_list = self._test_get_x(parser.get_address_list,
2332 'Monty Python: ;',
2333 'Monty Python: ;',
2334 'Monty Python: ;',
2335 [],
2336 '')
2337 self.assertEqual(address_list.token_type, 'address-list')
2338 self.assertEqual(len(address_list.mailboxes), 0)
2339 self.assertEqual(address_list.mailboxes,
2340 address_list.all_mailboxes)
2341 self.assertEqual(len(address_list.addresses), 1)
2342 self.assertEqual(address_list.addresses[0].token_type, 'address')
2343 self.assertEqual(address_list.addresses[0].display_name, 'Monty Python')
2344 self.assertEqual(len(address_list.addresses[0].mailboxes), 0)
2345
2346 def test_get_address_list_group_simple(self):
2347 address_list = self._test_get_x(parser.get_address_list,
2348 'Monty Python: dinsdale@example.com;',
2349 'Monty Python: dinsdale@example.com;',
2350 'Monty Python: dinsdale@example.com;',
2351 [],
2352 '')
2353 self.assertEqual(address_list.token_type, 'address-list')
2354 self.assertEqual(len(address_list.mailboxes), 1)
2355 self.assertEqual(address_list.mailboxes,
2356 address_list.all_mailboxes)
2357 self.assertEqual(address_list.mailboxes[0].domain, 'example.com')
2358 self.assertEqual(address_list.addresses[0].display_name,
2359 'Monty Python')
2360 self.assertEqual(address_list.addresses[0].mailboxes[0].domain,
2361 'example.com')
2362
2363 def test_get_address_list_group_and_mailboxes(self):
2364 address_list = self._test_get_x(parser.get_address_list,
2365 ('Monty Python: dinsdale@example.com, "Fred" <flint@example.com>;, '
2366 'Abe <x@example.com>, Bee <y@example.com>'),
2367 ('Monty Python: dinsdale@example.com, "Fred" <flint@example.com>;, '
2368 'Abe <x@example.com>, Bee <y@example.com>'),
2369 ('Monty Python: dinsdale@example.com, "Fred" <flint@example.com>;, '
2370 'Abe <x@example.com>, Bee <y@example.com>'),
2371 [],
2372 '')
2373 self.assertEqual(address_list.token_type, 'address-list')
2374 self.assertEqual(len(address_list.mailboxes), 4)
2375 self.assertEqual(address_list.mailboxes,
2376 address_list.all_mailboxes)
2377 self.assertEqual(len(address_list.addresses), 3)
2378 self.assertEqual(address_list.mailboxes[0].local_part, 'dinsdale')
2379 self.assertEqual(address_list.addresses[0].display_name,
2380 'Monty Python')
2381 self.assertEqual(address_list.addresses[0].mailboxes[0].domain,
2382 'example.com')
2383 self.assertEqual(address_list.addresses[0].mailboxes[1].local_part,
2384 'flint')
2385 self.assertEqual(address_list.addresses[1].mailboxes[0].local_part,
2386 'x')
2387 self.assertEqual(address_list.addresses[2].mailboxes[0].local_part,
2388 'y')
2389 self.assertEqual(str(address_list.addresses[1]),
2390 str(address_list.mailboxes[2]))
2391
2392
2393class TestFolding(TestEmailBase):
2394
2395 policy = policy.default
2396
2397 def _test(self, tl, folded, policy=policy):
2398 self.assertEqual(tl.fold(policy=policy), folded, tl.ppstr())
2399
2400 def test_simple_unstructured_no_folds(self):
2401 self._test(parser.get_unstructured("This is a test"),
2402 "This is a test\n")
2403
2404 def test_simple_unstructured_folded(self):
2405 self._test(parser.get_unstructured("This is also a test, but this "
2406 "time there are enough words (and even some "
2407 "symbols) to make it wrap; at least in theory."),
2408 "This is also a test, but this time there are enough "
2409 "words (and even some\n"
2410 " symbols) to make it wrap; at least in theory.\n")
2411
2412 def test_unstructured_with_unicode_no_folds(self):
2413 self._test(parser.get_unstructured("hübsch kleiner beißt"),
2414 "=?utf-8?q?h=C3=BCbsch_kleiner_bei=C3=9Ft?=\n")
2415
2416 def test_one_ew_on_each_of_two_wrapped_lines(self):
2417 self._test(parser.get_unstructured("Mein kleiner Kaktus ist sehr "
2418 "hübsch. Es hat viele Stacheln "
2419 "und oft beißt mich."),
2420 "Mein kleiner Kaktus ist sehr =?utf-8?q?h=C3=BCbsch=2E?= "
2421 "Es hat viele Stacheln\n"
2422 " und oft =?utf-8?q?bei=C3=9Ft?= mich.\n")
2423
2424 def test_ews_combined_before_wrap(self):
2425 self._test(parser.get_unstructured("Mein Kaktus ist hübsch. "
2426 "Es beißt mich. "
2427 "And that's all I'm sayin."),
2428 "Mein Kaktus ist =?utf-8?q?h=C3=BCbsch=2E__Es_bei=C3=9Ft?= "
2429 "mich. And that's\n"
2430 " all I'm sayin.\n")
2431
2432 # XXX Need test of an encoded word so long that it needs to be wrapped
2433
2434 def test_simple_address(self):
2435 self._test(parser.get_address_list("abc <xyz@example.com>")[0],
2436 "abc <xyz@example.com>\n")
2437
2438 def test_address_list_folding_at_commas(self):
2439 self._test(parser.get_address_list('abc <xyz@example.com>, '
2440 '"Fred Blunt" <sharp@example.com>, '
2441 '"J.P.Cool" <hot@example.com>, '
2442 '"K<>y" <key@example.com>, '
2443 'Firesale <cheap@example.com>, '
2444 '<end@example.com>')[0],
2445 'abc <xyz@example.com>, "Fred Blunt" <sharp@example.com>,\n'
2446 ' "J.P.Cool" <hot@example.com>, "K<>y" <key@example.com>,\n'
2447 ' Firesale <cheap@example.com>, <end@example.com>\n')
2448
2449 def test_address_list_with_unicode_names(self):
2450 self._test(parser.get_address_list(
2451 'Hübsch Kaktus <beautiful@example.com>, '
2452 'beißt beißt <biter@example.com>')[0],
2453 '=?utf-8?q?H=C3=BCbsch?= Kaktus <beautiful@example.com>,\n'
2454 ' =?utf-8?q?bei=C3=9Ft_bei=C3=9Ft?= <biter@example.com>\n')
2455
2456 def test_address_list_with_unicode_names_in_quotes(self):
2457 self._test(parser.get_address_list(
2458 '"Hübsch Kaktus" <beautiful@example.com>, '
2459 '"beißt" beißt <biter@example.com>')[0],
2460 '=?utf-8?q?H=C3=BCbsch?= Kaktus <beautiful@example.com>,\n'
2461 ' =?utf-8?q?bei=C3=9Ft_bei=C3=9Ft?= <biter@example.com>\n')
2462
2463 # XXX Need tests with comments on various sides of a unicode token,
2464 # and with unicode tokens in the comments. Spaces inside the quotes
2465 # currently don't do the right thing.
2466
2467 def test_initial_whitespace_splitting(self):
2468 body = parser.get_unstructured(' ' + 'x'*77)
2469 header = parser.Header([
2470 parser.HeaderLabel([parser.ValueTerminal('test:', 'atext')]),
2471 parser.CFWSList([parser.WhiteSpaceTerminal(' ', 'fws')]), body])
2472 self._test(header, 'test: \n ' + 'x'*77 + '\n')
2473
2474 def test_whitespace_splitting(self):
2475 self._test(parser.get_unstructured('xxx ' + 'y'*77),
2476 'xxx \n ' + 'y'*77 + '\n')
2477
2478if __name__ == '__main__':
2479 unittest.main()