diff --git a/CMakeLists.txt b/CMakeLists.txt index 204b976daa45..5dfdd028e839 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -268,7 +268,18 @@ if(BUILD_TESTING) ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_performance_csv.py) set_tests_properties(performance_csv PROPERTIES TIMEOUT 20) add_test(NAME conventions_wrapped_declarations COMMAND ${Python3_EXECUTABLE} - ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_wrapped_declarations.py) + ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_wrapped_declarations.py WrappedDeclarationTests) + set_tests_properties(conventions_wrapped_declarations PROPERTIES TIMEOUT 30) + set(conventions_wrapped_declarations_source "${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_wrapped_declarations.py") + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${conventions_wrapped_declarations_source}") + file(STRINGS "${conventions_wrapped_declarations_source}" conventions_wrapped_declarations_classes REGEX "^class [A-Za-z0-9_]*Tests\\(") + foreach(test_class IN LISTS conventions_wrapped_declarations_classes) + string(REGEX REPLACE "^class ([A-Za-z0-9_]+).*" "\\1" test_class "${test_class}") + if(NOT test_class STREQUAL "WrappedDeclarationTests") + add_test(NAME conventions_wrapped_declarations_${test_class} COMMAND ${Python3_EXECUTABLE} "${conventions_wrapped_declarations_source}" ${test_class}) + set_tests_properties(conventions_wrapped_declarations_${test_class} PROPERTIES TIMEOUT 30) + endif() + endforeach() add_test(NAME conventions_ci_gate COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_ci_gate.py) add_test(NAME preview_pad_timeline COMMAND ${Python3_EXECUTABLE} diff --git a/tools/tests/test_check_conventions_wrapped_declarations.py b/tools/tests/test_check_conventions_wrapped_declarations.py index 4c02868f6091..ee54cbb7023c 100644 --- a/tools/tests/test_check_conventions_wrapped_declarations.py +++ b/tools/tests/test_check_conventions_wrapped_declarations.py @@ -12,7 +12,7 @@ DEFINITION = "int APS5_VABI sceFooBar(int a, int b) { return a + b; }\n" -class WrappedDeclarationTests(unittest.TestCase): +class WrappedDeclarationFixture(unittest.TestCase): def check(self, first_file, first_text, second_text=DEFINITION): with tempfile.TemporaryDirectory() as directory: root = Path(directory) @@ -45,6 +45,8 @@ def git(*args): cwd=root, capture_output=True, text=True, env=env, timeout=20, ) + +class WrappedDeclarationTests(WrappedDeclarationFixture): def test_wrapped_declaration_is_not_a_duplicate(self): result = self.check("Export.h", "int APS5_VABI sceFooBar(int a,\n int b);\n") self.assertNotIn("duplicate-export", result.stdout, result.stdout + result.stderr) @@ -66,6 +68,41 @@ def test_wrapped_definition_is_a_duplicate(self): self.assertEqual(result.returncode, 1, result.stdout + result.stderr) self.assertIn("[duplicate-export]", result.stdout) + def test_multiline_raw_literal_is_not_a_duplicate(self): + source = 'const char* example = R"example(\n' + DEFINITION + ')example";\n' + result = self.check("Export.cpp", source) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertNotIn("[duplicate-export]", result.stdout) + + def test_block_comment_is_not_a_duplicate(self): + result = self.check("Export.cpp", "/*\n" + DEFINITION + "*/\n") + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertNotIn("[duplicate-export]", result.stdout) + + def test_literal_before_unrelated_export_is_not_a_duplicate(self): + source = 'const char* example = "APS5_VABI sceFooBar()"; int APS5_VABI sceOther() { return 1; }\n' + result = self.check("Export.cpp", source) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertNotIn("[duplicate-export]", result.stdout) + + def test_line_comment_before_definition_is_not_a_duplicate(self): + result = self.check("Export.cpp", "// " + DEFINITION + "int unrelated() { return 42; }\n") + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertNotIn("[duplicate-export]", result.stdout) + + def test_definition_after_unicode_raw_literal_is_a_duplicate(self): + source = 'const char* text = R"text(first\u2028+middle\u2029+last)text";\n' + DEFINITION + result = self.check("Export.cpp", source) + self.assertEqual(result.returncode, 1, result.stdout + result.stderr) + self.assertIn("[duplicate-export]", result.stdout) + + def test_definition_after_commented_example_is_a_duplicate(self): + result = self.check("Export.cpp", "/*\n" + DEFINITION + "*/\n" + DEFINITION) + self.assertEqual(result.returncode, 1, result.stdout + result.stderr) + self.assertEqual(result.stdout.count("[duplicate-export]"), 1, result.stdout) + + +class AbiAliasTests(WrappedDeclarationFixture): def test_local_abi_alias_cannot_hide_duplicates_in_either_library(self): aliased = "#define NATIVE_SYSV APS5_VABI\n" + DEFINITION.replace("APS5_VABI", "NATIVE_SYSV") for first, second in ((aliased, DEFINITION), (DEFINITION, aliased), (aliased, aliased)): @@ -117,39 +154,6 @@ def test_unique_aliased_definition_and_unpatched_helpers_remain_valid(self): result = self.check("Export.cpp", source, source if name.startswith("Support") else DEFINITION) self.assertEqual(result.returncode, 0, result.stdout + result.stderr) - def test_multiline_raw_literal_is_not_a_duplicate(self): - source = 'const char* example = R"example(\n' + DEFINITION + ')example";\n' - result = self.check("Export.cpp", source) - self.assertEqual(result.returncode, 0, result.stdout + result.stderr) - self.assertNotIn("[duplicate-export]", result.stdout) - - def test_block_comment_is_not_a_duplicate(self): - result = self.check("Export.cpp", "/*\n" + DEFINITION + "*/\n") - self.assertEqual(result.returncode, 0, result.stdout + result.stderr) - self.assertNotIn("[duplicate-export]", result.stdout) - - def test_literal_before_unrelated_export_is_not_a_duplicate(self): - source = 'const char* example = "APS5_VABI sceFooBar()"; int APS5_VABI sceOther() { return 1; }\n' - result = self.check("Export.cpp", source) - self.assertEqual(result.returncode, 0, result.stdout + result.stderr) - self.assertNotIn("[duplicate-export]", result.stdout) - - def test_line_comment_before_definition_is_not_a_duplicate(self): - result = self.check("Export.cpp", "// " + DEFINITION + "int unrelated() { return 42; }\n") - self.assertEqual(result.returncode, 0, result.stdout + result.stderr) - self.assertNotIn("[duplicate-export]", result.stdout) - - def test_definition_after_unicode_raw_literal_is_a_duplicate(self): - source = 'const char* text = R"text(first\u2028+middle\u2029+last)text";\n' + DEFINITION - result = self.check("Export.cpp", source) - self.assertEqual(result.returncode, 1, result.stdout + result.stderr) - self.assertIn("[duplicate-export]", result.stdout) - - def test_definition_after_commented_example_is_a_duplicate(self): - result = self.check("Export.cpp", "/*\n" + DEFINITION + "*/\n" + DEFINITION) - self.assertEqual(result.returncode, 1, result.stdout + result.stderr) - self.assertEqual(result.stdout.count("[duplicate-export]"), 1, result.stdout) - if __name__ == "__main__": unittest.main()