From 9578ea00e11a7675b226447de9a6449e9600a240 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 17 Jul 2023 00:08:38 +0200 Subject: [PATCH 1/3] gh-106368: Add functional tests for Tools/clinic/cpp.py --- Lib/test/test_clinic.py | 258 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 257 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index b5744f7013d6ad..0b3e6347f24d9a 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -4,7 +4,7 @@ from test import support, test_tools from test.support import os_helper -from textwrap import dedent +from textwrap import dedent, indent from unittest import TestCase import collections import inspect @@ -15,6 +15,7 @@ test_tools.skip_if_missing('clinic') with test_tools.imports_under_tool('clinic'): import clinic + import cpp from clinic import DSLParser @@ -200,6 +201,20 @@ def test_parse_with_body_prefix(self): """).lstrip() # Note, lstrip() because of the newline self.assertEqual(out, expected) + def test_cpp_monitor_fail_override(self): + raw = """ + #if + /*[clinic input] + [clinic start generated code] + #endif + """ + msg = ( + 'Error in file "test.c" on line 1:\n' + 'Invalid format for #if line: no argument!\n' + ) + out = self.expect_failure(raw) + self.assertEqual(out, msg) + class ClinicGroupPermuterTest(TestCase): def _test(self, l, m, r, output): @@ -1985,5 +2000,246 @@ def test_suffix_all_lines(self): self.assertEqual(out, expected) +class CppMonitorTests(TestCase): + + def validate_checkpoints(self, code, checkpoints): + mon = cpp.Monitor("", verbose=False) + lines = code.strip().split("\n") + for num, line in enumerate(lines, 1): + with self.subTest(num=num, line=line): + mon.writeline(line) + if num in checkpoints: + self.assertEqual(mon.status(), checkpoints[num]) + + def validate_verbose_run(self, code, expected): + mon = cpp.Monitor("", verbose=True) + with support.captured_stdout() as stdout: + mon.write(code.strip()) + out = stdout.getvalue() + expected = dedent(expected) + expected = indent(expected.lstrip(), prefix=" ") + self.assertEqual(out, expected) + + def expect_failure(self, code, msg, *, fn=None): + mon = cpp.Monitor(fn, verbose=True) + with support.captured_stdout() as stdout: + with self.assertRaises(SystemExit): + mon.write(code.strip()) + out = stdout.getvalue() + self.assertIn(msg, out) + + def test_cpp_monitor_no_defs(self): + code = """ + // one comment, no preprocessor directives + """ + checkpoints = {0: ""} + self.validate_checkpoints(code, checkpoints) + + def test_cpp_monitor_simple_if(self): + code = """ + #if MYDEF + // code + #endif + """ + checkpoints = { + 1: " 1: (MYDEF)", + 3: " 3: ", + } + self.validate_checkpoints(code, checkpoints) + + def test_cpp_monitor_simple_if_else(self): + code = """ + #if MYDEF + // code + #else + // more code + #endif + """ + checkpoints = { + 1: " 1: (MYDEF)", + 3: " 3: !(MYDEF)", + 5: " 5: ", + } + self.validate_checkpoints(code, checkpoints) + + def test_cpp_monitor_multi_if(self): + code = """ + #if MYDEF + f(); + # if OTHER + g(); + # endif + #else + h(); + # if MORE + i(); + # else + j(); + k(); + l(); + # endif + #endif + """ + checkpoints = { + 1: " 1: (MYDEF)", + 3: " 3: (MYDEF) && (OTHER)", + 5: " 5: (MYDEF)", + 7: " 7: !(MYDEF)", + 9: " 9: !(MYDEF) && (MORE)", + 11: " 11: !(MYDEF) && !(MORE)", + 12: " 12: !(MYDEF) && !(MORE)", + 13: " 13: !(MYDEF) && !(MORE)", + 15: " 15: ", + } + self.validate_checkpoints(code, checkpoints) + + def test_cpp_monitor_expr(self): + code = """ + // comment + #if VER < 1 + a(); + #elif VER < 2 + b(); + #else + c(); + #endif + // comment + """ + checkpoints = { + 2: " 2: (VER < 1)", + 4: " 4: !(VER < 1) && (VER < 2)", + 6: " 6: !(VER < 1) && !(VER < 2)", + 8: " 8: ", + } + self.validate_checkpoints(code, checkpoints) + + def test_cpp_monitor_ifdefs(self): + code = """ + #ifdef A + a(); + # if defined(B) + b(); + # endif + #endif + """ + checkpoints = { + 1: " 1: defined(A)", + 3: " 3: defined(A) && defined(B)", + 5: " 5: defined(A)", + 6: " 6: ", + } + self.validate_checkpoints(code, checkpoints) + + def test_cpp_monitor_verbose_1(self): + code = """ + #if A || B + // code + #endif + """ + expected = """ + 1: (A || B) + 3: + """ + self.validate_verbose_run(code, expected) + + def test_cpp_monitor_verbose_2(self): + code = """ + #if defined(A) && B || C + // code + # ifndef E + // code + # else + // code + #endif + #endif + """ + expected = """ + 1: (defined(A) && B || C) + 3: (defined(A) && B || C) && !defined(E) + 5: (defined(A) && B || C) && defined(E) + 7: (defined(A) && B || C) + 8: + """ + self.validate_verbose_run(code, expected) + + def test_cpp_monitor_verbose_3(self): + code = """ + #if A + # ifdef B + # else + # endif + #endif + """ + expected = """ + 1: (A) + 2: (A) && defined(B) + 3: (A) && !defined(B) + 4: (A) + 5: + """ + self.validate_verbose_run(code, expected) + + def test_cpp_monitor_verbose_cont(self): + code = r""" + #if A \ + &&\ + C + #pragma message ("") + #endif + """ + expected = """ + 3: (A && C) + 5: + """ + self.validate_verbose_run(code, expected) + + def test_cpp_monitor_fail_nested_block_comment(self): + code = """ + /* start + /* nested + */ + */ + """ + expected = dedent(""" + Error at test.c line 2 : + Nested block comment! + """).strip() + self.expect_failure(code, expected, fn="test.c") + + def test_cpp_monitor_fail_invalid_format_noarg(self): + code = """ + #if + a() + #endif + """ + expected = dedent(""" + Error at test.c line 1 : + Invalid format for #if line: no argument! + """).strip() + self.expect_failure(code, expected, fn="test.c") + + def test_cpp_monitor_fail_invalid_format_toomanyargs(self): + code = """ + #ifdef A B + a() + #endif + """ + expected = dedent(""" + Error at test.c line 1 : + Invalid format for #ifdef line: should be exactly one argument! + """).strip() + self.expect_failure(code, expected, fn="test.c") + + def test_cpp_monitor_fail_no_matching(self): + dataset = ( + ("#else", "#else without matching #if / #ifdef / #ifndef!"), + ("#endif", "#endif without matching #if / #ifdef / #ifndef!"), + ("#elif B", "#elif without matching #if / #ifdef / #ifndef!"), + ) + for line, msg in dataset: + with self.subTest(line=line): + self.expect_failure(line, msg) + + if __name__ == "__main__": unittest.main() From 3be5e8219837add2c31f276abb65465e43c97cd0 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 17 Jul 2023 00:13:59 +0200 Subject: [PATCH 2/3] Fix lint --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d62c57c044728f..263b9cfe5db181 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: check-yaml - id: end-of-file-fixer types: [python] - exclude: Lib/test/coding20731.py + exclude: Lib/test/coding20731.py|Lib/test/test_clinic.py - id: trailing-whitespace types_or: [c, python, rst] From f0b16319a3f8e21cb13eba78412085a1ce800f74 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 17 Jul 2023 00:18:41 +0200 Subject: [PATCH 3/3] Fix lint again --- .pre-commit-config.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 263b9cfe5db181..4ac7c85d2c5dca 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,9 +5,10 @@ repos: - id: check-yaml - id: end-of-file-fixer types: [python] - exclude: Lib/test/coding20731.py|Lib/test/test_clinic.py + exclude: Lib/test/coding20731.py - id: trailing-whitespace types_or: [c, python, rst] + exclude: Lib/test/test_clinic.py - repo: https://github.com/sphinx-contrib/sphinx-lint rev: v0.6.7 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy