diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e52b612f..9347321f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,16 @@ file(GLOB addons "addons/*.py") file(GLOB cfgs "cfg/*.cfg") file(GLOB platforms "platforms/*.xml") +find_program(LIBXML2_XMLLINT_EXECUTABLE xmllint) +if (LIBXML2_XMLLINT_EXECUTABLE) + add_custom_target(validateCFG ${LIBXML2_XMLLINT_EXECUTABLE} --noout ${CMAKE_SOURCE_DIR}/cfg/cppcheck-cfg.rng) + foreach(cfg ${cfgs}) + get_filename_component(cfgname ${cfg} NAME_WE) + add_custom_target(validateCFG-${cfgname} ${LIBXML2_XMLLINT_EXECUTABLE} --noout --relaxng ${CMAKE_SOURCE_DIR}/cfg/cppcheck-cfg.rng ${cfg}) + add_dependencies(validateCFG validateCFG-${cfgname}) + endforeach() +endif() + if (BUILD_TESTS) enable_testing() endif() diff --git a/cmake/options.cmake b/cmake/options.cmake index 179c9ccc1..314d000f3 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -33,6 +33,7 @@ else() endif() option(BUILD_TESTS "Build tests" OFF) +option(REGISTER_TESTS "Register tests in CTest" ON) option(ENABLE_CHECK_INTERNAL "Enable internal checks" OFF) option(ENABLE_OSS_FUZZ "Enable the OSS-Fuzz related targets" ON) option(BUILD_GUI "Build the qt application" OFF) diff --git a/cmake/printInfo.cmake b/cmake/printInfo.cmake index 6945539d4..c6fe4e1b1 100644 --- a/cmake/printInfo.cmake +++ b/cmake/printInfo.cmake @@ -31,7 +31,11 @@ if(NOT DEFINED BUILD_SHARED_LIBS) else() message( STATUS "BUILD_SHARED_LIBS = ${BUILD_SHARED_LIBS}" ) endif(NOT DEFINED BUILD_SHARED_LIBS) +message( STATUS "LIBXML2_XMLLINT_EXECUTABLE = ${LIBXML2_XMLLINT_EXECUTABLE}" ) message( STATUS "BUILD_TESTS = ${BUILD_TESTS}" ) +if(BUILD_TESTS) + message( STATUS "REGISTER_TESTS = ${REGISTER_TESTS}" ) +endif() message( STATUS "ENABLE_CHECK_INTERNAL = ${ENABLE_CHECK_INTERNAL}" ) message( STATUS "ENABLE_OSS_FUZZ = ${ENABLE_OSS_FUZZ}" ) message( STATUS ) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index f276db2cf..dcf509484 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -3239,7 +3239,7 @@ void CheckOther::knownArgumentError(const Token *tok, const Token *ftok, const V const std::string &expr = tok->expressionString(); const std::string &fun = ftok->str(); - const char *id;; + const char *id; std::string errmsg = "Argument '" + expr + "' to function " + fun + " is always " + std::to_string(intvalue) + ". "; if (!isVariableExpressionHidden) { id = "knownArgument"; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 84f8a638f..6178b6909 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,17 +1,4 @@ if (BUILD_TESTS) - - cmake_minimum_required(VERSION 3.4) # cmake_policy(SET CMP0064 NEW) - cmake_policy(SET CMP0064 NEW) - cmake_policy(SET CMP0057 NEW) - - include(CTest) - - find_package(Threads REQUIRED) - include(ProcessorCount) - ProcessorCount(N) - set(CTEST_PARALLEL_LEVEL ${N} CACHE STRING "CTest parallel level") - add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -j ${CTEST_PARALLEL_LEVEL} -C ${CMAKE_CFG_INTDIR} --timeout 90) - include_directories(${PROJECT_SOURCE_DIR}/lib/ ${PROJECT_SOURCE_DIR}/cli/) include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/externals/tinyxml) include_directories(${PROJECT_SOURCE_DIR}/externals/simplecpp/) @@ -26,130 +13,157 @@ if (BUILD_TESTS) if (USE_Z3) target_link_libraries(testrunner ${Z3_LIBRARIES}) endif() + if (WIN32 AND NOT BORLAND) + target_link_libraries(testrunner Shlwapi.lib) + endif() if (NOT CMAKE_DISABLE_PRECOMPILE_HEADERS) target_precompile_headers(testrunner PRIVATE precompiled.h) endif() add_custom_target(copy_cfg ALL + ${CMAKE_COMMAND} -E copy_directory "${PROJECT_SOURCE_DIR}/cfg" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cfg" COMMENT "Copying cfg files") - add_custom_command( - TARGET copy_cfg - COMMAND ${CMAKE_COMMAND} -E copy_directory "${PROJECT_SOURCE_DIR}/cfg" - "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cfg") + add_dependencies(testrunner copy_cfg) - if (WIN32 AND NOT BORLAND) - target_link_libraries(testrunner Shlwapi.lib) + if (LIBXML2_XMLLINT_EXECUTABLE) + # TODO: get rid of the copy + add_custom_target(checkcfg ${CMAKE_COMMAND} -E copy $ ${CMAKE_SOURCE_DIR} + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/cfg/runtests.sh + DEPENDS cppcheck validateCFG + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cfg) endif() - add_dependencies(testrunner copy_cfg) - add_dependencies(check testrunner cppcheck) + if (REGISTER_TESTS) + cmake_minimum_required(VERSION 3.4) # cmake_policy(SET CMP0064 NEW) + cmake_policy(SET CMP0064 NEW) + cmake_policy(SET CMP0057 NEW) - set(SKIP_TESTS "" CACHE STRING "A list of tests to skip") + include(CTest) - function(add_fixture NAME) - set(options) - set(oneValueArgs WORKING_DIRECTORY) - set(multiValueArgs) + find_package(Threads REQUIRED) + include(ProcessorCount) + ProcessorCount(N) + set(CTEST_PARALLEL_LEVEL ${N} CACHE STRING "CTest parallel level") + add_custom_target(check ${CMAKE_CTEST_COMMAND} --output-on-failure -j ${CTEST_PARALLEL_LEVEL} -C ${CMAKE_CFG_INTDIR} --timeout 90 + DEPENDS testrunner cppcheck) - cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(SKIP_TESTS "" CACHE STRING "A list of tests to skip") - if (${NAME} IN_LIST SKIP_TESTS) - elseif(TEST ${NAME}) - else() - set(WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - if (PARSE_WORKING_DIRECTORY) - set(WORKING_DIRECTORY ${PARSE_WORKING_DIRECTORY}) + function(add_fixture NAME) + set(options) + set(oneValueArgs WORKING_DIRECTORY) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if (${NAME} IN_LIST SKIP_TESTS) + elseif(TEST ${NAME}) + else() + set(WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + if (PARSE_WORKING_DIRECTORY) + set(WORKING_DIRECTORY ${PARSE_WORKING_DIRECTORY}) + endif() + add_test(NAME ${NAME} COMMAND testrunner ${NAME} WORKING_DIRECTORY ${WORKING_DIRECTORY}) endif() - add_test(NAME ${NAME} COMMAND testrunner ${NAME} WORKING_DIRECTORY ${WORKING_DIRECTORY}) - endif() - endfunction() + endfunction() - function(fixture_cost NAME COST) - if(TEST ${NAME}) - set_tests_properties(${NAME} PROPERTIES COST ${COST}) - endif() - endfunction() + function(fixture_cost NAME COST) + if(TEST ${NAME}) + set_tests_properties(${NAME} PROPERTIES COST ${COST}) + endif() + endfunction() - add_fixture(TestSamples WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) - foreach(SRC ${srcs}) - file(STRINGS ${SRC} FIXTURE_LINE REGEX "TestFixture\\(" LIMIT_COUNT 1) - if(FIXTURE_LINE MATCHES "TestFixture\\(\"([a-zA-z0-9]+)\"\\)") - add_fixture(${CMAKE_MATCH_1}) - endif() - endforeach() - add_fixture(TestLeakAutoVarStrcpy) - add_fixture(TestLeakAutoVarWindows) - add_fixture(TestMemleakInFunction) - add_fixture(TestMemleakInClass) - add_fixture(TestMemleakStructMember) - add_fixture(TestMemleakNoVar) + # TODO: what is this? + add_fixture(TestSamples WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) + foreach(SRC ${srcs}) + file(STRINGS ${SRC} FIXTURE_LINE REGEX "TestFixture\\(" LIMIT_COUNT 1) + if(FIXTURE_LINE MATCHES "TestFixture\\(\"([a-zA-z0-9]+)\"\\)") + add_fixture(${CMAKE_MATCH_1}) + endif() + endforeach() + # TODO: parse files for REGISTER_TEST macro + add_fixture(TestLeakAutoVarStrcpy) + add_fixture(TestLeakAutoVarWindows) + add_fixture(TestMemleakInFunction) + add_fixture(TestMemleakInClass) + add_fixture(TestMemleakStructMember) + add_fixture(TestMemleakNoVar) - function(add_cfg CFG_TEST) - set(options INCONCLUSIVE) - set(oneValueArgs PLATFORM NAME) - set(multiValueArgs LIBRARY) + function(add_cfg CFG_TEST) + set(options INCONCLUSIVE) + set(oneValueArgs PLATFORM NAME) + set(multiValueArgs LIBRARY) - cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - if(PARSE_LIBRARY) - string(REPLACE ";" "," LIBRARY "${PARSE_LIBRARY}") - else() - get_filename_component(LIBRARY ${CFG_TEST} NAME_WE) - endif() - set(PLATFORM unix64) - if(PARSE_PLATFORM) - set(PLATFORM ${PARSE_PLATFORM}) - endif() - if(PARSE_NAME) - set(TEST_NAME ${PARSE_NAME}) - else() - string(MAKE_C_IDENTIFIER ${CFG_TEST} TEST_NAME) - endif() - set(INCONCLUSIVE) - if(PARSE_INCONCLUSIVE) - set(INCONCLUSIVE "--inconclusive") - endif() - if (${TEST_NAME} IN_LIST SKIP_TESTS) - else() - add_test(NAME cfg-${TEST_NAME} - COMMAND $ - --check-library - --platform=${PLATFORM} - --library=${LIBRARY} - --enable=information - --enable=style - --error-exitcode=1 - --suppress=missingIncludeSystem - --inline-suppr - ${INCONCLUSIVE} - ${CMAKE_CURRENT_SOURCE_DIR}/cfg/${CFG_TEST} - ) - endif() - endfunction() - add_cfg(boost.cpp INCONCLUSIVE) - add_cfg(bsd.c) - add_cfg(gnu.c LIBRARY posix gnu) - add_cfg(googletest.cpp) - add_cfg(gtk.c INCONCLUSIVE) - add_cfg(libcurl.c) - add_cfg(lua.c) - add_cfg(openmp.c) - add_cfg(posix.c) - add_cfg(python.c) - add_cfg(qt.cpp) - add_cfg(sqlite3.c INCONCLUSIVE) - add_cfg(std.c INCONCLUSIVE) - add_cfg(std.cpp INCONCLUSIVE) - add_cfg(windows.cpp INCONCLUSIVE NAME windows32A PLATFORM win32A) - add_cfg(windows.cpp INCONCLUSIVE NAME windows32W PLATFORM win32W) - add_cfg(windows.cpp INCONCLUSIVE NAME windows64 PLATFORM win64) - add_cfg(wxwidgets.cpp INCONCLUSIVE) + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(PARSE_LIBRARY) + string(REPLACE ";" "," LIBRARY "${PARSE_LIBRARY}") + else() + get_filename_component(LIBRARY ${CFG_TEST} NAME_WE) + endif() + set(PLATFORM unix64) + if(PARSE_PLATFORM) + set(PLATFORM ${PARSE_PLATFORM}) + endif() + if(PARSE_NAME) + set(TEST_NAME ${PARSE_NAME}) + else() + string(MAKE_C_IDENTIFIER ${CFG_TEST} TEST_NAME) + endif() + set(INCONCLUSIVE) + if(PARSE_INCONCLUSIVE) + set(INCONCLUSIVE "--inconclusive") + endif() + if (${TEST_NAME} IN_LIST SKIP_TESTS) + else() + # TODO: add syntax check + add_test(NAME cfg-${TEST_NAME} + COMMAND $ + --check-library + --platform=${PLATFORM} + --library=${LIBRARY} + --enable=information + --enable=style + --error-exitcode=1 + --suppress=missingIncludeSystem + --inline-suppr + --template="{file}:{line}:{severity}:{id}:{message}" + ${INCONCLUSIVE} + ${CMAKE_CURRENT_SOURCE_DIR}/cfg/${CFG_TEST} + ) + endif() + endfunction() + add_cfg(posix.c) + add_cfg(gnu.c LIBRARY posix;gnu) + add_cfg(qt.cpp INCONCLUSIVE) + add_cfg(bsd.c) + add_cfg(std.c INCONCLUSIVE) + add_cfg(std.cpp INCONCLUSIVE) + add_cfg(windows.cpp INCONCLUSIVE NAME windows32A PLATFORM win32A) + add_cfg(windows.cpp INCONCLUSIVE NAME windows32W PLATFORM win32W) + add_cfg(windows.cpp INCONCLUSIVE NAME windows64 PLATFORM win64) + add_cfg(wxwidgets.cpp INCONCLUSIVE) + add_cfg(gtk.c INCONCLUSIVE) + add_cfg(boost.cpp INCONCLUSIVE) + add_cfg(sqlite3.c INCONCLUSIVE) + add_cfg(openmp.c) + add_cfg(python.c) + add_cfg(lua.c) + add_cfg(libcurl.c) + add_cfg(cairo.c) + add_cfg(googletest.cpp INCONCLUSIVE) + add_cfg(kde.cpp INCONCLUSIVE) + add_cfg(libsigc++.cpp) + add_cfg(openssl.c) + add_cfg(opencv2.cpp) - # Set cost of the more expensive tests to help improve parallel scheduling - # of tests - fixture_cost(TestIO 20) - fixture_cost(cfg-std_c 8) - fixture_cost(TestThreadExecutor 5) - fixture_cost(TestLeakAutoVar 4) - fixture_cost(TestTokenizer 4) + # Set cost of the more expensive tests to help improve parallel scheduling + # of tests + fixture_cost(TestIO 20) + fixture_cost(cfg-std_c 8) + fixture_cost(TestThreadExecutor 5) + fixture_cost(TestLeakAutoVar 4) + fixture_cost(TestTokenizer 4) + endif() endif() diff --git a/test/testsamples.cpp b/test/testsamples.cpp index b1bbff3bf..d064eb9d1 100644 --- a/test/testsamples.cpp +++ b/test/testsamples.cpp @@ -84,6 +84,7 @@ private: exec.check(7, argv); std::string expected_filename = Path::getPathFromFilename(i->first) + "out.txt"; std::ifstream ifs(expected_filename); + // TODO: this contains stray \n at the start of each line when the out.txt files have CRLF std::string expected((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); std::string actual = GET_REDIRECT_ERROUT; // We need some uniformization to make this work on Unix and Windows