From 16111707480c4ec3a73201f500bf1bb8b1ff1c0a Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 14 Jul 2023 23:33:24 +0200 Subject: [PATCH 1/3] gh-106368: Increase Argument Clinic BlockParser test coverage --- Lib/test/test_clinic.py | 91 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 975840333e5901..5c2c3d0338765c 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,14 @@ 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, _input): + return self.expect_parser_failure(self.clinic.parse, _input) + def test_eol(self): # regression test: # clinic's block parser didn't recognize @@ -98,15 +118,78 @@ 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 = dedent(""" + /*[clinic input] + [clinic start generated code]*/ + /*[clinic end generated code: foo]*/ + """).strip() + 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 = dedent(""" + /*[clinic input] + [clinic start generated code]*/ + /*[clinic end generated code: output=0123456789abcdef input=fedcba9876543210]*/ + """).strip() + 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 = dedent(""" + /*[clinic input] + [clinic start generated code]*/foobarfoobar! + """).strip() + 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 = dedent(""" + /*[clinic input] + [clinic start generated code]*/ + """).strip() + 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] + """) + cl.parse(raw) class ClinicGroupPermuterTest(TestCase): @@ -285,7 +368,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(), From c7caf0577dcf93a8b0b605355dad43ff3a9dec95 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 15 Jul 2023 10:29:57 +0200 Subject: [PATCH 2/3] Address Nikita's review: Let expect_failure() dedent and strip input string --- Lib/test/test_clinic.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 5c2c3d0338765c..84095a2c04f8b8 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -106,7 +106,8 @@ class ClinicWholeFileTest(_ParserBase): def setUp(self): self.clinic = clinic.Clinic(clinic.CLanguage(None), filename="test.c") - def expect_failure(self, _input): + def expect_failure(self, raw): + _input = dedent(raw).strip() return self.expect_parser_failure(self.clinic.parse, _input) def test_eol(self): @@ -127,11 +128,11 @@ def test_eol(self): self.assertEqual(end_line, "[clinic]*/") def test_mangled_marker_line(self): - raw = dedent(""" + raw = """ /*[clinic input] [clinic start generated code]*/ /*[clinic end generated code: foo]*/ - """).strip() + """ msg = ( 'Error in file "test.c" on line 3:\n' "Mangled Argument Clinic marker line: '/*[clinic end generated code: foo]*/'\n" @@ -140,11 +141,11 @@ def test_mangled_marker_line(self): self.assertEqual(out, msg) def test_checksum_mismatch(self): - raw = dedent(""" + raw = """ /*[clinic input] [clinic start generated code]*/ /*[clinic end generated code: output=0123456789abcdef input=fedcba9876543210]*/ - """).strip() + """ msg = ( 'Error in file "test.c" on line 3:\n' 'Checksum mismatch!\n' @@ -155,10 +156,10 @@ def test_checksum_mismatch(self): self.assertIn(msg, out) def test_garbage_after_stop_line(self): - raw = dedent(""" + raw = """ /*[clinic input] [clinic start generated code]*/foobarfoobar! - """).strip() + """ msg = ( 'Error in file "test.c" on line 2:\n' "Garbage after stop line: 'foobarfoobar!'\n" @@ -167,10 +168,10 @@ def test_garbage_after_stop_line(self): self.assertEqual(out, msg) def test_whitespace_before_stop_line(self): - raw = dedent(""" + raw = """ /*[clinic input] [clinic start generated code]*/ - """).strip() + """ msg = ( 'Error in file "test.c" on line 2:\n' "Whitespace is not allowed before the stop line: ' [clinic start generated code]*/'\n" From 8173cd1a5774d8da4fdb84d13f1595898e492ccc Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 15 Jul 2023 10:43:56 +0200 Subject: [PATCH 3/3] Address Nikita's review: Assert stuff in test_parse_with_body_prefix() --- Lib/test/test_clinic.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 84095a2c04f8b8..b5744f7013d6ad 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -189,8 +189,16 @@ def test_parse_with_body_prefix(self): //[clinic start] //module test //[clinic stop] - """) - cl.parse(raw) + """).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):