From b132b77fb11a6c9b8de5cf0f4afb8acc7f57a96c Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Sat, 15 Jul 2023 02:48:01 -0700 Subject: [PATCH] [3.11] gh-106368: Increase Argument Clinic BlockParser test coverage (GH-106759) (#106770) (cherry picked from commit 2d7d1aa4bcd5da0177458b22b1b856db76aa20d4) Co-authored-by: Erlend E. Aasland --- Lib/test/test_clinic.py | 100 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index fa65a41ec30d06..0e3fbb7627ab5a 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -18,6 +18,19 @@ from clinic import DSLParser +class _ParserBase(TestCase): + maxDiff = None + + def expect_parser_failure(self, parser, _input): + with support.captured_stdout() as stdout: + with self.assertRaises(SystemExit): + parser(_input) + return stdout.getvalue() + + def parse_function_should_fail(self, _input): + return self.expect_parser_failure(self.parse_function, _input) + + class FakeConverter: def __init__(self, name, args): self.name = name @@ -88,7 +101,15 @@ def directive(self, name, args): _module_and_class = clinic.Clinic._module_and_class -class ClinicWholeFileTest(TestCase): + +class ClinicWholeFileTest(_ParserBase): + def setUp(self): + self.clinic = clinic.Clinic(clinic.CLanguage(None), filename="test.c") + + def expect_failure(self, raw): + _input = dedent(raw).strip() + return self.expect_parser_failure(self.clinic.parse, _input) + def test_eol(self): # regression test: # clinic's block parser didn't recognize @@ -98,15 +119,86 @@ def test_eol(self): # so it would spit out an end line for you. # and since you really already had one, # the last line of the block got corrupted. - c = clinic.Clinic(clinic.CLanguage(None), filename="file") raw = "/*[clinic]\nfoo\n[clinic]*/" - cooked = c.parse(raw).splitlines() + cooked = self.clinic.parse(raw).splitlines() end_line = cooked[2].rstrip() # this test is redundant, it's just here explicitly to catch # the regression test so we don't forget what it looked like self.assertNotEqual(end_line, "[clinic]*/[clinic]*/") self.assertEqual(end_line, "[clinic]*/") + def test_mangled_marker_line(self): + raw = """ + /*[clinic input] + [clinic start generated code]*/ + /*[clinic end generated code: foo]*/ + """ + msg = ( + 'Error in file "test.c" on line 3:\n' + "Mangled Argument Clinic marker line: '/*[clinic end generated code: foo]*/'\n" + ) + out = self.expect_failure(raw) + self.assertEqual(out, msg) + + def test_checksum_mismatch(self): + raw = """ + /*[clinic input] + [clinic start generated code]*/ + /*[clinic end generated code: output=0123456789abcdef input=fedcba9876543210]*/ + """ + msg = ( + 'Error in file "test.c" on line 3:\n' + 'Checksum mismatch!\n' + 'Expected: 0123456789abcdef\n' + 'Computed: da39a3ee5e6b4b0d\n' + ) + out = self.expect_failure(raw) + self.assertIn(msg, out) + + def test_garbage_after_stop_line(self): + raw = """ + /*[clinic input] + [clinic start generated code]*/foobarfoobar! + """ + msg = ( + 'Error in file "test.c" on line 2:\n' + "Garbage after stop line: 'foobarfoobar!'\n" + ) + out = self.expect_failure(raw) + self.assertEqual(out, msg) + + def test_whitespace_before_stop_line(self): + raw = """ + /*[clinic input] + [clinic start generated code]*/ + """ + msg = ( + 'Error in file "test.c" on line 2:\n' + "Whitespace is not allowed before the stop line: ' [clinic start generated code]*/'\n" + ) + out = self.expect_failure(raw) + self.assertEqual(out, msg) + + def test_parse_with_body_prefix(self): + clang = clinic.CLanguage(None) + clang.body_prefix = "//" + clang.start_line = "//[{dsl_name} start]" + clang.stop_line = "//[{dsl_name} stop]" + cl = clinic.Clinic(clang, filename="test.c") + raw = dedent(""" + //[clinic start] + //module test + //[clinic stop] + """).strip() + out = cl.parse(raw) + expected = dedent(""" + //[clinic start] + //module test + // + //[clinic stop] + /*[clinic end generated code: output=da39a3ee5e6b4b0d input=65fab8adff58cf08]*/ + """).lstrip() # Note, lstrip() because of the newline + self.assertEqual(out, expected) class ClinicGroupPermuterTest(TestCase): @@ -285,7 +377,7 @@ def test_clinic_1(self): """) -class ClinicParserTest(TestCase): +class ClinicParserTest(_ParserBase): def checkDocstring(self, fn, expected): self.assertTrue(hasattr(fn, "docstring")) self.assertEqual(fn.docstring.strip(),