Skip to content

Commit 9ec2cce

Browse files
committed
Improve msgfmt.py test coverage
1 parent f237953 commit 9ec2cce

File tree

1 file changed

+356
-0
lines changed

1 file changed

+356
-0
lines changed

Lib/test/test_tools/test_msgfmt.py

Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,362 @@ def test_strings(self):
240240
with self.assertRaises(Exception):
241241
msgfmt.make('messages.po', 'messages.mo')
242242

243+
def test_general_syntax_errors(self):
244+
invalid_po_files = (
245+
'',
246+
'"',
247+
'""',
248+
'"foo"',
249+
# 'msgid', # invalid but currently accepted
250+
'msgstr',
251+
'msgid_plural',
252+
# 'msgctxt', # invalid but currently accepted
253+
'msgstr',
254+
'msgstr[0]',
255+
'[0]',
256+
257+
# unclosed string
258+
'''
259+
msgid "
260+
msgstr "bar"
261+
''',
262+
263+
# unclosed string
264+
'''
265+
msgid "foo
266+
msgstr "bar"
267+
''',
268+
269+
# unclosed string
270+
'''
271+
msgid "foo" "
272+
msgstr "bar"
273+
''',
274+
275+
# unclosed string
276+
'''
277+
msgid "foo"
278+
"
279+
msgstr "bar"
280+
''',
281+
282+
# illegal backslash
283+
'''
284+
msgid "foo\\"
285+
"
286+
msgstr "bar"
287+
''',
288+
289+
# msgid with an index
290+
'''
291+
msgid[0] "foo"
292+
msgstr "bar"
293+
''',
294+
295+
# invalid plural index
296+
# invalid but currently accepted
297+
# '''
298+
# msgid "foo"
299+
# msgid_plural "foos"
300+
# msgstr[foo] "baz"
301+
# ''',
302+
303+
# invalid plural index
304+
'''
305+
msgid "foo"
306+
msgid_plural "foos"
307+
msgstr[0 "baz"
308+
''',
309+
310+
# invalid plural index
311+
# invalid but currently accepted
312+
# '''
313+
# msgid "foo"
314+
# msgid_plural "foos"
315+
# msgstr[] "baz"
316+
# ''',
317+
318+
# invalid plural index
319+
'''
320+
msgid "foo"
321+
msgid_plural "foos"
322+
msgstr1] "baz"
323+
''',
324+
325+
# invalid plural index
326+
'''
327+
msgid "foo"
328+
msgid_plural "foos"
329+
msgstr[[0]] "baz"
330+
''',
331+
)
332+
with temp_cwd():
333+
for invalid_po in invalid_po_files:
334+
with self.subTest(invalid_po=invalid_po):
335+
Path('messages.po').write_text(invalid_po)
336+
# Reset the global MESSAGES dictionary
337+
msgfmt.MESSAGES.clear()
338+
with self.assertRaises((SystemExit, UnboundLocalError,
339+
IndexError, SyntaxError)):
340+
msgfmt.make('messages.po', 'messages.mo')
341+
342+
def test_semantic_errors(self):
343+
invalid_po_files = (
344+
# missing msgid after msgctxt
345+
# invalid but currently accepted
346+
# 'msgctxt "foo"',
347+
348+
# missing msgstr after msgid
349+
# invalid but currently accepted
350+
# 'msgid "foo"',
351+
352+
# comment line not allowed after msgctxt
353+
# invalid but currently accepted
354+
# '''
355+
# msgctxt "foo"
356+
# # comment
357+
# msgid "bar"
358+
# msgstr "bar"
359+
# ''',
360+
361+
# comment line not allowed after msgid
362+
# invalid but currently accepted
363+
# '''
364+
# msgid "foo"
365+
# # comment
366+
# msgstr "bar"
367+
# ''',
368+
369+
# comment line not allowed after msgid_plural
370+
# invalid but currently accepted
371+
# '''
372+
# msgid "foo"
373+
# msgid_plural "foos"
374+
# # comment
375+
# msgstr[0] "bar"
376+
# ''',
377+
378+
# msgctxt not allowed after msgctxt
379+
# invalid but currently accepted
380+
# '''
381+
# msgctxt "foo"
382+
383+
# msgctxt "bar"
384+
# msgid "foo"
385+
# msgstr "bar"
386+
# ''',
387+
388+
# msgctxt not allowed after msgid
389+
# invalid but currently accepted
390+
# '''
391+
# msgid "foo"
392+
# msgctxt "bar"
393+
394+
# msgid "bar"
395+
# msgstr "baz"
396+
# ''',
397+
398+
# msgctxt not allowed after msgid_plural
399+
# invalid but currently accepted
400+
# '''
401+
# msgid "foo"
402+
# msgid_plural "foos"
403+
# msgctxt "bar"
404+
405+
# msgid "bar"
406+
# msgstr "baz"
407+
# ''',
408+
409+
# msgid not allowed after msgid
410+
# invalid but currently accepted
411+
# '''
412+
# msgid "foo"
413+
414+
# msgid "bar"
415+
# msgstr "baz"
416+
# ''',
417+
418+
# msgid not allowed after msgid_plural
419+
# invalid but currently accepted
420+
# '''
421+
# msgid "foo"
422+
# msgid_plural "foos"
423+
424+
# msgid "bar"
425+
# msgstr "baz"
426+
# ''',
427+
428+
# msgid_plural must be preceded by msgid
429+
'''
430+
msgid_plural "foos"
431+
432+
msgid "bar"
433+
msgstr "baz"
434+
''',
435+
436+
# msgid_plural not allowed after comment
437+
'''
438+
# comment
439+
msgid_plural "foos"
440+
441+
msgid "bar"
442+
msgstr "baz"
443+
''',
444+
445+
# msgid_plural not allowed after msgid_plural
446+
# invalid but currently accepted
447+
# '''
448+
# msgid "foo"
449+
# msgid_plural "foos"
450+
# msgid_plural "bars"
451+
452+
# msgid "bar"
453+
# msgstr "baz"
454+
# ''',
455+
456+
# msgid_plural not allowed after msgctxt
457+
'''
458+
msgctxt "foo"
459+
msgid_plural "foos"
460+
461+
msgid "bar"
462+
msgstr "baz"
463+
''',
464+
465+
# msgid_plural not allowed after msgstr
466+
'''
467+
msgid "foo"
468+
msgstr "bar"
469+
msgid_plural "foos"
470+
471+
msgid "bar"
472+
msgstr "baz"
473+
''',
474+
475+
# msgstr must be preceded by msgid
476+
'''
477+
msgstr "foo"
478+
479+
msgid "bar"
480+
msgstr "baz"
481+
''',
482+
483+
# msgstr not allowed after comment
484+
# invalid but currently accepted
485+
# '''
486+
# # comment
487+
# # msgstr "foo"
488+
489+
# msgid "bar"
490+
# msgstr "baz"
491+
# ''',
492+
493+
# msgstr not allowed after msgctxt
494+
'''
495+
msgctxt "foo"
496+
msgstr "bar"
497+
498+
msgid "foo"
499+
msgstr "bar"
500+
''',
501+
502+
# msgstr not allowed after msgstr
503+
# invalid but currently accepted
504+
# '''
505+
# msgid "foo"
506+
# msgstr "bar"
507+
# msgstr "baz"
508+
509+
# msgid "bar"
510+
# msgstr "baz"
511+
# ''',
512+
513+
# missing msgid_plural section
514+
'''
515+
msgid "foo"
516+
msgstr[0] "bar"
517+
518+
msgid "bar"
519+
msgstr "baz"
520+
'''
521+
)
522+
with temp_cwd():
523+
for invalid_po in invalid_po_files:
524+
with self.subTest(invalid_po=invalid_po):
525+
Path('messages.po').write_text(invalid_po)
526+
# Reset the global MESSAGES dictionary
527+
msgfmt.MESSAGES.clear()
528+
with self.assertRaises((SystemExit, UnboundLocalError)):
529+
msgfmt.make('messages.po', 'messages.mo')
530+
531+
def test_msgstr_invalid_indices(self):
532+
invalid_po_files = (
533+
# wrong plural form index
534+
# invalid but currently accepted
535+
# '''
536+
# msgid "foo"
537+
# msgid_plural "foos"
538+
# msgstr[42] "bar"
539+
# ''',
540+
541+
# wrong plural form index
542+
# invalid but currently accepted
543+
# '''
544+
# msgid "foo"
545+
# msgid_plural "foos"
546+
# msgstr[0] "bar"
547+
# msgstr[42] "bars"
548+
# ''',
549+
550+
# msgstr not pluralized
551+
'''
552+
msgid "foo"
553+
msgid_plural "foos"
554+
msgstr "bar"
555+
''',
556+
)
557+
with temp_cwd():
558+
for invalid_po in invalid_po_files:
559+
with self.subTest(invalid_po=invalid_po):
560+
Path('messages.po').write_text(invalid_po)
561+
# Reset the global MESSAGES dictionary
562+
msgfmt.MESSAGES.clear()
563+
with self.assertRaises(SystemExit):
564+
msgfmt.make('messages.po', 'messages.mo')
565+
566+
def test_duplicate_entries(self):
567+
invalid_po_files = (
568+
# duplicate msgid
569+
# invalid but currently accepted
570+
# '''
571+
# msgid "foo"
572+
# msgstr "bar"
573+
574+
# msgid "foo"
575+
# msgstr "baz"
576+
# ''',
577+
578+
# duplicate msgctxt+msgid
579+
# invalid but currently accepted
580+
# '''
581+
# msgctxt "context"
582+
# msgid "foo"
583+
# msgstr "bar"
584+
585+
# msgctxt "context"
586+
# msgid "foo"
587+
# msgstr "baz"
588+
# '''
589+
)
590+
with temp_cwd():
591+
for invalid_po in invalid_po_files:
592+
with self.subTest(invalid_po=invalid_po):
593+
Path('messages.po').write_text(invalid_po)
594+
# Reset the global MESSAGES dictionary
595+
msgfmt.MESSAGES.clear()
596+
with self.assertRaises(SystemExit):
597+
msgfmt.make('messages.po', 'messages.mo')
598+
243599

244600
class CLITest(unittest.TestCase):
245601

0 commit comments

Comments
 (0)