From ad7738ddfbc0a1d822ec09131430ca22802e700d Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Tue, 3 Jan 2023 21:13:28 -0800 Subject: [PATCH 01/18] Initial work on C++ API --- .github/workflows/c-test-suite.yml | 2 +- .gitmodules | 3 + bindings/c/CMakeLists.txt | 16 +- bindings/cpp/.gitignore | 46 ++++++ bindings/cpp/CMakeLists.txt | 27 ++++ bindings/cpp/googletest | 1 + bindings/cpp/include/cppchecks/check.h | 46 ++++++ bindings/cpp/include/cppchecks/core.h | 3 + bindings/cpp/include/cppchecks/item.h | 53 +++++++ bindings/cpp/include/cppchecks/items.h | 49 ++++++ bindings/cpp/include/cppchecks/result.h | 47 ++++++ bindings/cpp/include/cppchecks/runner.h | 23 +++ bindings/cpp/include/cppchecks/status.h | 37 +++++ bindings/cpp/src/CMakeLists.txt | 28 ++++ bindings/cpp/src/check.cpp | 55 +++++++ bindings/cpp/src/item.cpp | 117 ++++++++++++++ bindings/cpp/src/items.cpp | 56 +++++++ bindings/cpp/src/result.cpp | 197 ++++++++++++++++++++++++ bindings/cpp/src/runner.cpp | 18 +++ bindings/cpp/src/status.cpp | 21 +++ bindings/cpp/tests/CMakeLists.txt | 31 ++++ bindings/cpp/tests/item_impl.h | 29 ++++ bindings/cpp/tests/test_check.cpp | 7 + bindings/cpp/tests/test_item.cpp | 12 ++ bindings/cpp/tests/test_result.cpp | 7 + bindings/cpp/tests/test_runner.cpp | 7 + bindings/cpp/tests/test_status.cpp | 70 +++++++++ 27 files changed, 1002 insertions(+), 6 deletions(-) create mode 100644 bindings/cpp/.gitignore create mode 100644 bindings/cpp/CMakeLists.txt create mode 160000 bindings/cpp/googletest create mode 100644 bindings/cpp/include/cppchecks/check.h create mode 100644 bindings/cpp/include/cppchecks/core.h create mode 100644 bindings/cpp/include/cppchecks/item.h create mode 100644 bindings/cpp/include/cppchecks/items.h create mode 100644 bindings/cpp/include/cppchecks/result.h create mode 100644 bindings/cpp/include/cppchecks/runner.h create mode 100644 bindings/cpp/include/cppchecks/status.h create mode 100644 bindings/cpp/src/CMakeLists.txt create mode 100644 bindings/cpp/src/check.cpp create mode 100644 bindings/cpp/src/item.cpp create mode 100644 bindings/cpp/src/items.cpp create mode 100644 bindings/cpp/src/result.cpp create mode 100644 bindings/cpp/src/runner.cpp create mode 100644 bindings/cpp/src/status.cpp create mode 100644 bindings/cpp/tests/CMakeLists.txt create mode 100644 bindings/cpp/tests/item_impl.h create mode 100644 bindings/cpp/tests/test_check.cpp create mode 100644 bindings/cpp/tests/test_item.cpp create mode 100644 bindings/cpp/tests/test_result.cpp create mode 100644 bindings/cpp/tests/test_runner.cpp create mode 100644 bindings/cpp/tests/test_status.cpp diff --git a/.github/workflows/c-test-suite.yml b/.github/workflows/c-test-suite.yml index 6df1486..6596e4a 100644 --- a/.github/workflows/c-test-suite.yml +++ b/.github/workflows/c-test-suite.yml @@ -27,7 +27,7 @@ jobs: working-directory: bindings/c/build run: | # Make cmocka a static dependency when testing. - cmake ../ -DBUILD_SHARED_LIBS=OFF + cmake ../ -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=ON - name: CMake Build working-directory: bindings/c/build run: | diff --git a/.gitmodules b/.gitmodules index 1b0ccab..238018e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "bindings/c/corrosion"] path = bindings/c/corrosion url = https://github.com/corrosion-rs/corrosion.git +[submodule "bindings/cpp/googletest"] + path = bindings/cpp/googletest + url = https://github.com/google/googletest.git diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt index e441f55..eacee09 100644 --- a/bindings/c/CMakeLists.txt +++ b/bindings/c/CMakeLists.txt @@ -16,10 +16,16 @@ project(cchecks VERSION ${CCHECKS_VERSION} LANGUAGES C) # -------------------------------------------------------------------------------- set(UNIT_TESTING OFF) -enable_testing() - add_subdirectory(corrosion) -corrosion_import_crate(MANIFEST_PATH "${CMAKE_SOURCE_DIR}/Cargo.toml") -add_subdirectory(cmocka) -add_subdirectory(tests) +if (NOT DEFINED CCHECKS_SOURCE_DIR OR CCHECKS_SOURCE_DIR MATCHES "") +set(CCHECKS_SOURCE_DIR, "${CMAKE_SOURCE_DIR}") +endif() + +corrosion_import_crate(MANIFEST_PATH "${CCHECKS_SOURCE_DIR}/Cargo.toml") + +if (BUILD_TESTING) + enable_testing() + add_subdirectory(cmocka) + add_subdirectory(tests) +endif() diff --git a/bindings/cpp/.gitignore b/bindings/cpp/.gitignore new file mode 100644 index 0000000..89ee243 --- /dev/null +++ b/bindings/cpp/.gitignore @@ -0,0 +1,46 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +build/ + +# Cmake +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps diff --git a/bindings/cpp/CMakeLists.txt b/bindings/cpp/CMakeLists.txt new file mode 100644 index 0000000..9d23433 --- /dev/null +++ b/bindings/cpp/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR) + +set(CPPCHECKS_VERSION_MAJOR "0") +set(CPPCHECKS_VERSION_MINOR "1") +set(CPPCHECKS_VERSION_PATCH "0") +set(CPPCHECKS_VERSION ${CPPCHECKS_VERSION_MAJOR}.${CPPCHECKS_VERSION_MINOR}.${CPPCHECKS_VERSION_PATCH}) + +project(cppchecks VERSION ${CPPCHECKS_VERSION} LANGUAGES CXX) + +# -------------------------------------------------------------------------------- +# Build Options +# -------------------------------------------------------------------------------- +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# -------------------------------------------------------------------------------- +# Do the build +# -------------------------------------------------------------------------------- +add_subdirectory(src) + +if (BUILD_TESTS) + enable_testing() + add_subdirectory(googletest) + # For Windows: Prevent overriding the parent project's compiler/linker settings + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + add_subdirectory(tests) +endif() diff --git a/bindings/cpp/googletest b/bindings/cpp/googletest new file mode 160000 index 0000000..71140c3 --- /dev/null +++ b/bindings/cpp/googletest @@ -0,0 +1 @@ +Subproject commit 71140c3ca7a87bb1b5b9c9f1500fea8858cce344 diff --git a/bindings/cpp/include/cppchecks/check.h b/bindings/cpp/include/cppchecks/check.h new file mode 100644 index 0000000..939ff80 --- /dev/null +++ b/bindings/cpp/include/cppchecks/check.h @@ -0,0 +1,46 @@ +#pragma once + +extern "C" +{ +#include +} + +#include +#include +#include + +#include "cppchecks/core.h" +#include "cppchecks/item.h" +#include "cppchecks/items.h" +#include "cppchecks/status.h" +#include "cppchecks/result.h" + +namespace CPPCHECKS_NAMESPACE +{ + enum class CheckHint + { + None = CCHECKS_CHECK_HINT_NONE, + AutoFix = CCHECKS_CHECK_HINT_AUTO_FIX, + }; + + template + class BaseCheck + { + public: + BaseCheck(); + virtual std::string title() = 0; + virtual std::string description() = 0; + virtual CheckHint hint() = 0; + virtual CPPCHECKS_NAMESPACE::CheckResult check() = 0; + virtual std::optional auto_fix() { return std::string("Auto fix is not implemented."); } + + private: + CChecksBaseCheck _check; + static const char *title_fn(const CChecksBaseCheck *check); + static const char *description_fn(const CChecksBaseCheck *check); + static CChecksCheckHint hint_fn(const CChecksBaseCheck *check); + static CChecksCheckResult check_fn(const CChecksBaseCheck *check); + static CChecksAutoFixResult auto_fix_fn(const CChecksBaseCheck *check); + }; + +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/include/cppchecks/core.h b/bindings/cpp/include/cppchecks/core.h new file mode 100644 index 0000000..7b06225 --- /dev/null +++ b/bindings/cpp/include/cppchecks/core.h @@ -0,0 +1,3 @@ +#pragma once + +#define CPPCHECKS_NAMESPACE cppchecks diff --git a/bindings/cpp/include/cppchecks/item.h b/bindings/cpp/include/cppchecks/item.h new file mode 100644 index 0000000..e650987 --- /dev/null +++ b/bindings/cpp/include/cppchecks/item.h @@ -0,0 +1,53 @@ +#pragma once + +extern "C" +{ +#include +} + +#include +#include + +#include "cppchecks/core.h" + +namespace CPPCHECKS_NAMESPACE +{ + template + class Item + { + public: + Item(T value, std::optional type_hint); + + const T &value() const { return this->_value; } + const std::optional &type_hint() const { return this->_type_hint; } + + // Display + virtual std::string display() const = 0; + // Debug + virtual std::string debug() const = 0; + + // Ordering + virtual inline bool operator<(const Item &other) const = 0; + virtual inline bool operator>(const Item &other) const { return &other < this; } + virtual inline bool operator<=(const Item &other) const { return !(this > &other); } + virtual inline bool operator>=(const Item &other) const { return !(this < &other); } + + // Comparison + virtual inline bool operator==(const Item &other) const = 0; + virtual inline bool operator!=(const Item &other) const { return !(this == &other); } + + private: + CChecksItem _item; + T _value; + std::optional _type_hint; + + static const char *type_hint_fn(const CChecksItem *item); + static const void *value_fn(const CChecksItem *item); + static void clone_fn(const CChecksItem *item, CChecksItem *other); + static void destroy_fn(CChecksItem *item); + static CChecksString debug_fn(const CChecksItem *item); + static CChecksString display_fn(const CChecksItem *item); + static bool lt_fn(const CChecksItem *item, const CChecksItem *other); + static bool eq_fn(const CChecksItem *item, const CChecksItem *other); + }; +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/include/cppchecks/items.h b/bindings/cpp/include/cppchecks/items.h new file mode 100644 index 0000000..974d9f8 --- /dev/null +++ b/bindings/cpp/include/cppchecks/items.h @@ -0,0 +1,49 @@ +#pragma once + +extern "C" +{ +#include +} + +#include + +#include "cppchecks/core.h" +#include "cppchecks/item.h" + +namespace CPPCHECKS_NAMESPACE +{ + template + class Items + { + public: + class iterator + { + public: + iterator(const CPPCHECKS_NAMESPACE::Item *items); + iterator &operator++(); + iterator operator++(int); + bool operator==(iterator other) const; + bool operator!=(iterator other) const; + const CPPCHECKS_NAMESPACE::Item &operator*(); + + // iterator traits + using difference_type = size_t; + using value_type = CPPCHECKS_NAMESPACE::Item; + using pointer = const CPPCHECKS_NAMESPACE::Item *; + using reference = const CPPCHECKS_NAMESPACE::Item &; + using iterator_category = std::input_iterator_tag; + + private: + const CPPCHECKS_NAMESPACE::Item *_items; + }; + + Items(const CChecksItem *items, size_t count); + + iterator begin(); + iterator end(); + + private: + const CPPCHECKS_NAMESPACE::Item *_items; + size_t _count; + }; +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/include/cppchecks/result.h b/bindings/cpp/include/cppchecks/result.h new file mode 100644 index 0000000..dea42de --- /dev/null +++ b/bindings/cpp/include/cppchecks/result.h @@ -0,0 +1,47 @@ +#pragma once + +extern "C" +{ +#include +} + +#include +#include +#include + +#include "cppchecks/core.h" +#include "cppchecks/item.h" +#include "cppchecks/items.h" +#include "cppchecks/status.h" + +namespace CPPCHECKS_NAMESPACE +{ + template + class CheckResult + { + public: + CheckResult(CPPCHECKS_NAMESPACE::Status status, const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip, std::optional error); + static CheckResult passed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip); + static CheckResult skipped(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip); + static CheckResult warning(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip); + static CheckResult failed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip); + ~CheckResult(); + + const CPPCHECKS_NAMESPACE::Status &status(); + std::string message(); + std::optional> items(); + bool can_fix(); + bool can_skip(); + std::optional error(); + double check_duration(); + double fix_duration(); + + private: + CheckResult() {} + CheckResult(CChecksCheckResult result) : _result(result) {} + CChecksCheckResult _result; + + static void items_destroy_fn(CChecksItem *item); + }; + +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/include/cppchecks/runner.h b/bindings/cpp/include/cppchecks/runner.h new file mode 100644 index 0000000..13e231a --- /dev/null +++ b/bindings/cpp/include/cppchecks/runner.h @@ -0,0 +1,23 @@ +#pragma once + +extern "C" +{ +#include +} + +#include +#include +#include + +#include "cppchecks/core.h" +#include "cppchecks/check.h" +#include "cppchecks/result.h" + +namespace CPPCHECKS_NAMESPACE +{ + template + CPPCHECKS_NAMESPACE::CheckResult run(const CPPCHECKS_NAMESPACE::BaseCheck &check); + + template + CPPCHECKS_NAMESPACE::CheckResult auto_fix(CPPCHECKS_NAMESPACE::BaseCheck &check); +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/include/cppchecks/status.h b/bindings/cpp/include/cppchecks/status.h new file mode 100644 index 0000000..efcd01c --- /dev/null +++ b/bindings/cpp/include/cppchecks/status.h @@ -0,0 +1,37 @@ +#pragma once + +extern "C" +{ +#include +} + +#include "cppchecks/core.h" + +namespace CPPCHECKS_NAMESPACE +{ + class Status + { + public: + enum Value + { + Pending = CChecksStatusPending, + Skipped = CChecksStatusSkipped, + Passed = CChecksStatusPassed, + Warning = CChecksStatusWarning, + Failed = CChecksStatusFailed, + SystemError = CChecksStatusSystemError, + }; + + Status() = default; + constexpr Status(Value status) : _value(status) {} + constexpr operator Value() const { return _value; } + explicit operator bool() const = delete; + + bool is_pending(); + bool has_passed(); + bool has_failed(); + + private: + Value _value; + }; +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/CMakeLists.txt b/bindings/cpp/src/CMakeLists.txt new file mode 100644 index 0000000..0978f78 --- /dev/null +++ b/bindings/cpp/src/CMakeLists.txt @@ -0,0 +1,28 @@ +set(CHECKS_HEADERS + ${PROJECT_SOURCE_DIR}/include/cppchecks/check.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/item.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/items.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/result.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/runner.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/status.h +) + +add_library(${CMAKE_PROJECT_NAME} + check.cpp + item.cpp + items.cpp + result.cpp + runner.cpp + status.cpp + ${CHECKS_HEADERS} +) + +set(CCHECKS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../c) +add_subdirectory(${PROJECT_SOURCE_DIR}/../c ${CMAKE_BINARY_DIR}/cchecks) + +target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/../c/include +) + +target_link_libraries(${CMAKE_PROJECT_NAME} cchecks) diff --git a/bindings/cpp/src/check.cpp b/bindings/cpp/src/check.cpp new file mode 100644 index 0000000..6a7c86b --- /dev/null +++ b/bindings/cpp/src/check.cpp @@ -0,0 +1,55 @@ +#include + +#include "cppchecks/check.h" + +namespace CPPCHECKS_NAMESPACE +{ + template + BaseCheck::BaseCheck() + { + _check.title_fn = title_fn; + _check.description_fn = description_fn; + _check.hint_fn = hint_fn; + _check.check_fn = check_fn; + _check.auto_fix_fn = auto_fix_fn; + } + + template + const char *BaseCheck::title_fn(const CChecksBaseCheck *check) + { + return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->title().c_str(); + } + + template + const char *BaseCheck::description_fn(const CChecksBaseCheck *check) + { + return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->description().c_str(); + } + + template + CChecksCheckHint BaseCheck::hint_fn(const CChecksBaseCheck *check) + { + return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->hint(); + } + + template + CChecksCheckResult BaseCheck::check_fn(const CChecksBaseCheck *check) + { + return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->check()._result; + } + + template + CChecksAutoFixResult BaseCheck::auto_fix_fn(const CChecksBaseCheck *check) + { + auto auto_fix_result = ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->auto_fix(); + + if (!auto_fix_result) + { + return cchecks_check_auto_fix_ok(); + } + else + { + return cchecks_check_auto_fix_error(auto_fix_result.value().c_str()); + } + } +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/item.cpp b/bindings/cpp/src/item.cpp new file mode 100644 index 0000000..cc4a20d --- /dev/null +++ b/bindings/cpp/src/item.cpp @@ -0,0 +1,117 @@ +#include + +#include "cppchecks/item.h" +#include "cppchecks/core.h" + +void destroy_str_fn(struct CChecksString *str) +{ + delete[] str->string; +} + +namespace CPPCHECKS_NAMESPACE +{ + template + Item::Item(T value, std::optional type_hint) + { + CChecksItem item; + item.type_hint_fn = nullptr; + item.value_fn = nullptr; + item.clone_fn = nullptr; + item.destroy_fn = nullptr; + item.debug_fn = nullptr; + item.display_fn = nullptr; + item.lt_fn = nullptr; + item.eq_fn = nullptr; + } + + template + const char *Item::type_hint_fn(const CChecksItem *item) + { + Item *cppitem = (Item *)item; + + if (cppitem->_type_hint) + { + return cppitem->_type_hint.value().c_str(); + } + else + { + return nullptr; + } + } + + template + const void *Item::value_fn(const CChecksItem *item) + { + Item *cppitem = (Item *)item; + + return (void *)&cppitem->_value; + } + + template + void Item::clone_fn(const CChecksItem *item, CChecksItem *other) + { + Item *cppitem = (Item *)item; + Item *cppother = (Item *)other; + other = Item(cppitem); + } + + template + void Item::destroy_fn(CChecksItem *item) + { + Item *cppitem = (Item *)item; + cppitem->~Item(); + } + + template + CChecksString Item::debug_fn(const CChecksItem *item) + { + Item *cppitem = (Item *)item; + + std::string msg = cppitem->debug(); + + char *cstr = new char[msg.length() + 1]; + std::strcpy(cstr, msg.c_str()); + + CChecksString cchecks_msg; + cchecks_msg.string = cstr; + cchecks_msg.destroy_fn = destroy_str_fn; + + return cchecks_msg; + } + + template + CChecksString Item::display_fn(const CChecksItem *item) + { + Item *cppitem = (Item *)item; + + std::string msg = cppitem->display(); + + char *cstr = new char[msg.length() + 1]; + std::strcpy(cstr, msg.c_str()); + + CChecksString cchecks_msg; + cchecks_msg.string = cstr; + cchecks_msg.destroy_fn = destroy_str_fn; + + return cchecks_msg; + } + + template + bool Item::lt_fn(const CChecksItem *item, const CChecksItem *other) + { + Item *cppitem = (Item *)item; + Item *cppother = (Item *)other; + + return cppitem < cppother; + } + + template + bool Item::eq_fn(const CChecksItem *item, const CChecksItem *other) + { + Item *cppitem = (Item *)item; + Item *cppother = (Item *)other; + + return cppitem == cppother; + } + +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/items.cpp b/bindings/cpp/src/items.cpp new file mode 100644 index 0000000..9da275e --- /dev/null +++ b/bindings/cpp/src/items.cpp @@ -0,0 +1,56 @@ +#include + +#include "cppchecks/items.h" +#include "cppchecks/core.h" + +namespace CPPCHECKS_NAMESPACE +{ + + template + Items::iterator::iterator(const CPPCHECKS_NAMESPACE::Item *items) : _items(items) {} + + template + typename Items::iterator &Items::iterator::operator++() { return *this + 1; } + + template + typename Items::iterator Items::iterator::operator++(int) + { + iterator retval = *this; + ++(*this); + return retval; + } + + template + bool Items::iterator::operator==(iterator other) const + { + return _items == other._items; + } + + template + bool Items::iterator::operator!=(iterator other) const + { + return !(*this == other); + } + + template + const CPPCHECKS_NAMESPACE::Item &Items::iterator::operator*() + { + return _items; + } + + template + Items::Items(const CChecksItem *items, size_t count) : _items(items), _count(count) {} + + template + typename Items::iterator Items::begin() + { + return Items::iterator(_items); + } + + template + typename Items::iterator Items::end() + { + return Items::iterator(_items + _count); + } + +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/result.cpp b/bindings/cpp/src/result.cpp new file mode 100644 index 0000000..9b8f25c --- /dev/null +++ b/bindings/cpp/src/result.cpp @@ -0,0 +1,197 @@ +#include + +#include "cppchecks/result.h" +#include "cppchecks/core.h" + +template +inline CPPCHECKS_NAMESPACE::Item *clone_vector(std::vector> &items) +{ + return (CPPCHECKS_NAMESPACE::Item *)malloc(sizeof(CPPCHECKS_NAMESPACE::Item) * items.size()); +} + +namespace CPPCHECKS_NAMESPACE +{ + + template + CheckResult::CheckResult(CPPCHECKS_NAMESPACE::Status status, const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip, std::optional error) + { + CChecksStatus cstatus = (CChecksStatus)(status); + char *cmessage = message.c_str(); + CChecksItem *citems = nullptr; + size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); + size_t item_count = 0; + char *cerror = nullptr; + + if (items) + { + citems = (CChecksItem *)clone_vector(items.value()); + item_count = items.value().size(); + } + + if (error) + { + cerror = error.value().c_str(); + } + + _result = cchecks_check_result_new(cstatus, cmessage, citems, item_size, item_count, can_fix, can_skip, cerror, items_destroy_fn); + } + + template + CheckResult CheckResult::passed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) + { + char *cmessage = message.c_str(); + CChecksItem *citems = nullptr; + size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); + size_t item_count = 0; + + if (items) + { + citems = (CChecksItem *)clone_vector(items.value()); + item_count = items.value().size(); + } + + CheckResult result; + result._result = cchecks_check_result_passed(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + + return result; + } + + template + CheckResult CheckResult::skipped(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) + { + char *cmessage = message.c_str(); + CChecksItem *citems = nullptr; + size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); + size_t item_count = 0; + + if (items) + { + citems = (CChecksItem *)clone_vector(items.value()); + item_count = items.value().size(); + } + + CheckResult result; + result._result = cchecks_check_result_skipped(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + + return result; + } + + template + CheckResult CheckResult::warning(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) + { + char *cmessage = message.c_str(); + CChecksItem *citems = nullptr; + size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); + size_t item_count = 0; + + if (items) + { + citems = (CChecksItem *)clone_vector(items.value()); + item_count = items.value().size(); + } + + CheckResult result; + result._result = cchecks_check_result_warning(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + + return result; + } + + template + CheckResult CheckResult::failed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) + { + char *cmessage = message.c_str(); + CChecksItem *citems = nullptr; + size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); + size_t item_count = 0; + + if (items) + { + citems = (CChecksItem *)clone_vector(items.value()); + item_count = items.value().size(); + } + + CheckResult result; + result._result = cchecks_check_result_failed(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + + return result; + } + + template + CheckResult::~CheckResult() + { + cchecks_check_result_destroy(&_result); + } + + template + const CPPCHECKS_NAMESPACE::Status &CheckResult::status() + { + return CPPCHECKS_NAMESPACE::Status(cchecks_check_result_status(&_result)); + } + + template + std::string CheckResult::message() + { + return std::string(cchecks_check_result_message(&_result).string); + } + + template + std::optional> CheckResult::items() + { + const CChecksItems *citems = cchecks_check_result_items(&_result); + + if (!citems) + { + return std::nullopt; + } + else + { + return CPPCHECKS_NAMESPACE::Items(citems->ptr, citems->length); + } + } + + template + bool CheckResult::can_fix() + { + return cchecks_check_result_can_fix(&_result); + } + + template + bool CheckResult::can_skip() + { + return cchecks_check_result_can_skip(&_result); + } + + template + std::optional CheckResult::error() + { + CChecksStringView cerr = cchecks_check_result_error(&_result); + + if (!cerr.string) + { + return std::nullopt; + } + else + { + return std::string(cerr.string); + } + } + + template + double CheckResult::check_duration() + { + return cchecks_check_result_check_duration(&_result); + } + + template + double CheckResult::fix_duration() + { + return cchecks_check_result_fix_duration(&_result); + } + + template + void CheckResult::items_destroy_fn(CChecksItem *item) + { + free((CPPCHECKS_NAMESPACE::Item *)item); + } + +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/runner.cpp b/bindings/cpp/src/runner.cpp new file mode 100644 index 0000000..eee02c7 --- /dev/null +++ b/bindings/cpp/src/runner.cpp @@ -0,0 +1,18 @@ +#include + +#include "cppchecks/runner.h" + +namespace CPPCHECKS_NAMESPACE +{ + template + CPPCHECKS_NAMESPACE::CheckResult run(const CPPCHECKS_NAMESPACE::BaseCheck &check) + { + CPPCHECKS_NAMESPACE::CheckResult(cchecks_run(&check._check)); + } + + template + CPPCHECKS_NAMESPACE::CheckResult auto_fix(CPPCHECKS_NAMESPACE::BaseCheck &check) + { + CPPCHECKS_NAMESPACE::CheckResult(cchecks_auto_fix(&check._check)); + } +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/status.cpp b/bindings/cpp/src/status.cpp new file mode 100644 index 0000000..81f324b --- /dev/null +++ b/bindings/cpp/src/status.cpp @@ -0,0 +1,21 @@ +#include "cppchecks/status.h" +#include "cppchecks/core.h" + +namespace CPPCHECKS_NAMESPACE +{ + bool Status::is_pending() + { + return cchecks_status_is_pending((CChecksStatus *)&_value); + } + + bool Status::has_passed() + { + return cchecks_status_has_passed((CChecksStatus *)&_value); + } + + bool Status::has_failed() + { + return cchecks_status_has_failed((CChecksStatus *)&_value); + } + +} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/tests/CMakeLists.txt b/bindings/cpp/tests/CMakeLists.txt new file mode 100644 index 0000000..06cbadb --- /dev/null +++ b/bindings/cpp/tests/CMakeLists.txt @@ -0,0 +1,31 @@ +set(TESTS + test_check + test_item + test_result + test_runner + test_status +) +set(TEST_HEADERS + item_impl.h +) + +foreach(TEST ${TESTS}) + add_executable(${TEST} ${TEST}.cpp + ${TEST_HEADERS} + ) + target_include_directories(${TEST} PRIVATE + "${PROJECT_SOURCE_DIR}/tests" + "${PROJECT_SOURCE_DIR}/include" + "${PROJECT_SOURCE_DIR}/../c/include" + "${PROJECT_SOURCE_DIR}/googletest/googlemock/include" + "${PROJECT_SOURCE_DIR}/googletest/googletest/include" + ) + target_link_libraries(${TEST} + PUBLIC + gtest + gtest_main + cchecks + cppchecks + ) + add_test(NAME ${TEST} COMMAND ${TEST}) +endforeach() diff --git a/bindings/cpp/tests/item_impl.h b/bindings/cpp/tests/item_impl.h new file mode 100644 index 0000000..3e510a8 --- /dev/null +++ b/bindings/cpp/tests/item_impl.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include +#include + +class IntItem : public cppchecks::Item +{ +public: + IntItem(int value, std::optional type_hint) : cppchecks::Item(value, type_hint) {} + + virtual std::string display() const + { + return std::to_string(this->value()); + } + + virtual std::string debug() const + { + std::ostringstream stream; + stream << "Item(" << this->value() << ")"; + + return std::string(stream.str()); + } + + virtual inline bool operator<(const Item &other) const { return this->value() < other.value(); } + + virtual inline bool operator==(const Item &other) const { return this->value() == other.value(); } +}; diff --git a/bindings/cpp/tests/test_check.cpp b/bindings/cpp/tests/test_check.cpp new file mode 100644 index 0000000..7ce7191 --- /dev/null +++ b/bindings/cpp/tests/test_check.cpp @@ -0,0 +1,7 @@ +#include +#include + +TEST(Check, ItWorks) +{ + ASSERT_EQ(1, 1); +} diff --git a/bindings/cpp/tests/test_item.cpp b/bindings/cpp/tests/test_item.cpp new file mode 100644 index 0000000..cd40b9d --- /dev/null +++ b/bindings/cpp/tests/test_item.cpp @@ -0,0 +1,12 @@ +#include +#include +#include +#include +#include + +#include "item_impl.h" + +TEST(Item, IntItemDisplaySuccess) +{ + IntItem item{1, std::string("test")}; +} diff --git a/bindings/cpp/tests/test_result.cpp b/bindings/cpp/tests/test_result.cpp new file mode 100644 index 0000000..2ef1478 --- /dev/null +++ b/bindings/cpp/tests/test_result.cpp @@ -0,0 +1,7 @@ +#include +#include + +TEST(CheckResult, ItWorks) +{ + ASSERT_EQ(1, 1); +} diff --git a/bindings/cpp/tests/test_runner.cpp b/bindings/cpp/tests/test_runner.cpp new file mode 100644 index 0000000..09b5242 --- /dev/null +++ b/bindings/cpp/tests/test_runner.cpp @@ -0,0 +1,7 @@ +#include +#include + +TEST(Runner, ItWorks) +{ + ASSERT_EQ(1, 1); +} diff --git a/bindings/cpp/tests/test_status.cpp b/bindings/cpp/tests/test_status.cpp new file mode 100644 index 0000000..e264c45 --- /dev/null +++ b/bindings/cpp/tests/test_status.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +TEST(Status, IsStatusPendingSuccess) +{ + auto cases = std::vector{ + std::make_tuple(cppchecks::Status::Pending, true), + std::make_tuple(cppchecks::Status::Skipped, false), + std::make_tuple(cppchecks::Status::Passed, false), + std::make_tuple(cppchecks::Status::Warning, false), + std::make_tuple(cppchecks::Status::Failed, false), + std::make_tuple(cppchecks::Status::SystemError, false), + }; + + cppchecks::Status status; + bool expected; + + for (auto &&test_case : cases) + { + status = std::get<0>(test_case); + expected = std::get<1>(test_case); + ASSERT_EQ(status.is_pending(), expected); + } +} + +TEST(Status, HasStatusPassedSuccess) +{ + auto cases = std::vector{ + std::make_tuple(cppchecks::Status::Pending, false), + std::make_tuple(cppchecks::Status::Skipped, true), + std::make_tuple(cppchecks::Status::Passed, true), + std::make_tuple(cppchecks::Status::Warning, true), + std::make_tuple(cppchecks::Status::Failed, false), + std::make_tuple(cppchecks::Status::SystemError, false), + }; + + cppchecks::Status status; + bool expected; + + for (auto &&test_case : cases) + { + status = std::get<0>(test_case); + expected = std::get<1>(test_case); + ASSERT_EQ(status.has_passed(), expected); + } +} + +TEST(Status, HasStatusFailedSuccess) +{ + auto cases = std::vector{ + std::make_tuple(cppchecks::Status::Pending, false), + std::make_tuple(cppchecks::Status::Skipped, false), + std::make_tuple(cppchecks::Status::Passed, false), + std::make_tuple(cppchecks::Status::Warning, false), + std::make_tuple(cppchecks::Status::Failed, true), + std::make_tuple(cppchecks::Status::SystemError, true), + }; + + cppchecks::Status status; + bool expected; + + for (auto &&test_case : cases) + { + status = std::get<0>(test_case); + expected = std::get<1>(test_case); + ASSERT_EQ(status.has_failed(), expected); + } +} From 732a8a36afdca868e4f6d467445643a3e98c7387 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Wed, 4 Jan 2023 06:54:44 -0800 Subject: [PATCH 02/18] Make Clang happy --- bindings/cpp/include/cppchecks/result.h | 16 ++++++------- bindings/cpp/include/cppchecks/status.h | 8 ++++--- bindings/cpp/src/result.cpp | 30 ++++++++++++------------- bindings/cpp/src/status.cpp | 25 ++++++++++++++++++--- bindings/cpp/tests/item_impl.h | 5 +++-- 5 files changed, 53 insertions(+), 31 deletions(-) diff --git a/bindings/cpp/include/cppchecks/result.h b/bindings/cpp/include/cppchecks/result.h index dea42de..37eb061 100644 --- a/bindings/cpp/include/cppchecks/result.h +++ b/bindings/cpp/include/cppchecks/result.h @@ -27,14 +27,14 @@ namespace CPPCHECKS_NAMESPACE static CheckResult failed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip); ~CheckResult(); - const CPPCHECKS_NAMESPACE::Status &status(); - std::string message(); - std::optional> items(); - bool can_fix(); - bool can_skip(); - std::optional error(); - double check_duration(); - double fix_duration(); + const CPPCHECKS_NAMESPACE::Status status() const; + std::string message() const; + std::optional> items() const; + bool can_fix() const; + bool can_skip() const; + std::optional error() const; + double check_duration() const; + double fix_duration() const; private: CheckResult() {} diff --git a/bindings/cpp/include/cppchecks/status.h b/bindings/cpp/include/cppchecks/status.h index efcd01c..ccc291e 100644 --- a/bindings/cpp/include/cppchecks/status.h +++ b/bindings/cpp/include/cppchecks/status.h @@ -27,9 +27,11 @@ namespace CPPCHECKS_NAMESPACE constexpr operator Value() const { return _value; } explicit operator bool() const = delete; - bool is_pending(); - bool has_passed(); - bool has_failed(); + bool is_pending() const; + bool has_passed() const; + bool has_failed() const; + + CChecksStatus c_status() const; private: Value _value; diff --git a/bindings/cpp/src/result.cpp b/bindings/cpp/src/result.cpp index 9b8f25c..ff81b05 100644 --- a/bindings/cpp/src/result.cpp +++ b/bindings/cpp/src/result.cpp @@ -15,12 +15,12 @@ namespace CPPCHECKS_NAMESPACE template CheckResult::CheckResult(CPPCHECKS_NAMESPACE::Status status, const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip, std::optional error) { - CChecksStatus cstatus = (CChecksStatus)(status); - char *cmessage = message.c_str(); + CChecksStatus cstatus = status.c_status(); + const char *cmessage = message.c_str(); CChecksItem *citems = nullptr; size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); size_t item_count = 0; - char *cerror = nullptr; + const char *cerror = nullptr; if (items) { @@ -39,7 +39,7 @@ namespace CPPCHECKS_NAMESPACE template CheckResult CheckResult::passed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) { - char *cmessage = message.c_str(); + const char *cmessage = message.c_str(); CChecksItem *citems = nullptr; size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); size_t item_count = 0; @@ -59,7 +59,7 @@ namespace CPPCHECKS_NAMESPACE template CheckResult CheckResult::skipped(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) { - char *cmessage = message.c_str(); + const char *cmessage = message.c_str(); CChecksItem *citems = nullptr; size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); size_t item_count = 0; @@ -79,7 +79,7 @@ namespace CPPCHECKS_NAMESPACE template CheckResult CheckResult::warning(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) { - char *cmessage = message.c_str(); + const char *cmessage = message.c_str(); CChecksItem *citems = nullptr; size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); size_t item_count = 0; @@ -99,7 +99,7 @@ namespace CPPCHECKS_NAMESPACE template CheckResult CheckResult::failed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) { - char *cmessage = message.c_str(); + const char *cmessage = message.c_str(); CChecksItem *citems = nullptr; size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); size_t item_count = 0; @@ -123,19 +123,19 @@ namespace CPPCHECKS_NAMESPACE } template - const CPPCHECKS_NAMESPACE::Status &CheckResult::status() + const CPPCHECKS_NAMESPACE::Status CheckResult::status() const { return CPPCHECKS_NAMESPACE::Status(cchecks_check_result_status(&_result)); } template - std::string CheckResult::message() + std::string CheckResult::message() const { return std::string(cchecks_check_result_message(&_result).string); } template - std::optional> CheckResult::items() + std::optional> CheckResult::items() const { const CChecksItems *citems = cchecks_check_result_items(&_result); @@ -150,19 +150,19 @@ namespace CPPCHECKS_NAMESPACE } template - bool CheckResult::can_fix() + bool CheckResult::can_fix() const { return cchecks_check_result_can_fix(&_result); } template - bool CheckResult::can_skip() + bool CheckResult::can_skip() const { return cchecks_check_result_can_skip(&_result); } template - std::optional CheckResult::error() + std::optional CheckResult::error() const { CChecksStringView cerr = cchecks_check_result_error(&_result); @@ -177,13 +177,13 @@ namespace CPPCHECKS_NAMESPACE } template - double CheckResult::check_duration() + double CheckResult::check_duration() const { return cchecks_check_result_check_duration(&_result); } template - double CheckResult::fix_duration() + double CheckResult::fix_duration() const { return cchecks_check_result_fix_duration(&_result); } diff --git a/bindings/cpp/src/status.cpp b/bindings/cpp/src/status.cpp index 81f324b..5973762 100644 --- a/bindings/cpp/src/status.cpp +++ b/bindings/cpp/src/status.cpp @@ -3,19 +3,38 @@ namespace CPPCHECKS_NAMESPACE { - bool Status::is_pending() + bool Status::is_pending() const { return cchecks_status_is_pending((CChecksStatus *)&_value); } - bool Status::has_passed() + bool Status::has_passed() const { return cchecks_status_has_passed((CChecksStatus *)&_value); } - bool Status::has_failed() + bool Status::has_failed() const { return cchecks_status_has_failed((CChecksStatus *)&_value); } + CChecksStatus Status::c_status() const + { + switch (_value) + { + case Status::Value::Pending: + return CChecksStatusPending; + case Status::Value::Skipped: + return CChecksStatusSkipped; + case Status::Value::Passed: + return CChecksStatusPassed; + case Status::Value::Warning: + return CChecksStatusWarning; + case Status::Value::Failed: + return CChecksStatusFailed; + case Status::Value::SystemError: + return CChecksStatusSystemError; + } + } + } // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/tests/item_impl.h b/bindings/cpp/tests/item_impl.h index 3e510a8..f2ea481 100644 --- a/bindings/cpp/tests/item_impl.h +++ b/bindings/cpp/tests/item_impl.h @@ -1,14 +1,15 @@ #pragma once +#include #include #include #include #include -class IntItem : public cppchecks::Item +class IntItem : public CPPCHECKS_NAMESPACE::Item { public: - IntItem(int value, std::optional type_hint) : cppchecks::Item(value, type_hint) {} + IntItem(int value, std::optional type_hint) : CPPCHECKS_NAMESPACE::Item(value, type_hint) {} virtual std::string display() const { From 45c11060f7b9343bb09d89cbf06eb41c3d21b610 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Wed, 4 Jan 2023 07:03:44 -0800 Subject: [PATCH 03/18] Fix issue with C build script --- bindings/c/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt index eacee09..1441250 100644 --- a/bindings/c/CMakeLists.txt +++ b/bindings/c/CMakeLists.txt @@ -19,7 +19,7 @@ set(UNIT_TESTING OFF) add_subdirectory(corrosion) if (NOT DEFINED CCHECKS_SOURCE_DIR OR CCHECKS_SOURCE_DIR MATCHES "") -set(CCHECKS_SOURCE_DIR, "${CMAKE_SOURCE_DIR}") +set(CCHECKS_SOURCE_DIR "${PROJECT_SOURCE_DIR}") endif() corrosion_import_crate(MANIFEST_PATH "${CCHECKS_SOURCE_DIR}/Cargo.toml") From 91736394bcffd3b2aa09b2e0366e432015f65a1f Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Sun, 15 Jan 2023 10:04:56 -0800 Subject: [PATCH 04/18] Stashing current work. The result checks are currently segfaulting, but no idea why. Stashing to work on something different in the mean time. --- bindings/c/CMakeLists.txt | 2 +- bindings/c/corrosion | 2 +- bindings/c/src/item.rs | 2 +- bindings/c/tests/test_check.c | 11 +- bindings/c/tests/test_item.c | 22 ++- bindings/c/tests/test_result.c | 11 +- bindings/c/tests/test_runner.c | 11 +- bindings/cpp/CMakeLists.txt | 28 +++- bindings/cpp/googletest | 2 +- bindings/cpp/include/cppchecks/check.h | 52 +++++- bindings/cpp/include/cppchecks/item.h | 156 +++++++++++++++--- bindings/cpp/include/cppchecks/items.h | 51 ++++-- bindings/cpp/include/cppchecks/result.h | 184 +++++++++++++++++++-- bindings/cpp/include/cppchecks/runner.h | 11 +- bindings/cpp/include/cppchecks/status.h | 40 ++++- bindings/cpp/src/CMakeLists.txt | 28 ---- bindings/cpp/src/check.cpp | 55 ------- bindings/cpp/src/item.cpp | 117 ------------- bindings/cpp/src/items.cpp | 56 ------- bindings/cpp/src/result.cpp | 197 ---------------------- bindings/cpp/src/runner.cpp | 18 -- bindings/cpp/src/status.cpp | 40 ----- bindings/cpp/tests/CMakeLists.txt | 7 +- bindings/cpp/tests/item_impl.h | 25 +-- bindings/cpp/tests/test_item.cpp | 209 +++++++++++++++++++++++- bindings/cpp/tests/test_items.cpp | 22 +++ bindings/cpp/tests/test_result.cpp | 110 ++++++++++++- 27 files changed, 850 insertions(+), 619 deletions(-) delete mode 100644 bindings/cpp/src/CMakeLists.txt delete mode 100644 bindings/cpp/src/check.cpp delete mode 100644 bindings/cpp/src/item.cpp delete mode 100644 bindings/cpp/src/items.cpp delete mode 100644 bindings/cpp/src/result.cpp delete mode 100644 bindings/cpp/src/runner.cpp delete mode 100644 bindings/cpp/src/status.cpp create mode 100644 bindings/cpp/tests/test_items.cpp diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt index 1441250..d09ae83 100644 --- a/bindings/c/CMakeLists.txt +++ b/bindings/c/CMakeLists.txt @@ -24,7 +24,7 @@ endif() corrosion_import_crate(MANIFEST_PATH "${CCHECKS_SOURCE_DIR}/Cargo.toml") -if (BUILD_TESTING) +if (BUILD_CCHECKS_TESTS) enable_testing() add_subdirectory(cmocka) add_subdirectory(tests) diff --git a/bindings/c/corrosion b/bindings/c/corrosion index ae043e1..e3d8d20 160000 --- a/bindings/c/corrosion +++ b/bindings/c/corrosion @@ -1 +1 @@ -Subproject commit ae043e17b6c7b52af980805589b630096e57bda6 +Subproject commit e3d8d200082fd49350dc6b9c4f974efc2402f6ae diff --git a/bindings/c/src/item.rs b/bindings/c/src/item.rs index 8e1a221..1ebd2e9 100644 --- a/bindings/c/src/item.rs +++ b/bindings/c/src/item.rs @@ -158,7 +158,7 @@ impl std::fmt::Debug for CChecksItem { unsafe { let c_str = CStr::from_ptr(c_display.string); let result = match c_str.to_str() { - Ok(s) => write!(f, "Item({})", s), + Ok(s) => write!(f, "{}", s), Err(_) => Err(std::fmt::Error), }; diff --git a/bindings/c/tests/test_check.c b/bindings/c/tests/test_check.c index 9049993..4c83703 100644 --- a/bindings/c/tests/test_check.c +++ b/bindings/c/tests/test_check.c @@ -64,7 +64,16 @@ void int_item_destroy_fn(CChecksItem *item) { } CChecksString int_item_debug_fn(const CChecksItem *item) { - return item->display_fn(item); + int value = ((IntItem *)item)->value; + size_t length = snprintf(NULL, 0, "Item(%d)", value); + char *debug_string = malloc(length + 1); + sprintf(debug_string, "Item(%d)", value); + + CChecksString result; + result.string = debug_string; + result.destroy_fn = destroy_string_ptr; + + return result; } CChecksString int_item_display_fn(const CChecksItem *item) { diff --git a/bindings/c/tests/test_item.c b/bindings/c/tests/test_item.c index 51b9365..0036bd2 100644 --- a/bindings/c/tests/test_item.c +++ b/bindings/c/tests/test_item.c @@ -63,7 +63,16 @@ void int_item_destroy_fn(CChecksItem *item) { } CChecksString int_item_debug_fn(const CChecksItem *item) { - return item->display_fn(item); + int value = ((IntItem *)item)->value; + size_t length = snprintf(NULL, 0, "Item(%d)", value); + char *debug_string = malloc(length + 1); + sprintf(debug_string, "Item(%d)", value); + + CChecksString result; + result.string = debug_string; + result.destroy_fn = destroy_string_ptr; + + return result; } CChecksString int_item_display_fn(const CChecksItem *item) { @@ -174,7 +183,16 @@ void string_item_destroy_fn(CChecksItem *item) { } CChecksString string_item_debug_fn(const CChecksItem *item) { - return item->display_fn(item); + char *value = ((StringItem *)item)->value; + size_t length = snprintf(NULL, 0, "Item(%s)", value); + char *debug_string = malloc(length + 1); + sprintf(debug_string, "Item(%s)", value); + + CChecksString result; + result.string = debug_string; + result.destroy_fn = destroy_string_ptr; + + return result; } CChecksString string_item_display_fn(const CChecksItem *item) { diff --git a/bindings/c/tests/test_result.c b/bindings/c/tests/test_result.c index 7312ae3..3c17afe 100644 --- a/bindings/c/tests/test_result.c +++ b/bindings/c/tests/test_result.c @@ -64,7 +64,16 @@ void int_item_destroy_fn(CChecksItem *item) { } CChecksString int_item_debug_fn(const CChecksItem *item) { - return item->display_fn(item); + int value = ((IntItem *)item)->value; + size_t length = snprintf(NULL, 0, "Item(%d)", value); + char *debug_string = malloc(length + 1); + sprintf(debug_string, "Item(%d)", value); + + CChecksString result; + result.string = debug_string; + result.destroy_fn = destroy_string_ptr; + + return result; } CChecksString int_item_display_fn(const CChecksItem *item) { diff --git a/bindings/c/tests/test_runner.c b/bindings/c/tests/test_runner.c index a42fa0a..6116b60 100644 --- a/bindings/c/tests/test_runner.c +++ b/bindings/c/tests/test_runner.c @@ -64,7 +64,16 @@ void int_item_destroy_fn(CChecksItem *item) { } CChecksString int_item_debug_fn(const CChecksItem *item) { - return item->display_fn(item); + int value = ((IntItem *)item)->value; + size_t length = snprintf(NULL, 0, "Item(%d)", value); + char *debug_string = malloc(length + 1); + sprintf(debug_string, "Item(%d)", value); + + CChecksString result; + result.string = debug_string; + result.destroy_fn = destroy_string_ptr; + + return result; } CChecksString int_item_display_fn(const CChecksItem *item) { diff --git a/bindings/cpp/CMakeLists.txt b/bindings/cpp/CMakeLists.txt index 9d23433..024113b 100644 --- a/bindings/cpp/CMakeLists.txt +++ b/bindings/cpp/CMakeLists.txt @@ -16,9 +16,33 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # -------------------------------------------------------------------------------- # Do the build # -------------------------------------------------------------------------------- -add_subdirectory(src) +set(CHECKS_HEADERS +${PROJECT_SOURCE_DIR}/include/cppchecks/check.h +${PROJECT_SOURCE_DIR}/include/cppchecks/item.h +${PROJECT_SOURCE_DIR}/include/cppchecks/items.h +${PROJECT_SOURCE_DIR}/include/cppchecks/result.h +${PROJECT_SOURCE_DIR}/include/cppchecks/runner.h +${PROJECT_SOURCE_DIR}/include/cppchecks/status.h +) -if (BUILD_TESTS) +add_library(${CMAKE_PROJECT_NAME} +${CHECKS_HEADERS} +) + +set(CCHECKS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../c) +add_subdirectory(${PROJECT_SOURCE_DIR}/../c ${CMAKE_BINARY_DIR}/cchecks) + +target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC +${PROJECT_SOURCE_DIR}/include +${PROJECT_SOURCE_DIR}/../c/include +) + +set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) +target_link_libraries(${CMAKE_PROJECT_NAME} cchecks) + +# add_subdirectory(src) + +if (BUILD_CPPCHECKS_TESTS) enable_testing() add_subdirectory(googletest) # For Windows: Prevent overriding the parent project's compiler/linker settings diff --git a/bindings/cpp/googletest b/bindings/cpp/googletest index 71140c3..356fc30 160000 --- a/bindings/cpp/googletest +++ b/bindings/cpp/googletest @@ -1 +1 @@ -Subproject commit 71140c3ca7a87bb1b5b9c9f1500fea8858cce344 +Subproject commit 356fc301251378e0f6fa6aa794d73714202887ac diff --git a/bindings/cpp/include/cppchecks/check.h b/bindings/cpp/include/cppchecks/check.h index 939ff80..285cf4d 100644 --- a/bindings/cpp/include/cppchecks/check.h +++ b/bindings/cpp/include/cppchecks/check.h @@ -5,9 +5,9 @@ extern "C" #include } -#include #include #include +#include #include "cppchecks/core.h" #include "cppchecks/item.h" @@ -27,20 +27,56 @@ namespace CPPCHECKS_NAMESPACE class BaseCheck { public: - BaseCheck(); + BaseCheck() + { + _check.title_fn = title_fn; + _check.description_fn = description_fn; + _check.hint_fn = hint_fn; + _check.check_fn = check_fn; + _check.auto_fix_fn = auto_fix_fn; + } + virtual std::string title() = 0; virtual std::string description() = 0; virtual CheckHint hint() = 0; virtual CPPCHECKS_NAMESPACE::CheckResult check() = 0; - virtual std::optional auto_fix() { return std::string("Auto fix is not implemented."); } + virtual std::string auto_fix() { return std::string("Auto fix is not implemented."); } private: CChecksBaseCheck _check; - static const char *title_fn(const CChecksBaseCheck *check); - static const char *description_fn(const CChecksBaseCheck *check); - static CChecksCheckHint hint_fn(const CChecksBaseCheck *check); - static CChecksCheckResult check_fn(const CChecksBaseCheck *check); - static CChecksAutoFixResult auto_fix_fn(const CChecksBaseCheck *check); + static const char *title_fn(const CChecksBaseCheck *check) + { + return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->title().c_str(); + } + + static const char *description_fn(const CChecksBaseCheck *check) + { + return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->description().c_str(); + } + + static CChecksCheckHint hint_fn(const CChecksBaseCheck *check) + { + return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->hint(); + } + + static CChecksCheckResult check_fn(const CChecksBaseCheck *check) + { + return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->check()._result; + } + + static CChecksAutoFixResult auto_fix_fn(const CChecksBaseCheck *check) + { + auto auto_fix_result = ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->auto_fix(); + + if (!auto_fix_result) + { + return cchecks_check_auto_fix_ok(); + } + else + { + return cchecks_check_auto_fix_error(auto_fix_result.value().c_str()); + } + } }; } // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/include/cppchecks/item.h b/bindings/cpp/include/cppchecks/item.h index e650987..74e6cd5 100644 --- a/bindings/cpp/include/cppchecks/item.h +++ b/bindings/cpp/include/cppchecks/item.h @@ -5,49 +5,159 @@ extern "C" #include } -#include #include +#include +#include +#include #include "cppchecks/core.h" namespace CPPCHECKS_NAMESPACE { + namespace _private + { + void destroy_str_fn(struct CChecksString *str) + { + delete[] str->string; + } + } // namespace _private + template - class Item + class Item : private CChecksItem { public: - Item(T value, std::optional type_hint); + Item(const T &value, const std::string &type_hint) : _value(value), _type_hint(type_hint) + { + this->init(); + } + + virtual ~Item() {} + + virtual void clone(const Item &other) + { + this->clone(&other); + } + + virtual void clone(const Item *other) + { + this->init(); + this->_value = other->value(); + this->_type_hint = other->type_hint(); + } const T &value() const { return this->_value; } - const std::optional &type_hint() const { return this->_type_hint; } + const std::string &type_hint() const { return this->_type_hint; } // Display - virtual std::string display() const = 0; + virtual std::string display() const + { + return std::to_string(this->value()); + } // Debug - virtual std::string debug() const = 0; + virtual std::string debug() const + { + std::ostringstream stream; + + stream << "Item(" << this->display() << ")"; + + return stream.str(); + } // Ordering - virtual inline bool operator<(const Item &other) const = 0; - virtual inline bool operator>(const Item &other) const { return &other < this; } - virtual inline bool operator<=(const Item &other) const { return !(this > &other); } - virtual inline bool operator>=(const Item &other) const { return !(this < &other); } + virtual inline bool operator<(const Item &other) const { return this->value() < other.value(); } + virtual inline bool operator>(const Item &other) const { return other < *this; } + virtual inline bool operator<=(const Item &other) const { return !(*this > other); } + virtual inline bool operator>=(const Item &other) const { return !(*this < other); } // Comparison - virtual inline bool operator==(const Item &other) const = 0; - virtual inline bool operator!=(const Item &other) const { return !(this == &other); } + virtual inline bool operator==(const Item &other) const { return this->value() == other.value(); } + virtual inline bool operator!=(const Item &other) const { return !(*this == other); } private: - CChecksItem _item; T _value; - std::optional _type_hint; - - static const char *type_hint_fn(const CChecksItem *item); - static const void *value_fn(const CChecksItem *item); - static void clone_fn(const CChecksItem *item, CChecksItem *other); - static void destroy_fn(CChecksItem *item); - static CChecksString debug_fn(const CChecksItem *item); - static CChecksString display_fn(const CChecksItem *item); - static bool lt_fn(const CChecksItem *item, const CChecksItem *other); - static bool eq_fn(const CChecksItem *item, const CChecksItem *other); + std::string _type_hint; + + void init() + { + this->type_hint_fn = _type_hint_impl; + this->value_fn = _value_impl; + this->clone_fn = _clone_impl; + this->destroy_fn = _destroy_impl; + this->debug_fn = _debug_impl; + this->display_fn = _display_impl; + this->lt_fn = _lt_impl; + this->eq_fn = _eq_impl; + } + + static const char *_type_hint_impl(const CChecksItem *item) + { + const char *type_hint = ((Item *)item)->type_hint().c_str(); + + if (type_hint == nullptr || std::string_view(type_hint).empty()) + { + return nullptr; + } + + return type_hint; + } + + static const void *_value_impl(const CChecksItem *item) + { + const T *value = &((Item *)item)->value(); + + return (void *)value; + } + + static void _clone_impl(const CChecksItem *item, CChecksItem *other) + { + ((Item *)item)->clone((Item *)other); + } + + static void _destroy_impl(CChecksItem *item) + { + ((Item *)item)->~Item(); + }; + + static CChecksString _debug_impl(const CChecksItem *item) + { + Item *cppitem = (Item *)item; + + std::string msg = cppitem->debug(); + + char *cstr = new char[msg.length() + 1]; + std::strcpy(cstr, msg.c_str()); + + CChecksString cchecks_msg; + cchecks_msg.string = cstr; + cchecks_msg.destroy_fn = CPPCHECKS_NAMESPACE::_private::destroy_str_fn; + + return cchecks_msg; + } + + static CChecksString _display_impl(const CChecksItem *item) + { + Item *cppitem = (Item *)item; + + std::string msg = cppitem->display(); + + char *cstr = new char[msg.length() + 1]; + std::strcpy(cstr, msg.c_str()); + + CChecksString cchecks_msg; + cchecks_msg.string = cstr; + cchecks_msg.destroy_fn = CPPCHECKS_NAMESPACE::_private::destroy_str_fn; + + return cchecks_msg; + } + + static bool _lt_impl(const CChecksItem *item, const CChecksItem *other) + { + return (*(Item *)item) < (*(Item *)other); + } + + static bool _eq_impl(const CChecksItem *item, const CChecksItem *other) + { + return (*(Item *)item) == (*(Item *)other); + } }; } // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/include/cppchecks/items.h b/bindings/cpp/include/cppchecks/items.h index 974d9f8..86d253f 100644 --- a/bindings/cpp/include/cppchecks/items.h +++ b/bindings/cpp/include/cppchecks/items.h @@ -5,7 +5,9 @@ extern "C" #include } +#include #include +#include #include "cppchecks/core.h" #include "cppchecks/item.h" @@ -19,15 +21,37 @@ namespace CPPCHECKS_NAMESPACE class iterator { public: - iterator(const CPPCHECKS_NAMESPACE::Item *items); - iterator &operator++(); - iterator operator++(int); - bool operator==(iterator other) const; - bool operator!=(iterator other) const; - const CPPCHECKS_NAMESPACE::Item &operator*(); + iterator(const CPPCHECKS_NAMESPACE::Item *items) : _items(items) {} + iterator &operator++() + { + this->_items++; + return *this; + } + iterator operator++(int) + { + iterator retval = *this; + ++(*this); + return retval; + } + + bool operator==(iterator &other) const + { + return this->_items == other._items; + } + + bool operator!=(iterator &other) const + { + return !(*this == other); + } + + const CPPCHECKS_NAMESPACE::Item &operator*() + { + return *_items; + } // iterator traits - using difference_type = size_t; + using difference_type = std::ptrdiff_t; + // using difference_type = size_t; using value_type = CPPCHECKS_NAMESPACE::Item; using pointer = const CPPCHECKS_NAMESPACE::Item *; using reference = const CPPCHECKS_NAMESPACE::Item &; @@ -37,10 +61,17 @@ namespace CPPCHECKS_NAMESPACE const CPPCHECKS_NAMESPACE::Item *_items; }; - Items(const CChecksItem *items, size_t count); + Items(const CPPCHECKS_NAMESPACE::Item *items, size_t count) : _items(items), _count(count) {} - iterator begin(); - iterator end(); + iterator begin() + { + return Items::iterator(_items); + } + + iterator end() + { + return Items::iterator(_items + _count); + } private: const CPPCHECKS_NAMESPACE::Item *_items; diff --git a/bindings/cpp/include/cppchecks/result.h b/bindings/cpp/include/cppchecks/result.h index 37eb061..9fde482 100644 --- a/bindings/cpp/include/cppchecks/result.h +++ b/bindings/cpp/include/cppchecks/result.h @@ -5,9 +5,11 @@ extern "C" #include } -#include +#include #include +#include #include +#include #include "cppchecks/core.h" #include "cppchecks/item.h" @@ -16,32 +18,180 @@ extern "C" namespace CPPCHECKS_NAMESPACE { + namespace _private + { + template + inline CPPCHECKS_NAMESPACE::Item *clone_vector(const std::vector> &items) + { + size_t array_size = sizeof(CPPCHECKS_NAMESPACE::Item) * items.size(); + void *citems_malloc = malloc(array_size); + CPPCHECKS_NAMESPACE::Item *citems = (CPPCHECKS_NAMESPACE::Item *)citems_malloc; + std::copy(items.cbegin(), items.cend(), citems); + + return citems; + } + } // namespace _private + template class CheckResult { public: - CheckResult(CPPCHECKS_NAMESPACE::Status status, const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip, std::optional error); - static CheckResult passed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip); - static CheckResult skipped(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip); - static CheckResult warning(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip); - static CheckResult failed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip); - ~CheckResult(); - - const CPPCHECKS_NAMESPACE::Status status() const; - std::string message() const; - std::optional> items() const; - bool can_fix() const; - bool can_skip() const; - std::optional error() const; - double check_duration() const; - double fix_duration() const; + CheckResult(CPPCHECKS_NAMESPACE::Status status, const std::string &message, const std::vector> &items, bool can_fix, bool can_skip, std::string error) + { + CChecksStatus cstatus = status.c_status(); + const char *cmessage = message.c_str(); + CChecksItem *citems = nullptr; + size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); + size_t item_count = 0; + const char *cerror = error.c_str(); + + citems = (CChecksItem *)CPPCHECKS_NAMESPACE::_private::clone_vector(items); + item_count = items.size(); + + _result = cchecks_check_result_new(cstatus, cmessage, citems, item_size, item_count, can_fix, can_skip, cerror, items_destroy_fn); + } + + static CheckResult passed(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) + { + const char *cmessage = message.c_str(); + CChecksItem *citems = nullptr; + size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); + size_t item_count = 0; + + citems = (CChecksItem *)CPPCHECKS_NAMESPACE::_private::clone_vector(items); + item_count = items.size(); + + CheckResult result; + result._result = cchecks_check_result_passed(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + + return result; + } + + static CheckResult skipped(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) + { + const char *cmessage = message.c_str(); + CChecksItem *citems = nullptr; + size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); + size_t item_count = 0; + + if (items) + { + citems = (CChecksItem *)CPPCHECKS_NAMESPACE::_private::clone_vector(items.value()); + item_count = items.value().size(); + } + + CheckResult result; + result._result = cchecks_check_result_skipped(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + + return result; + } + + static CheckResult warning(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) + { + const char *cmessage = message.c_str(); + CChecksItem *citems = nullptr; + size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); + size_t item_count = 0; + + if (items) + { + citems = (CChecksItem *)CPPCHECKS_NAMESPACE::_private::clone_vector(items.value()); + item_count = items.value().size(); + } + + CheckResult result; + result._result = cchecks_check_result_warning(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + + return result; + } + + static CheckResult failed(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) + { + const char *cmessage = message.c_str(); + CChecksItem *citems = nullptr; + size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); + size_t item_count = 0; + + if (items) + { + citems = (CChecksItem *)CPPCHECKS_NAMESPACE::_private::clone_vector(items.value()); + item_count = items.value().size(); + } + + CheckResult result; + result._result = cchecks_check_result_failed(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + + return result; + } + + virtual ~CheckResult() + { + // TODO: This causes double frees. + // cchecks_check_result_destroy(&this->_result); + } + + const CPPCHECKS_NAMESPACE::Status status() const + { + return CPPCHECKS_NAMESPACE::Status(cchecks_check_result_status((CChecksCheckResult *)&_result)); + } + + std::string_view message() const + { + return std::string_view(cchecks_check_result_message(&_result).string); + } + + CPPCHECKS_NAMESPACE::Items items() const + { + const CChecksItems *citems = cchecks_check_result_items(&_result); + + const CChecksItem *ptr = citems->ptr; + return CPPCHECKS_NAMESPACE::Items((const CPPCHECKS_NAMESPACE::Item *)ptr, citems->length); + } + + bool can_fix() const + { + return cchecks_check_result_can_fix(&_result); + } + + bool can_skip() const + { + return cchecks_check_result_can_skip(&_result); + } + + std::string error() const + { + CChecksStringView cerr = cchecks_check_result_error(&_result); + + if (!cerr.string) + { + return std::string(); + } + else + { + return std::string(cerr.string); + } + } + + double check_duration() const + { + return cchecks_check_result_check_duration(&_result); + } + + double fix_duration() const + { + return cchecks_check_result_fix_duration(&_result); + } private: CheckResult() {} CheckResult(CChecksCheckResult result) : _result(result) {} CChecksCheckResult _result; + std::vector> _items; - static void items_destroy_fn(CChecksItem *item); + static void items_destroy_fn(CChecksItem *item) + { + free((CPPCHECKS_NAMESPACE::Item *)item); + } }; } // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/include/cppchecks/runner.h b/bindings/cpp/include/cppchecks/runner.h index 13e231a..096a44e 100644 --- a/bindings/cpp/include/cppchecks/runner.h +++ b/bindings/cpp/include/cppchecks/runner.h @@ -5,7 +5,6 @@ extern "C" #include } -#include #include #include @@ -16,8 +15,14 @@ extern "C" namespace CPPCHECKS_NAMESPACE { template - CPPCHECKS_NAMESPACE::CheckResult run(const CPPCHECKS_NAMESPACE::BaseCheck &check); + CPPCHECKS_NAMESPACE::CheckResult run(const CPPCHECKS_NAMESPACE::BaseCheck &check) + { + CPPCHECKS_NAMESPACE::CheckResult(cchecks_run(&check._check)); + } template - CPPCHECKS_NAMESPACE::CheckResult auto_fix(CPPCHECKS_NAMESPACE::BaseCheck &check); + CPPCHECKS_NAMESPACE::CheckResult auto_fix(CPPCHECKS_NAMESPACE::BaseCheck &check) + { + CPPCHECKS_NAMESPACE::CheckResult(cchecks_auto_fix(&check._check)); + } } // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/include/cppchecks/status.h b/bindings/cpp/include/cppchecks/status.h index ccc291e..7fa6f21 100644 --- a/bindings/cpp/include/cppchecks/status.h +++ b/bindings/cpp/include/cppchecks/status.h @@ -24,14 +24,46 @@ namespace CPPCHECKS_NAMESPACE Status() = default; constexpr Status(Value status) : _value(status) {} + constexpr Status(CChecksStatus status) : _value((Status::Value)status) {} + constexpr operator Value() const { return _value; } explicit operator bool() const = delete; - bool is_pending() const; - bool has_passed() const; - bool has_failed() const; + bool is_pending() const + { + return cchecks_status_is_pending((CChecksStatus *)&_value); + } + + bool has_passed() const + { + return cchecks_status_has_passed((CChecksStatus *)&_value); + } - CChecksStatus c_status() const; + bool has_failed() const + { + return cchecks_status_has_failed((CChecksStatus *)&_value); + } + + CChecksStatus c_status() const + { + switch (_value) + { + case Status::Value::Pending: + return CChecksStatusPending; + case Status::Value::Skipped: + return CChecksStatusSkipped; + case Status::Value::Passed: + return CChecksStatusPassed; + case Status::Value::Warning: + return CChecksStatusWarning; + case Status::Value::Failed: + return CChecksStatusFailed; + case Status::Value::SystemError: + return CChecksStatusSystemError; + default: + return CChecksStatusSystemError; + } + } private: Value _value; diff --git a/bindings/cpp/src/CMakeLists.txt b/bindings/cpp/src/CMakeLists.txt deleted file mode 100644 index 0978f78..0000000 --- a/bindings/cpp/src/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -set(CHECKS_HEADERS - ${PROJECT_SOURCE_DIR}/include/cppchecks/check.h - ${PROJECT_SOURCE_DIR}/include/cppchecks/item.h - ${PROJECT_SOURCE_DIR}/include/cppchecks/items.h - ${PROJECT_SOURCE_DIR}/include/cppchecks/result.h - ${PROJECT_SOURCE_DIR}/include/cppchecks/runner.h - ${PROJECT_SOURCE_DIR}/include/cppchecks/status.h -) - -add_library(${CMAKE_PROJECT_NAME} - check.cpp - item.cpp - items.cpp - result.cpp - runner.cpp - status.cpp - ${CHECKS_HEADERS} -) - -set(CCHECKS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../c) -add_subdirectory(${PROJECT_SOURCE_DIR}/../c ${CMAKE_BINARY_DIR}/cchecks) - -target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC - ${PROJECT_SOURCE_DIR}/include - ${PROJECT_SOURCE_DIR}/../c/include -) - -target_link_libraries(${CMAKE_PROJECT_NAME} cchecks) diff --git a/bindings/cpp/src/check.cpp b/bindings/cpp/src/check.cpp deleted file mode 100644 index 6a7c86b..0000000 --- a/bindings/cpp/src/check.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include - -#include "cppchecks/check.h" - -namespace CPPCHECKS_NAMESPACE -{ - template - BaseCheck::BaseCheck() - { - _check.title_fn = title_fn; - _check.description_fn = description_fn; - _check.hint_fn = hint_fn; - _check.check_fn = check_fn; - _check.auto_fix_fn = auto_fix_fn; - } - - template - const char *BaseCheck::title_fn(const CChecksBaseCheck *check) - { - return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->title().c_str(); - } - - template - const char *BaseCheck::description_fn(const CChecksBaseCheck *check) - { - return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->description().c_str(); - } - - template - CChecksCheckHint BaseCheck::hint_fn(const CChecksBaseCheck *check) - { - return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->hint(); - } - - template - CChecksCheckResult BaseCheck::check_fn(const CChecksBaseCheck *check) - { - return ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->check()._result; - } - - template - CChecksAutoFixResult BaseCheck::auto_fix_fn(const CChecksBaseCheck *check) - { - auto auto_fix_result = ((CPPCHECKS_NAMESPACE::BaseCheck *)check)->auto_fix(); - - if (!auto_fix_result) - { - return cchecks_check_auto_fix_ok(); - } - else - { - return cchecks_check_auto_fix_error(auto_fix_result.value().c_str()); - } - } -} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/item.cpp b/bindings/cpp/src/item.cpp deleted file mode 100644 index cc4a20d..0000000 --- a/bindings/cpp/src/item.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include - -#include "cppchecks/item.h" -#include "cppchecks/core.h" - -void destroy_str_fn(struct CChecksString *str) -{ - delete[] str->string; -} - -namespace CPPCHECKS_NAMESPACE -{ - template - Item::Item(T value, std::optional type_hint) - { - CChecksItem item; - item.type_hint_fn = nullptr; - item.value_fn = nullptr; - item.clone_fn = nullptr; - item.destroy_fn = nullptr; - item.debug_fn = nullptr; - item.display_fn = nullptr; - item.lt_fn = nullptr; - item.eq_fn = nullptr; - } - - template - const char *Item::type_hint_fn(const CChecksItem *item) - { - Item *cppitem = (Item *)item; - - if (cppitem->_type_hint) - { - return cppitem->_type_hint.value().c_str(); - } - else - { - return nullptr; - } - } - - template - const void *Item::value_fn(const CChecksItem *item) - { - Item *cppitem = (Item *)item; - - return (void *)&cppitem->_value; - } - - template - void Item::clone_fn(const CChecksItem *item, CChecksItem *other) - { - Item *cppitem = (Item *)item; - Item *cppother = (Item *)other; - other = Item(cppitem); - } - - template - void Item::destroy_fn(CChecksItem *item) - { - Item *cppitem = (Item *)item; - cppitem->~Item(); - } - - template - CChecksString Item::debug_fn(const CChecksItem *item) - { - Item *cppitem = (Item *)item; - - std::string msg = cppitem->debug(); - - char *cstr = new char[msg.length() + 1]; - std::strcpy(cstr, msg.c_str()); - - CChecksString cchecks_msg; - cchecks_msg.string = cstr; - cchecks_msg.destroy_fn = destroy_str_fn; - - return cchecks_msg; - } - - template - CChecksString Item::display_fn(const CChecksItem *item) - { - Item *cppitem = (Item *)item; - - std::string msg = cppitem->display(); - - char *cstr = new char[msg.length() + 1]; - std::strcpy(cstr, msg.c_str()); - - CChecksString cchecks_msg; - cchecks_msg.string = cstr; - cchecks_msg.destroy_fn = destroy_str_fn; - - return cchecks_msg; - } - - template - bool Item::lt_fn(const CChecksItem *item, const CChecksItem *other) - { - Item *cppitem = (Item *)item; - Item *cppother = (Item *)other; - - return cppitem < cppother; - } - - template - bool Item::eq_fn(const CChecksItem *item, const CChecksItem *other) - { - Item *cppitem = (Item *)item; - Item *cppother = (Item *)other; - - return cppitem == cppother; - } - -} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/items.cpp b/bindings/cpp/src/items.cpp deleted file mode 100644 index 9da275e..0000000 --- a/bindings/cpp/src/items.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include - -#include "cppchecks/items.h" -#include "cppchecks/core.h" - -namespace CPPCHECKS_NAMESPACE -{ - - template - Items::iterator::iterator(const CPPCHECKS_NAMESPACE::Item *items) : _items(items) {} - - template - typename Items::iterator &Items::iterator::operator++() { return *this + 1; } - - template - typename Items::iterator Items::iterator::operator++(int) - { - iterator retval = *this; - ++(*this); - return retval; - } - - template - bool Items::iterator::operator==(iterator other) const - { - return _items == other._items; - } - - template - bool Items::iterator::operator!=(iterator other) const - { - return !(*this == other); - } - - template - const CPPCHECKS_NAMESPACE::Item &Items::iterator::operator*() - { - return _items; - } - - template - Items::Items(const CChecksItem *items, size_t count) : _items(items), _count(count) {} - - template - typename Items::iterator Items::begin() - { - return Items::iterator(_items); - } - - template - typename Items::iterator Items::end() - { - return Items::iterator(_items + _count); - } - -} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/result.cpp b/bindings/cpp/src/result.cpp deleted file mode 100644 index ff81b05..0000000 --- a/bindings/cpp/src/result.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#include - -#include "cppchecks/result.h" -#include "cppchecks/core.h" - -template -inline CPPCHECKS_NAMESPACE::Item *clone_vector(std::vector> &items) -{ - return (CPPCHECKS_NAMESPACE::Item *)malloc(sizeof(CPPCHECKS_NAMESPACE::Item) * items.size()); -} - -namespace CPPCHECKS_NAMESPACE -{ - - template - CheckResult::CheckResult(CPPCHECKS_NAMESPACE::Status status, const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip, std::optional error) - { - CChecksStatus cstatus = status.c_status(); - const char *cmessage = message.c_str(); - CChecksItem *citems = nullptr; - size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = 0; - const char *cerror = nullptr; - - if (items) - { - citems = (CChecksItem *)clone_vector(items.value()); - item_count = items.value().size(); - } - - if (error) - { - cerror = error.value().c_str(); - } - - _result = cchecks_check_result_new(cstatus, cmessage, citems, item_size, item_count, can_fix, can_skip, cerror, items_destroy_fn); - } - - template - CheckResult CheckResult::passed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) - { - const char *cmessage = message.c_str(); - CChecksItem *citems = nullptr; - size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = 0; - - if (items) - { - citems = (CChecksItem *)clone_vector(items.value()); - item_count = items.value().size(); - } - - CheckResult result; - result._result = cchecks_check_result_passed(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); - - return result; - } - - template - CheckResult CheckResult::skipped(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) - { - const char *cmessage = message.c_str(); - CChecksItem *citems = nullptr; - size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = 0; - - if (items) - { - citems = (CChecksItem *)clone_vector(items.value()); - item_count = items.value().size(); - } - - CheckResult result; - result._result = cchecks_check_result_skipped(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); - - return result; - } - - template - CheckResult CheckResult::warning(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) - { - const char *cmessage = message.c_str(); - CChecksItem *citems = nullptr; - size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = 0; - - if (items) - { - citems = (CChecksItem *)clone_vector(items.value()); - item_count = items.value().size(); - } - - CheckResult result; - result._result = cchecks_check_result_warning(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); - - return result; - } - - template - CheckResult CheckResult::failed(const std::string &message, const std::optional>> &items, bool can_fix, bool can_skip) - { - const char *cmessage = message.c_str(); - CChecksItem *citems = nullptr; - size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = 0; - - if (items) - { - citems = (CChecksItem *)clone_vector(items.value()); - item_count = items.value().size(); - } - - CheckResult result; - result._result = cchecks_check_result_failed(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); - - return result; - } - - template - CheckResult::~CheckResult() - { - cchecks_check_result_destroy(&_result); - } - - template - const CPPCHECKS_NAMESPACE::Status CheckResult::status() const - { - return CPPCHECKS_NAMESPACE::Status(cchecks_check_result_status(&_result)); - } - - template - std::string CheckResult::message() const - { - return std::string(cchecks_check_result_message(&_result).string); - } - - template - std::optional> CheckResult::items() const - { - const CChecksItems *citems = cchecks_check_result_items(&_result); - - if (!citems) - { - return std::nullopt; - } - else - { - return CPPCHECKS_NAMESPACE::Items(citems->ptr, citems->length); - } - } - - template - bool CheckResult::can_fix() const - { - return cchecks_check_result_can_fix(&_result); - } - - template - bool CheckResult::can_skip() const - { - return cchecks_check_result_can_skip(&_result); - } - - template - std::optional CheckResult::error() const - { - CChecksStringView cerr = cchecks_check_result_error(&_result); - - if (!cerr.string) - { - return std::nullopt; - } - else - { - return std::string(cerr.string); - } - } - - template - double CheckResult::check_duration() const - { - return cchecks_check_result_check_duration(&_result); - } - - template - double CheckResult::fix_duration() const - { - return cchecks_check_result_fix_duration(&_result); - } - - template - void CheckResult::items_destroy_fn(CChecksItem *item) - { - free((CPPCHECKS_NAMESPACE::Item *)item); - } - -} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/runner.cpp b/bindings/cpp/src/runner.cpp deleted file mode 100644 index eee02c7..0000000 --- a/bindings/cpp/src/runner.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include - -#include "cppchecks/runner.h" - -namespace CPPCHECKS_NAMESPACE -{ - template - CPPCHECKS_NAMESPACE::CheckResult run(const CPPCHECKS_NAMESPACE::BaseCheck &check) - { - CPPCHECKS_NAMESPACE::CheckResult(cchecks_run(&check._check)); - } - - template - CPPCHECKS_NAMESPACE::CheckResult auto_fix(CPPCHECKS_NAMESPACE::BaseCheck &check) - { - CPPCHECKS_NAMESPACE::CheckResult(cchecks_auto_fix(&check._check)); - } -} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/src/status.cpp b/bindings/cpp/src/status.cpp deleted file mode 100644 index 5973762..0000000 --- a/bindings/cpp/src/status.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "cppchecks/status.h" -#include "cppchecks/core.h" - -namespace CPPCHECKS_NAMESPACE -{ - bool Status::is_pending() const - { - return cchecks_status_is_pending((CChecksStatus *)&_value); - } - - bool Status::has_passed() const - { - return cchecks_status_has_passed((CChecksStatus *)&_value); - } - - bool Status::has_failed() const - { - return cchecks_status_has_failed((CChecksStatus *)&_value); - } - - CChecksStatus Status::c_status() const - { - switch (_value) - { - case Status::Value::Pending: - return CChecksStatusPending; - case Status::Value::Skipped: - return CChecksStatusSkipped; - case Status::Value::Passed: - return CChecksStatusPassed; - case Status::Value::Warning: - return CChecksStatusWarning; - case Status::Value::Failed: - return CChecksStatusFailed; - case Status::Value::SystemError: - return CChecksStatusSystemError; - } - } - -} // namespace CPPCHECKS_NAMESPACE diff --git a/bindings/cpp/tests/CMakeLists.txt b/bindings/cpp/tests/CMakeLists.txt index 06cbadb..091e182 100644 --- a/bindings/cpp/tests/CMakeLists.txt +++ b/bindings/cpp/tests/CMakeLists.txt @@ -1,6 +1,7 @@ set(TESTS test_check test_item + test_items test_result test_runner test_status @@ -14,17 +15,13 @@ foreach(TEST ${TESTS}) ${TEST_HEADERS} ) target_include_directories(${TEST} PRIVATE - "${PROJECT_SOURCE_DIR}/tests" + "${PROJECT_SOURCE_DIR}/tests" "${PROJECT_SOURCE_DIR}/include" - "${PROJECT_SOURCE_DIR}/../c/include" - "${PROJECT_SOURCE_DIR}/googletest/googlemock/include" "${PROJECT_SOURCE_DIR}/googletest/googletest/include" ) target_link_libraries(${TEST} PUBLIC - gtest gtest_main - cchecks cppchecks ) add_test(NAME ${TEST} COMMAND ${TEST}) diff --git a/bindings/cpp/tests/item_impl.h b/bindings/cpp/tests/item_impl.h index f2ea481..4861328 100644 --- a/bindings/cpp/tests/item_impl.h +++ b/bindings/cpp/tests/item_impl.h @@ -3,28 +3,5 @@ #include #include #include -#include -#include -class IntItem : public CPPCHECKS_NAMESPACE::Item -{ -public: - IntItem(int value, std::optional type_hint) : CPPCHECKS_NAMESPACE::Item(value, type_hint) {} - - virtual std::string display() const - { - return std::to_string(this->value()); - } - - virtual std::string debug() const - { - std::ostringstream stream; - stream << "Item(" << this->value() << ")"; - - return std::string(stream.str()); - } - - virtual inline bool operator<(const Item &other) const { return this->value() < other.value(); } - - virtual inline bool operator==(const Item &other) const { return this->value() == other.value(); } -}; +using IntItem = CPPCHECKS_NAMESPACE::Item; diff --git a/bindings/cpp/tests/test_item.cpp b/bindings/cpp/tests/test_item.cpp index cd40b9d..1891a50 100644 --- a/bindings/cpp/tests/test_item.cpp +++ b/bindings/cpp/tests/test_item.cpp @@ -1,12 +1,219 @@ +extern "C" +{ +#include +} + #include #include #include #include -#include #include "item_impl.h" +TEST(Item, IntItemValueSuccess) +{ + IntItem item{1, std::string("test")}; + ASSERT_EQ(item.value(), 1); +} + +TEST(Item, IntItemTypeHintSuccess) +{ + IntItem item{1, std::string("test")}; + ASSERT_EQ(item.type_hint(), std::string("test")); + + item = IntItem{1, ""}; + ASSERT_EQ(item.type_hint(), ""); +} + TEST(Item, IntItemDisplaySuccess) { IntItem item{1, std::string("test")}; + + ASSERT_EQ(item.display(), "1"); +} + +TEST(Item, IntItemDebugSuccess) +{ + IntItem item{1, std::string("test")}; + + ASSERT_EQ(item.debug(), "Item(1)"); +} + +TEST(Item, IntItemCloneSuccess) +{ + IntItem item{1, std::string("test")}; + IntItem other{2, std::string("other")}; + other.clone(item); + + ASSERT_EQ(item.value(), other.value()); + ASSERT_EQ(item.type_hint(), other.type_hint()); + ASSERT_NE(&item, &other); +} + +TEST(Item, IntItemLtSuccess) +{ + IntItem item{1, std::string("test")}; + IntItem other{2, std::string("test")}; + + ASSERT_LT(item, other); + + item = IntItem{1, std::string("test")}; + other = IntItem{1, std::string("test")}; + + ASSERT_FALSE(item < other); +} + +TEST(Item, IntItemLeSuccess) +{ + IntItem item{1, std::string("test")}; + IntItem other{2, std::string("test")}; + + ASSERT_LE(item, other); + + item = IntItem{1, std::string("test")}; + other = IntItem{1, std::string("test")}; + + ASSERT_LE(item, other); + + item = IntItem{2, std::string("test")}; + other = IntItem{1, std::string("test")}; + + ASSERT_FALSE(item <= other); +} + +TEST(Item, IntItemGtSuccess) +{ + IntItem item{2, std::string("test")}; + IntItem other{1, std::string("test")}; + + ASSERT_GT(item, other); + + item = IntItem{1, std::string("test")}; + other = IntItem{1, std::string("test")}; + + ASSERT_FALSE(item > other); +} + +TEST(Item, IntItemGeSuccess) +{ + IntItem item{2, std::string("test")}; + IntItem other{1, std::string("test")}; + + ASSERT_GE(item, other); + + item = IntItem{1, std::string("test")}; + other = IntItem{1, std::string("test")}; + + ASSERT_GE(item, other); + + item = IntItem{1, std::string("test")}; + other = IntItem{2, std::string("test")}; + + ASSERT_FALSE(item >= other); +} + +TEST(Item, IntItemEqSuccess) +{ + IntItem item{1, std::string("test")}; + IntItem other{1, std::string("test")}; + + ASSERT_EQ(item, other); + + item = IntItem{1, std::string("test")}; + other = IntItem{2, std::string("test")}; + + ASSERT_FALSE(item == other); +} + +TEST(Item, IntItemNeSuccess) +{ + IntItem item{1, std::string("test")}; + IntItem other{2, std::string("test")}; + + ASSERT_NE(item, other); + + item = IntItem{1, std::string("test")}; + other = IntItem{1, std::string("test")}; + + ASSERT_FALSE(item != other); +} + +TEST(Item, CIntItemValueSuccess) +{ + IntItem item{1, std::string("test")}; + ASSERT_EQ(*(int *)cchecks_item_value((CChecksItem *)&item), 1); +} + +TEST(Item, CIntItemTypeHintSuccess) +{ + IntItem item{1, std::string("test")}; + CChecksItem *citem = (CChecksItem *)&item; + const char *ctype_hint = cchecks_item_type_hint(citem); + + ASSERT_STREQ(ctype_hint, "test"); + + item = IntItem{1, ""}; + citem = (CChecksItem *)&item; + ctype_hint = cchecks_item_type_hint(citem); + + ASSERT_EQ(ctype_hint, nullptr); +} + +TEST(Item, CIntItemDisplaySuccess) +{ + IntItem item{1, std::string("test")}; + CChecksItem *citem = (CChecksItem *)&item; + CChecksString display = cchecks_item_display(citem); + + ASSERT_STREQ(display.string, "1"); + + cchecks_string_destroy(&display); +} + +TEST(Item, CIntItemDebugSuccess) +{ + IntItem item{1, std::string("test")}; + CChecksItem *citem = (CChecksItem *)&item; + CChecksString debug = cchecks_item_debug(citem); + + ASSERT_STREQ(debug.string, "Item(1)"); + + cchecks_string_destroy(&debug); +} + +TEST(Item, CIntItemCloneSuccess) +{ + IntItem item{1, std::string("test")}; + IntItem other{2, std::string("other")}; + cchecks_item_clone((CChecksItem *)&item, (CChecksItem *)&other); + + ASSERT_EQ(item.value(), other.value()); + ASSERT_EQ(item.type_hint(), other.type_hint()); + ASSERT_NE(&item, &other); +} + +TEST(Item, CIntItemLtSuccess) +{ + IntItem item{1, std::string("test")}; + IntItem other{2, std::string("test")}; + + ASSERT_TRUE(cchecks_item_lt((CChecksItem *)&item, (CChecksItem *)&other)); + + item = IntItem{1, std::string("test")}; + other = IntItem{1, std::string("test")}; + + ASSERT_FALSE(cchecks_item_lt((CChecksItem *)&item, (CChecksItem *)&other)); +} + +TEST(Item, CIntItemEqSuccess) +{ + IntItem item{1, std::string("test")}; + IntItem other{1, std::string("test")}; + + ASSERT_TRUE(cchecks_item_eq((CChecksItem *)&item, (CChecksItem *)&other)); + + item = IntItem{1, std::string("test")}; + other = IntItem{2, std::string("test")}; + + ASSERT_FALSE(cchecks_item_eq((CChecksItem *)&item, (CChecksItem *)&other)); } diff --git a/bindings/cpp/tests/test_items.cpp b/bindings/cpp/tests/test_items.cpp new file mode 100644 index 0000000..774d76b --- /dev/null +++ b/bindings/cpp/tests/test_items.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +#include "item_impl.h" + +TEST(CheckItems, IterateSuccess) +{ + std::vector vec{IntItem(0, ""), IntItem(1, ""), IntItem(2, "")}; + CPPCHECKS_NAMESPACE::Items items{vec.data(), vec.size()}; + int index = 0; + + for (auto &&item : items) + { + ASSERT_EQ(item.value(), index); + index++; + } + + ASSERT_EQ(index, vec.size()); +} diff --git a/bindings/cpp/tests/test_result.cpp b/bindings/cpp/tests/test_result.cpp index 2ef1478..e4298de 100644 --- a/bindings/cpp/tests/test_result.cpp +++ b/bindings/cpp/tests/test_result.cpp @@ -1,7 +1,113 @@ +#include +#include #include +#include +#include +#include +#include #include -TEST(CheckResult, ItWorks) +#include "item_impl.h" + +using IntResult = CPPCHECKS_NAMESPACE::CheckResult; + +void validate_result(IntResult &result, + CPPCHECKS_NAMESPACE::Status &status, + std::string &message, + std::vector &items, + bool can_fix, + bool can_skip, + std::string &error) +{ + EXPECT_EQ(result.status(), status); + EXPECT_EQ(result.message(), message); + + auto result_items = result.items(); + + int index = 0; + + for (auto &&item : result_items) + { + EXPECT_EQ(item.value(), index); + index++; + } + + EXPECT_EQ(index, items.size()); + + if (status == CPPCHECKS_NAMESPACE::Status::SystemError) + { + EXPECT_FALSE(result.can_fix()); + EXPECT_FALSE(result.can_skip()); + } + else + { + EXPECT_EQ(result.can_fix(), can_fix); + EXPECT_EQ(result.can_skip(), can_skip); + } + + EXPECT_EQ(result.error(), error); +} + +class ResultParameterizedTestFixture : public ::testing::TestWithParam, bool, bool, std::string>> +{ +}; + +TEST_P(ResultParameterizedTestFixture, ResultSuccess) +{ + CPPCHECKS_NAMESPACE::Status status = std::get<0>(GetParam()); + std::string message = std::get<1>(GetParam()); + std::vector items = std::get<2>(GetParam()); + bool can_fix = std::get<3>(GetParam()); + bool can_skip = std::get<4>(GetParam()); + std::string error = std::get<5>(GetParam()); + + IntResult result{status, message, items, can_fix, can_skip, error}; + + validate_result(result, status, message, items, can_fix, can_skip, error); +} + +// clang-format off +INSTANTIATE_TEST_SUITE_P( + CheckResult, + ResultParameterizedTestFixture, + ::testing::Combine( + ::testing::Values(CPPCHECKS_NAMESPACE::Status::Pending, CPPCHECKS_NAMESPACE::Status::Skipped, CPPCHECKS_NAMESPACE::Status::Passed, CPPCHECKS_NAMESPACE::Status::Warning, CPPCHECKS_NAMESPACE::Status::Failed, CPPCHECKS_NAMESPACE::Status::SystemError), + ::testing::Values(std::string("message")), + ::testing::Values(std::vector{IntItem(0, ""), IntItem(1, ""), IntItem(2, "")}), + ::testing::Bool(), + ::testing::Bool(), + ::testing::Values(std::string("error")) + ) +); +// clang-format on + +class StaticResultParameterizedTestFixture : public ::testing::TestWithParam, bool, bool>> +{ +}; + +TEST_P(StaticResultParameterizedTestFixture, ResultPassedSuccess) { - ASSERT_EQ(1, 1); + CPPCHECKS_NAMESPACE::Status status = CPPCHECKS_NAMESPACE::Status::Passed; + std::string message = std::get<0>(GetParam()); + std::vector items = std::get<1>(GetParam()); + bool can_fix = std::get<2>(GetParam()); + bool can_skip = std::get<3>(GetParam()); + std::string error = ""; + + IntResult result = IntResult::passed(message, items, can_fix, can_skip); + + validate_result(result, status, message, items, can_fix, can_skip, error); } + +// clang-format off +INSTANTIATE_TEST_SUITE_P( + CheckResult, + StaticResultParameterizedTestFixture, + ::testing::Combine( + ::testing::Values(std::string("message")), + ::testing::Values(std::vector{IntItem(0, ""), IntItem(1, ""), IntItem(2, "")}), + ::testing::Bool(), + ::testing::Bool() + ) +); +// clang-format on From 6e7cf0c208ad240036e9aa19ef12249e509ca606 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Wed, 10 Jan 2024 19:57:01 -0800 Subject: [PATCH 05/18] Make sure to drop string when destroying --- bindings/c/src/c_string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/c/src/c_string.rs b/bindings/c/src/c_string.rs index f5c1429..67036a6 100644 --- a/bindings/c/src/c_string.rs +++ b/bindings/c/src/c_string.rs @@ -42,7 +42,7 @@ impl CChecksString { pub(crate) fn new>(text: T) -> Self { unsafe extern "C" fn destroy_fn(string: *mut CChecksString) { if !(*string).string.is_null() { - unsafe { CString::from_raw((*string).string) }; + unsafe { drop(CString::from_raw((*string).string)) }; } } From d0bc6a6bfd1cdd432959d01e71a382331b6ca55d Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Wed, 10 Jan 2024 19:57:13 -0800 Subject: [PATCH 06/18] Update dependencies and fixing C tests --- .github/workflows/test_suite_c.yml | 2 +- bindings/c/Cargo.toml | 4 ++-- bindings/c/src/item.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_suite_c.yml b/.github/workflows/test_suite_c.yml index 9fa37a3..4aefd3c 100644 --- a/.github/workflows/test_suite_c.yml +++ b/.github/workflows/test_suite_c.yml @@ -67,7 +67,7 @@ jobs: working-directory: bindings/c/build run: | # Make cmocka a static dependency when testing. - cmake ../ -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=ON + cmake ../ -DBUILD_SHARED_LIBS=OFF -DBUILD_CCHECKS_TESTS=ON - name: CMake Build working-directory: bindings/c/build run: | diff --git a/bindings/c/Cargo.toml b/bindings/c/Cargo.toml index 5f69060..922d76c 100644 --- a/bindings/c/Cargo.toml +++ b/bindings/c/Cargo.toml @@ -18,8 +18,8 @@ panic = "abort" [dependencies] checks = { path = "../../" } -bitflags = "2.0.0" -libc = "0.2.138" +bitflags = "2.4.1" +libc = "0.2.152" [build-dependencies] cbindgen = "0.26.0" diff --git a/bindings/c/src/item.rs b/bindings/c/src/item.rs index 579051c..0a145c0 100644 --- a/bindings/c/src/item.rs +++ b/bindings/c/src/item.rs @@ -260,7 +260,7 @@ pub unsafe extern "C" fn cchecks_item_destroy(item: *mut CChecksItem) { /// The item pointer must not be null. #[no_mangle] pub unsafe extern "C" fn cchecks_item_debug(item: *const CChecksItem) -> crate::CChecksString { - let result = format!("{:?}", (*item)); + let result = format!("Item({:?})", (*item)); crate::CChecksString::new(result) } From 5978833cd369f6ca77a88c1ffd954ab14d454cf8 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Wed, 10 Jan 2024 21:41:11 -0800 Subject: [PATCH 07/18] Prevent segfault when copying items --- bindings/cpp/include/cppchecks/result.h | 38 ++++++++----------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/bindings/cpp/include/cppchecks/result.h b/bindings/cpp/include/cppchecks/result.h index 9fde482..23fbb07 100644 --- a/bindings/cpp/include/cppchecks/result.h +++ b/bindings/cpp/include/cppchecks/result.h @@ -18,25 +18,11 @@ extern "C" namespace CPPCHECKS_NAMESPACE { - namespace _private - { - template - inline CPPCHECKS_NAMESPACE::Item *clone_vector(const std::vector> &items) - { - size_t array_size = sizeof(CPPCHECKS_NAMESPACE::Item) * items.size(); - void *citems_malloc = malloc(array_size); - CPPCHECKS_NAMESPACE::Item *citems = (CPPCHECKS_NAMESPACE::Item *)citems_malloc; - std::copy(items.cbegin(), items.cend(), citems); - - return citems; - } - } // namespace _private - template class CheckResult { public: - CheckResult(CPPCHECKS_NAMESPACE::Status status, const std::string &message, const std::vector> &items, bool can_fix, bool can_skip, std::string error) + CheckResult(CPPCHECKS_NAMESPACE::Status status, const std::string &message, const std::vector> &items, bool can_fix, bool can_skip, std::string error) : _items(items) { CChecksStatus cstatus = status.c_status(); const char *cmessage = message.c_str(); @@ -45,10 +31,9 @@ namespace CPPCHECKS_NAMESPACE size_t item_count = 0; const char *cerror = error.c_str(); - citems = (CChecksItem *)CPPCHECKS_NAMESPACE::_private::clone_vector(items); item_count = items.size(); - _result = cchecks_check_result_new(cstatus, cmessage, citems, item_size, item_count, can_fix, can_skip, cerror, items_destroy_fn); + _result = cchecks_check_result_new(cstatus, cmessage, (CChecksItem *)_items.data(), item_size, item_count, can_fix, can_skip, cerror, items_destroy_fn); } static CheckResult passed(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) @@ -58,11 +43,11 @@ namespace CPPCHECKS_NAMESPACE size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); size_t item_count = 0; - citems = (CChecksItem *)CPPCHECKS_NAMESPACE::_private::clone_vector(items); item_count = items.size(); CheckResult result; - result._result = cchecks_check_result_passed(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + result._items = items; + result._result = cchecks_check_result_passed(cmessage, (CChecksItem *)result._items.data(), item_size, item_count, can_fix, can_skip, items_destroy_fn); return result; } @@ -76,12 +61,12 @@ namespace CPPCHECKS_NAMESPACE if (items) { - citems = (CChecksItem *)CPPCHECKS_NAMESPACE::_private::clone_vector(items.value()); item_count = items.value().size(); } CheckResult result; - result._result = cchecks_check_result_skipped(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + result._items = items; + result._result = cchecks_check_result_skipped(cmessage, (CChecksItem *)result._items.data(), item_size, item_count, can_fix, can_skip, items_destroy_fn); return result; } @@ -95,12 +80,12 @@ namespace CPPCHECKS_NAMESPACE if (items) { - citems = (CChecksItem *)CPPCHECKS_NAMESPACE::_private::clone_vector(items.value()); item_count = items.value().size(); } CheckResult result; - result._result = cchecks_check_result_warning(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + result._items = items; + result._result = cchecks_check_result_warning(cmessage, (CChecksItem *)result._items.data(), item_size, item_count, can_fix, can_skip, items_destroy_fn); return result; } @@ -114,12 +99,12 @@ namespace CPPCHECKS_NAMESPACE if (items) { - citems = (CChecksItem *)CPPCHECKS_NAMESPACE::_private::clone_vector(items.value()); item_count = items.value().size(); } CheckResult result; - result._result = cchecks_check_result_failed(cmessage, citems, item_size, item_count, can_fix, can_skip, items_destroy_fn); + result._items = items; + result._result = cchecks_check_result_failed(cmessage, (CChecksItem *)result._items.data(), item_size, item_count, can_fix, can_skip, items_destroy_fn); return result; } @@ -190,7 +175,8 @@ namespace CPPCHECKS_NAMESPACE static void items_destroy_fn(CChecksItem *item) { - free((CPPCHECKS_NAMESPACE::Item *)item); + // Do not destroy the items, since C++ will handle the destruction. + // The items are owned by the class itself, and the C result type references it. } }; From 30c60cc5d7bfa5bbe54a214b9772bafe2e01ae98 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Wed, 10 Jan 2024 21:41:39 -0800 Subject: [PATCH 08/18] fix misc test errors --- bindings/cpp/include/cppchecks/item.h | 2 +- bindings/cpp/tests/test_status.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/cpp/include/cppchecks/item.h b/bindings/cpp/include/cppchecks/item.h index 74e6cd5..2bccec7 100644 --- a/bindings/cpp/include/cppchecks/item.h +++ b/bindings/cpp/include/cppchecks/item.h @@ -122,7 +122,7 @@ namespace CPPCHECKS_NAMESPACE { Item *cppitem = (Item *)item; - std::string msg = cppitem->debug(); + std::string msg = cppitem->display(); char *cstr = new char[msg.length() + 1]; std::strcpy(cstr, msg.c_str()); diff --git a/bindings/cpp/tests/test_status.cpp b/bindings/cpp/tests/test_status.cpp index e264c45..83c4bbd 100644 --- a/bindings/cpp/tests/test_status.cpp +++ b/bindings/cpp/tests/test_status.cpp @@ -29,7 +29,7 @@ TEST(Status, HasStatusPassedSuccess) { auto cases = std::vector{ std::make_tuple(cppchecks::Status::Pending, false), - std::make_tuple(cppchecks::Status::Skipped, true), + std::make_tuple(cppchecks::Status::Skipped, false), std::make_tuple(cppchecks::Status::Passed, true), std::make_tuple(cppchecks::Status::Warning, true), std::make_tuple(cppchecks::Status::Failed, false), From fe575ccd5db8dc0b34f258a75c95b46449f19412 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Wed, 10 Jan 2024 21:53:15 -0800 Subject: [PATCH 09/18] Update workflows --- .github/workflows/codeql_c.yml | 30 ++------- .github/workflows/codeql_cpp.yml | 82 +++++++++++++++++++++++++ .github/workflows/codeql_python.yml | 24 +++++--- .github/workflows/rust-audit.yml | 13 ++++ .github/workflows/test_suite_c.yml | 26 ++------ .github/workflows/test_suite_cpp.yml | 73 ++++++++++++++++++++++ .github/workflows/test_suite_python.yml | 32 +++++----- .github/workflows/test_suite_rust.yml | 4 +- 8 files changed, 211 insertions(+), 73 deletions(-) create mode 100644 .github/workflows/codeql_cpp.yml create mode 100644 .github/workflows/test_suite_cpp.yml diff --git a/.github/workflows/codeql_c.yml b/.github/workflows/codeql_c.yml index a2fa9a0..3436c22 100644 --- a/.github/workflows/codeql_c.yml +++ b/.github/workflows/codeql_c.yml @@ -15,17 +15,8 @@ on: push: branches: ["main"] paths: - - .github/workflows/codeql_c.yml - - bindings/c/cmocka/** - - bindings/c/corrosion/** - - bindings/c/include/** - - bindings/c/src/** - - bindings/c/tests/** - - bindings/c/build.rs - - bindings/c/Cargo.toml - - bindings/c/Cargo.lock - - bindings/c/cbindgen.toml - - bindings/c/CMakeLists.txt + - .github/workflows/*_c.yml + - bindings/c/** - src/** - Cargo.lock - Cargo.toml @@ -35,18 +26,9 @@ on: # The branches below must be a subset of the branches above branches: ["main"] paths: - - .github/workflows/codeql_c.yml - - bindings/c/cmocka/** - - bindings/c/corrosion/** - - bindings/c/include/** - - bindings/c/src/** - - bindings/c/tests/** - - bindings/c/build.rs - - bindings/c/Cargo.toml - - bindings/c/Cargo.lock - - bindings/c/cbindgen.toml - - bindings/c/CMakeLists.txt - - src/* + - .github/workflows/*_c.yml + - bindings/c/** + - src/** - Cargo.lock - Cargo.toml - deny.toml @@ -87,7 +69,7 @@ jobs: working-directory: bindings/c/build run: | # Make cmocka a static dependency when testing. - cmake ../ -DBUILD_SHARED_LIBS=OFF + cmake ../ -DBUILD_SHARED_LIBS=OFF -DBUILD_CCHECKS_TESTS=ON - name: CMake Build working-directory: bindings/c/build run: | diff --git a/.github/workflows/codeql_cpp.yml b/.github/workflows/codeql_cpp.yml new file mode 100644 index 0000000..e36ba4b --- /dev/null +++ b/.github/workflows/codeql_cpp.yml @@ -0,0 +1,82 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: ["main"] + paths: + - .github/workflows/*_cpp.yml + - bindings/cpp/** + - src/** + - Cargo.lock + - Cargo.toml + - deny.toml + - .gitmodules + pull_request: + # The branches below must be a subset of the branches above + branches: ["main"] + paths: + - .github/workflows/*_cpp.yml + - bindings/cpp/** + - src/** + - Cargo.lock + - Cargo.toml + - deny.toml + - .gitmodules + schedule: + - cron: "0 0 * * 1" + +jobs: + analyze_cpp: + name: Analyze C++ + defaults: + run: + working-directory: bindings/cpp + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: recursive + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: cpp + + # Build C Project + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - name: Make Build Directory + run: mkdir -p build + - name: CMake Configure + working-directory: bindings/cpp/build + run: | + # Make cmocka a static dependency when testing. + cmake ../ -DBUILD_SHARED_LIBS=OFF -DBUILD_CPPCHECKS_TESTS=ON + - name: CMake Build + working-directory: bindings/cpp/build + run: | + cmake --build . --config=Debug + + # Run the analysis + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:cpp" diff --git a/.github/workflows/codeql_python.yml b/.github/workflows/codeql_python.yml index d033b8c..bd51b2e 100644 --- a/.github/workflows/codeql_python.yml +++ b/.github/workflows/codeql_python.yml @@ -15,20 +15,24 @@ on: push: branches: ["main"] paths: - - .github/workflows/codeql_python.yml - - bindings/python/pychecks/** - - bindings/python/tests/** - - bindings/python/conftest.py - - bindings/python/pyproject.toml + - .github/workflows/*_python.yml + - bindings/python/** + - src/** + - Cargo.lock + - Cargo.toml + - deny.toml + - .gitmodules pull_request: # The branches below must be a subset of the branches above branches: ["main"] paths: - - .github/workflows/codeql_python.yml - - bindings/python/pychecks/** - - bindings/python/tests/** - - bindings/python/conftest.py - - bindings/python/pyproject.toml + - .github/workflows/*_python.yml + - bindings/python/** + - src/** + - Cargo.lock + - Cargo.toml + - deny.toml + - .gitmodules schedule: - cron: "0 0 * * 1" diff --git a/.github/workflows/rust-audit.yml b/.github/workflows/rust-audit.yml index 2f857f1..59d1709 100644 --- a/.github/workflows/rust-audit.yml +++ b/.github/workflows/rust-audit.yml @@ -26,6 +26,19 @@ jobs: - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - uses: EmbarkStudios/cargo-deny-action@v1 + audit_cpp: + name: Audit C++ + runs-on: ubuntu-latest + defaults: + run: + working-directory: bindings/cpp + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - uses: EmbarkStudios/cargo-deny-action@v1 audit_python: name: Audit Python runs-on: ubuntu-latest diff --git a/.github/workflows/test_suite_c.yml b/.github/workflows/test_suite_c.yml index 4aefd3c..c74f0c5 100644 --- a/.github/workflows/test_suite_c.yml +++ b/.github/workflows/test_suite_c.yml @@ -3,17 +3,8 @@ name: C Test Suite on: push: paths: - - .github/workflows/test_suite_c.yml - - bindings/c/cmocka/** - - bindings/c/corrosion/** - - bindings/c/include/** - - bindings/c/src/** - - bindings/c/tests/** - - bindings/c/build.rs - - bindings/c/Cargo.toml - - bindings/c/Cargo.lock - - bindings/c/cbindgen.toml - - bindings/c/CMakeLists.txt + - .github/workflows/*_c.yml + - bindings/c/** - src/** - Cargo.lock - Cargo.toml @@ -21,17 +12,8 @@ on: - .gitmodules pull_request: paths: - - .github/workflows/test_suite_c.yml - - bindings/c/cmocka/** - - bindings/c/corrosion/** - - bindings/c/include/** - - bindings/c/src/** - - bindings/c/tests/** - - bindings/c/build.rs - - bindings/c/Cargo.toml - - bindings/c/Cargo.lock - - bindings/c/cbindgen.toml - - bindings/c/CMakeLists.txt + - .github/workflows/*_c.yml + - bindings/c/** - src/** - Cargo.lock - Cargo.toml diff --git a/.github/workflows/test_suite_cpp.yml b/.github/workflows/test_suite_cpp.yml new file mode 100644 index 0000000..eeb4bc3 --- /dev/null +++ b/.github/workflows/test_suite_cpp.yml @@ -0,0 +1,73 @@ +name: C Test Suite + +on: + push: + paths: + - .github/workflows/*_cpp.yml + - bindings/cpp/** + - src/** + - Cargo.lock + - Cargo.toml + - deny.toml + - .gitmodules + pull_request: + paths: + - .github/workflows/*_cpp.yml + - bindings/cpp/** + - src/** + - Cargo.lock + - Cargo.toml + - deny.toml + - .gitmodules + +jobs: + test: + name: C++ test + defaults: + run: + working-directory: bindings/cpp + strategy: + matrix: + os: + - ubuntu-latest + - windows-latest + - macos-latest + runs-on: ${{matrix.os}} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@cargo-llvm-cov + - run: cargo clippy + - run: cargo llvm-cov --all-features --lcov --output-path lcov.info + - name: Make Build Directory + run: mkdir -p build + - name: CMake Configure + working-directory: bindings/cpp/build + run: | + # Make cmocka a static dependency when testing. + cmake ../ -DBUILD_SHARED_LIBS=OFF -DBUILD_CPPCHECKS_TESTS=ON + - name: CMake Build + working-directory: bindings/cpp/build + run: | + cmake --build . --config=Debug + - name: Run Test + working-directory: bindings/cpp/build + run: ctest -C Debug -VV --output-on-failure + - name: Run Valgrind + working-directory: bindings/cpp/build + if: ${{ matrix.os == 'ubuntu-latest' }} + run: | + sudo apt install -y valgrind + valgrind -v --leak-check=full --show-leak-kinds=all tests/test_check + valgrind -v --leak-check=full --show-leak-kinds=all tests/test_item + valgrind -v --leak-check=full --show-leak-kinds=all tests/test_result + valgrind -v --leak-check=full --show-leak-kinds=all tests/test_runner + valgrind -v --leak-check=full --show-leak-kinds=all tests/test_status + - uses: codecov/codecov-action@v3 + with: + files: lcov.info + flags: lang-cpp diff --git a/.github/workflows/test_suite_python.yml b/.github/workflows/test_suite_python.yml index 567979d..8005e7a 100644 --- a/.github/workflows/test_suite_python.yml +++ b/.github/workflows/test_suite_python.yml @@ -2,21 +2,23 @@ name: Python Test Suite on: push: - # paths: - # - .github/workflows/test_suite_python.yml - # - bindings/python/conftest.py - # - bindings/python/pychecks/** - # - bindings/python/pyproject.toml - # - bindings/python/src/** - # - bindings/python/tests/** - # pull_request: - # paths: - # - .github/workflows/test_suite_python.yml - # - bindings/python/conftest.py - # - bindings/python/pychecks/** - # - bindings/python/pyproject.toml - # - bindings/python/src/** - # - bindings/python/tests/** + paths: + - .github/workflows/*_python.yml + - bindings/python/** + - src/** + - Cargo.lock + - Cargo.toml + - deny.toml + - .gitmodules + pull_request: + paths: + - .github/workflows/*_python.yml + - bindings/python/** + - src/** + - Cargo.lock + - Cargo.toml + - deny.toml + - .gitmodules jobs: test: diff --git a/.github/workflows/test_suite_rust.yml b/.github/workflows/test_suite_rust.yml index 45e6ba1..fb35f7b 100644 --- a/.github/workflows/test_suite_rust.yml +++ b/.github/workflows/test_suite_rust.yml @@ -3,7 +3,7 @@ name: Rust Test Suite on: push: paths: - - .github/workflows/test_suite_rust.yml + - .github/workflows/*_rust.yml - src/** - tests/** - Cargo.lock @@ -11,7 +11,7 @@ on: - deny.toml pull_request: paths: - - .github/workflows/test_suite_rust.yml + - .github/workflows/*_rust.yml - src/** - tests/** - Cargo.lock From 8d30ec3f8111b790c7f4c3d28307d91182500cff Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Wed, 10 Jan 2024 22:10:13 -0800 Subject: [PATCH 10/18] Make MacOS happy(?) --- bindings/cpp/CMakeLists.txt | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/bindings/cpp/CMakeLists.txt b/bindings/cpp/CMakeLists.txt index 024113b..3225720 100644 --- a/bindings/cpp/CMakeLists.txt +++ b/bindings/cpp/CMakeLists.txt @@ -17,31 +17,32 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # Do the build # -------------------------------------------------------------------------------- set(CHECKS_HEADERS -${PROJECT_SOURCE_DIR}/include/cppchecks/check.h -${PROJECT_SOURCE_DIR}/include/cppchecks/item.h -${PROJECT_SOURCE_DIR}/include/cppchecks/items.h -${PROJECT_SOURCE_DIR}/include/cppchecks/result.h -${PROJECT_SOURCE_DIR}/include/cppchecks/runner.h -${PROJECT_SOURCE_DIR}/include/cppchecks/status.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/check.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/core.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/item.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/items.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/result.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/runner.h + ${PROJECT_SOURCE_DIR}/include/cppchecks/status.h ) +include_directories(${PROJECT_SOURCE_DIR}/include) + add_library(${CMAKE_PROJECT_NAME} -${CHECKS_HEADERS} + ${CHECKS_HEADERS} ) set(CCHECKS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../c) add_subdirectory(${PROJECT_SOURCE_DIR}/../c ${CMAKE_BINARY_DIR}/cchecks) target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC -${PROJECT_SOURCE_DIR}/include -${PROJECT_SOURCE_DIR}/../c/include + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/../c/include ) set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) target_link_libraries(${CMAKE_PROJECT_NAME} cchecks) -# add_subdirectory(src) - if (BUILD_CPPCHECKS_TESTS) enable_testing() add_subdirectory(googletest) From e2678630a0737c33476d00d2b970f17203e73ba5 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Wed, 10 Jan 2024 23:02:00 -0800 Subject: [PATCH 11/18] More fixes, possibly making MacOS happy --- .github/workflows/codeql_cpp.yml | 2 +- .github/workflows/test_suite_cpp.yml | 2 +- bindings/cpp/CMakeLists.txt | 11 ++++++++--- bindings/cpp/src/core.cpp | 10 ++++++++++ 4 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 bindings/cpp/src/core.cpp diff --git a/.github/workflows/codeql_cpp.yml b/.github/workflows/codeql_cpp.yml index e36ba4b..b646fd5 100644 --- a/.github/workflows/codeql_cpp.yml +++ b/.github/workflows/codeql_cpp.yml @@ -60,7 +60,7 @@ jobs: with: languages: cpp - # Build C Project + # Build C++ Project - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: Make Build Directory diff --git a/.github/workflows/test_suite_cpp.yml b/.github/workflows/test_suite_cpp.yml index eeb4bc3..a013d03 100644 --- a/.github/workflows/test_suite_cpp.yml +++ b/.github/workflows/test_suite_cpp.yml @@ -1,4 +1,4 @@ -name: C Test Suite +name: C++ Test Suite on: push: diff --git a/bindings/cpp/CMakeLists.txt b/bindings/cpp/CMakeLists.txt index 3225720..2846ff1 100644 --- a/bindings/cpp/CMakeLists.txt +++ b/bindings/cpp/CMakeLists.txt @@ -25,11 +25,13 @@ set(CHECKS_HEADERS ${PROJECT_SOURCE_DIR}/include/cppchecks/runner.h ${PROJECT_SOURCE_DIR}/include/cppchecks/status.h ) - -include_directories(${PROJECT_SOURCE_DIR}/include) +set(CHECKS_SRC + ${PROJECT_SOURCE_DIR}/src/core.cpp +) add_library(${CMAKE_PROJECT_NAME} ${CHECKS_HEADERS} + ${CHECKS_SRC} ) set(CCHECKS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../c) @@ -43,9 +45,12 @@ target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) target_link_libraries(${CMAKE_PROJECT_NAME} cchecks) +install(FILES ${CHECKS_HEADERS} DESTINATION include/cppchecks) +install(TARGETS ${CMAKE_PROJECT_NAME} EXPORT cppchecks DESTINATION lib) + if (BUILD_CPPCHECKS_TESTS) enable_testing() - add_subdirectory(googletest) + add_subdirectory(googletest EXCLUDE_FROM_ALL) # For Windows: Prevent overriding the parent project's compiler/linker settings set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) add_subdirectory(tests) diff --git a/bindings/cpp/src/core.cpp b/bindings/cpp/src/core.cpp new file mode 100644 index 0000000..758f84a --- /dev/null +++ b/bindings/cpp/src/core.cpp @@ -0,0 +1,10 @@ +extern "C" +{ +#include +} + +#include "cppchecks/check.h" +#include "cppchecks/core.h" +#include "cppchecks/item.h" +#include "cppchecks/items.h" +#include "cppchecks/status.h" From 028cff83912d1b1d3bfa1056377993f5cc9e2ef9 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Fri, 12 Jan 2024 20:37:16 -0800 Subject: [PATCH 12/18] Address some bugs with the check result --- bindings/cpp/include/cppchecks/items.h | 7 +++++++ bindings/cpp/include/cppchecks/result.h | 22 +++++++--------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/bindings/cpp/include/cppchecks/items.h b/bindings/cpp/include/cppchecks/items.h index 86d253f..c13c626 100644 --- a/bindings/cpp/include/cppchecks/items.h +++ b/bindings/cpp/include/cppchecks/items.h @@ -63,6 +63,13 @@ namespace CPPCHECKS_NAMESPACE Items(const CPPCHECKS_NAMESPACE::Item *items, size_t count) : _items(items), _count(count) {} + const CPPCHECKS_NAMESPACE::Item operator[](size_t index) const + { + return _items[index]; + } + + size_t size() const noexcept { return _count; } + iterator begin() { return Items::iterator(_items); diff --git a/bindings/cpp/include/cppchecks/result.h b/bindings/cpp/include/cppchecks/result.h index 23fbb07..4c2d4a3 100644 --- a/bindings/cpp/include/cppchecks/result.h +++ b/bindings/cpp/include/cppchecks/result.h @@ -26,24 +26,18 @@ namespace CPPCHECKS_NAMESPACE { CChecksStatus cstatus = status.c_status(); const char *cmessage = message.c_str(); - CChecksItem *citems = nullptr; size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = 0; + size_t item_count = items.size(); const char *cerror = error.c_str(); - item_count = items.size(); - _result = cchecks_check_result_new(cstatus, cmessage, (CChecksItem *)_items.data(), item_size, item_count, can_fix, can_skip, cerror, items_destroy_fn); } static CheckResult passed(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) { const char *cmessage = message.c_str(); - CChecksItem *citems = nullptr; size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = 0; - - item_count = items.size(); + size_t item_count = items.size(); CheckResult result; result._items = items; @@ -55,9 +49,8 @@ namespace CPPCHECKS_NAMESPACE static CheckResult skipped(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) { const char *cmessage = message.c_str(); - CChecksItem *citems = nullptr; size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = 0; + size_t item_count = items.size(); if (items) { @@ -74,9 +67,8 @@ namespace CPPCHECKS_NAMESPACE static CheckResult warning(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) { const char *cmessage = message.c_str(); - CChecksItem *citems = nullptr; size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = 0; + size_t item_count = items.size(); if (items) { @@ -93,9 +85,8 @@ namespace CPPCHECKS_NAMESPACE static CheckResult failed(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) { const char *cmessage = message.c_str(); - CChecksItem *citems = nullptr; size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = 0; + size_t item_count = items.size(); if (items) { @@ -130,7 +121,8 @@ namespace CPPCHECKS_NAMESPACE const CChecksItems *citems = cchecks_check_result_items(&_result); const CChecksItem *ptr = citems->ptr; - return CPPCHECKS_NAMESPACE::Items((const CPPCHECKS_NAMESPACE::Item *)ptr, citems->length); + auto items = CPPCHECKS_NAMESPACE::Items((const CPPCHECKS_NAMESPACE::Item *)ptr, citems->length); + return items; } bool can_fix() const From 9fa776833f0cf603269ed3ba652b756a0ad01a27 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Fri, 12 Jan 2024 21:48:00 -0800 Subject: [PATCH 13/18] Make Windows happy --- bindings/cpp/include/cppchecks/result.h | 55 +------------- bindings/cpp/tests/test_result.cpp | 99 ++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 54 deletions(-) diff --git a/bindings/cpp/include/cppchecks/result.h b/bindings/cpp/include/cppchecks/result.h index 4c2d4a3..ca8a98f 100644 --- a/bindings/cpp/include/cppchecks/result.h +++ b/bindings/cpp/include/cppchecks/result.h @@ -35,69 +35,22 @@ namespace CPPCHECKS_NAMESPACE static CheckResult passed(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) { - const char *cmessage = message.c_str(); - size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = items.size(); - - CheckResult result; - result._items = items; - result._result = cchecks_check_result_passed(cmessage, (CChecksItem *)result._items.data(), item_size, item_count, can_fix, can_skip, items_destroy_fn); - - return result; + return CheckResult{CPPCHECKS_NAMESPACE::Status::Passed, message, items, can_fix, can_skip, ""}; } static CheckResult skipped(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) { - const char *cmessage = message.c_str(); - size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = items.size(); - - if (items) - { - item_count = items.value().size(); - } - - CheckResult result; - result._items = items; - result._result = cchecks_check_result_skipped(cmessage, (CChecksItem *)result._items.data(), item_size, item_count, can_fix, can_skip, items_destroy_fn); - - return result; + return CheckResult{CPPCHECKS_NAMESPACE::Status::Skipped, message, items, can_fix, can_skip, ""}; } static CheckResult warning(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) { - const char *cmessage = message.c_str(); - size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = items.size(); - - if (items) - { - item_count = items.value().size(); - } - - CheckResult result; - result._items = items; - result._result = cchecks_check_result_warning(cmessage, (CChecksItem *)result._items.data(), item_size, item_count, can_fix, can_skip, items_destroy_fn); - - return result; + return CheckResult{CPPCHECKS_NAMESPACE::Status::Warning, message, items, can_fix, can_skip, ""}; } static CheckResult failed(const std::string &message, const std::vector> &items, bool can_fix, bool can_skip) { - const char *cmessage = message.c_str(); - size_t item_size = sizeof(CPPCHECKS_NAMESPACE::Item); - size_t item_count = items.size(); - - if (items) - { - item_count = items.value().size(); - } - - CheckResult result; - result._items = items; - result._result = cchecks_check_result_failed(cmessage, (CChecksItem *)result._items.data(), item_size, item_count, can_fix, can_skip, items_destroy_fn); - - return result; + return CheckResult{CPPCHECKS_NAMESPACE::Status::Failed, message, items, can_fix, can_skip, ""}; } virtual ~CheckResult() diff --git a/bindings/cpp/tests/test_result.cpp b/bindings/cpp/tests/test_result.cpp index e4298de..7269ecf 100644 --- a/bindings/cpp/tests/test_result.cpp +++ b/bindings/cpp/tests/test_result.cpp @@ -81,11 +81,11 @@ INSTANTIATE_TEST_SUITE_P( ); // clang-format on -class StaticResultParameterizedTestFixture : public ::testing::TestWithParam, bool, bool>> +class PassedResultParameterizedTestFixture : public ::testing::TestWithParam, bool, bool>> { }; -TEST_P(StaticResultParameterizedTestFixture, ResultPassedSuccess) +TEST_P(PassedResultParameterizedTestFixture, ResultPassedSuccess) { CPPCHECKS_NAMESPACE::Status status = CPPCHECKS_NAMESPACE::Status::Passed; std::string message = std::get<0>(GetParam()); @@ -102,7 +102,100 @@ TEST_P(StaticResultParameterizedTestFixture, ResultPassedSuccess) // clang-format off INSTANTIATE_TEST_SUITE_P( CheckResult, - StaticResultParameterizedTestFixture, + PassedResultParameterizedTestFixture, + ::testing::Combine( + ::testing::Values(std::string("message")), + ::testing::Values(std::vector{IntItem(0, ""), IntItem(1, ""), IntItem(2, "")}), + ::testing::Bool(), + ::testing::Bool() + ) +); +// clang-format on + +class SkippedResultParameterizedTestFixture : public ::testing::TestWithParam, bool, bool>> +{ +}; + +TEST_P(SkippedResultParameterizedTestFixture, ResultSkippedSuccess) +{ + CPPCHECKS_NAMESPACE::Status status = CPPCHECKS_NAMESPACE::Status::Skipped; + std::string message = std::get<0>(GetParam()); + std::vector items = std::get<1>(GetParam()); + bool can_fix = std::get<2>(GetParam()); + bool can_skip = std::get<3>(GetParam()); + std::string error = ""; + + IntResult result = IntResult::skipped(message, items, can_fix, can_skip); + + validate_result(result, status, message, items, can_fix, can_skip, error); +} + +// clang-format off +INSTANTIATE_TEST_SUITE_P( + CheckResult, + SkippedResultParameterizedTestFixture, + ::testing::Combine( + ::testing::Values(std::string("message")), + ::testing::Values(std::vector{IntItem(0, ""), IntItem(1, ""), IntItem(2, "")}), + ::testing::Bool(), + ::testing::Bool() + ) +); +// clang-format on + +class WarningResultParameterizedTestFixture : public ::testing::TestWithParam, bool, bool>> +{ +}; + +TEST_P(WarningResultParameterizedTestFixture, ResultWarningSuccess) +{ + CPPCHECKS_NAMESPACE::Status status = CPPCHECKS_NAMESPACE::Status::Warning; + std::string message = std::get<0>(GetParam()); + std::vector items = std::get<1>(GetParam()); + bool can_fix = std::get<2>(GetParam()); + bool can_skip = std::get<3>(GetParam()); + std::string error = ""; + + IntResult result = IntResult::warning(message, items, can_fix, can_skip); + + validate_result(result, status, message, items, can_fix, can_skip, error); +} + +// clang-format off +INSTANTIATE_TEST_SUITE_P( + CheckResult, + WarningResultParameterizedTestFixture, + ::testing::Combine( + ::testing::Values(std::string("message")), + ::testing::Values(std::vector{IntItem(0, ""), IntItem(1, ""), IntItem(2, "")}), + ::testing::Bool(), + ::testing::Bool() + ) +); +// clang-format on + +class FailedResultParameterizedTestFixture : public ::testing::TestWithParam, bool, bool>> +{ +}; + +TEST_P(FailedResultParameterizedTestFixture, ResultFailedSuccess) +{ + CPPCHECKS_NAMESPACE::Status status = CPPCHECKS_NAMESPACE::Status::Failed; + std::string message = std::get<0>(GetParam()); + std::vector items = std::get<1>(GetParam()); + bool can_fix = std::get<2>(GetParam()); + bool can_skip = std::get<3>(GetParam()); + std::string error = ""; + + IntResult result = IntResult::failed(message, items, can_fix, can_skip); + + validate_result(result, status, message, items, can_fix, can_skip, error); +} + +// clang-format off +INSTANTIATE_TEST_SUITE_P( + CheckResult, + FailedResultParameterizedTestFixture, ::testing::Combine( ::testing::Values(std::string("message")), ::testing::Values(std::vector{IntItem(0, ""), IntItem(1, ""), IntItem(2, "")}), From 7a6c28ef289e448ab1bb10d7a975b6d02339678a Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Fri, 12 Jan 2024 21:55:47 -0800 Subject: [PATCH 14/18] CI fix --- .github/workflows/test_suite_cpp.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_suite_cpp.yml b/.github/workflows/test_suite_cpp.yml index a013d03..32b020f 100644 --- a/.github/workflows/test_suite_cpp.yml +++ b/.github/workflows/test_suite_cpp.yml @@ -61,6 +61,7 @@ jobs: working-directory: bindings/cpp/build if: ${{ matrix.os == 'ubuntu-latest' }} run: | + sudo apt update sudo apt install -y valgrind valgrind -v --leak-check=full --show-leak-kinds=all tests/test_check valgrind -v --leak-check=full --show-leak-kinds=all tests/test_item From 33803147d64ede0a6cafde7b06d836fbc638e6bb Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Fri, 12 Jan 2024 22:06:42 -0800 Subject: [PATCH 15/18] More CI fixes --- .github/workflows/test_suite_c.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_suite_c.yml b/.github/workflows/test_suite_c.yml index c74f0c5..f79af68 100644 --- a/.github/workflows/test_suite_c.yml +++ b/.github/workflows/test_suite_c.yml @@ -61,6 +61,7 @@ jobs: working-directory: bindings/c/build if: ${{ matrix.os == 'ubuntu-latest' }} run: | + sudo apt update sudo apt install -y valgrind valgrind -v --leak-check=full --show-leak-kinds=all tests/test_check valgrind -v --leak-check=full --show-leak-kinds=all tests/test_item From ef37b871a73663fb5b0089c16a063d371058ce05 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Fri, 12 Jan 2024 23:33:47 -0800 Subject: [PATCH 16/18] Add coverage to C++ --- .github/workflows/test_suite_c.yml | 1 - .github/workflows/test_suite_cpp.yml | 5 ----- bindings/c/tests/CMakeLists.txt | 4 ++++ bindings/cpp/tests/CMakeLists.txt | 4 ++++ 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test_suite_c.yml b/.github/workflows/test_suite_c.yml index f79af68..fd14845 100644 --- a/.github/workflows/test_suite_c.yml +++ b/.github/workflows/test_suite_c.yml @@ -70,5 +70,4 @@ jobs: valgrind -v --leak-check=full --show-leak-kinds=all tests/test_status - uses: codecov/codecov-action@v3 with: - files: lcov.info flags: lang-c diff --git a/.github/workflows/test_suite_cpp.yml b/.github/workflows/test_suite_cpp.yml index 32b020f..7e6c2fe 100644 --- a/.github/workflows/test_suite_cpp.yml +++ b/.github/workflows/test_suite_cpp.yml @@ -39,10 +39,6 @@ jobs: submodules: recursive - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - - name: Install cargo-llvm-cov - uses: taiki-e/install-action@cargo-llvm-cov - - run: cargo clippy - - run: cargo llvm-cov --all-features --lcov --output-path lcov.info - name: Make Build Directory run: mkdir -p build - name: CMake Configure @@ -70,5 +66,4 @@ jobs: valgrind -v --leak-check=full --show-leak-kinds=all tests/test_status - uses: codecov/codecov-action@v3 with: - files: lcov.info flags: lang-cpp diff --git a/bindings/c/tests/CMakeLists.txt b/bindings/c/tests/CMakeLists.txt index 5571644..71d0667 100644 --- a/bindings/c/tests/CMakeLists.txt +++ b/bindings/c/tests/CMakeLists.txt @@ -6,6 +6,10 @@ set(TESTS test_status ) +SET(CMAKE_CXX_FLAGS "-g -O0 -Wall -fprofile-arcs -ftest-coverage") +SET(CMAKE_C_FLAGS "-g -O0 -Wall -W -fprofile-arcs -ftest-coverage") +SET(CMAKE_EXE_LINKER_FLAGS "-fprofile-arcs -ftest-coverage") + if(CODE_COVERAGE AND CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") # Don't use e.g. GNU extension (like -std=gnu++11) for portability set(CMAKE_C_EXTENSIONS OFF) diff --git a/bindings/cpp/tests/CMakeLists.txt b/bindings/cpp/tests/CMakeLists.txt index 091e182..8926f27 100644 --- a/bindings/cpp/tests/CMakeLists.txt +++ b/bindings/cpp/tests/CMakeLists.txt @@ -10,6 +10,10 @@ set(TEST_HEADERS item_impl.h ) +SET(CMAKE_CXX_FLAGS "-g -O0 -Wall -fprofile-arcs -ftest-coverage") +SET(CMAKE_C_FLAGS "-g -O0 -Wall -W -fprofile-arcs -ftest-coverage") +SET(CMAKE_EXE_LINKER_FLAGS "-fprofile-arcs -ftest-coverage") + foreach(TEST ${TESTS}) add_executable(${TEST} ${TEST}.cpp ${TEST_HEADERS} From 56e42dc50c9f26a5eb17b252449549158388fdd5 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Fri, 12 Jan 2024 23:43:25 -0800 Subject: [PATCH 17/18] More coverage updates --- .github/workflows/test_suite_c.yml | 7 +++++++ .github/workflows/test_suite_cpp.yml | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/.github/workflows/test_suite_c.yml b/.github/workflows/test_suite_c.yml index fd14845..99076cb 100644 --- a/.github/workflows/test_suite_c.yml +++ b/.github/workflows/test_suite_c.yml @@ -68,6 +68,13 @@ jobs: valgrind -v --leak-check=full --show-leak-kinds=all tests/test_result valgrind -v --leak-check=full --show-leak-kinds=all tests/test_runner valgrind -v --leak-check=full --show-leak-kinds=all tests/test_status + - name: Run LCov + working-directory: bindings/cpp/build + run: | + sudo apt update + sudo apt install -y lcov + lcov -c -d . -o coverage.info - uses: codecov/codecov-action@v3 with: flags: lang-c + files: build/coverage.info diff --git a/.github/workflows/test_suite_cpp.yml b/.github/workflows/test_suite_cpp.yml index 7e6c2fe..77a30ff 100644 --- a/.github/workflows/test_suite_cpp.yml +++ b/.github/workflows/test_suite_cpp.yml @@ -64,6 +64,13 @@ jobs: valgrind -v --leak-check=full --show-leak-kinds=all tests/test_result valgrind -v --leak-check=full --show-leak-kinds=all tests/test_runner valgrind -v --leak-check=full --show-leak-kinds=all tests/test_status + - name: Run LCov + working-directory: bindings/cpp/build + run: | + sudo apt update + sudo apt install -y lcov + lcov -c -d . -o coverage.info - uses: codecov/codecov-action@v3 with: flags: lang-cpp + files: build/coverage.info From 0c9a4414a0220f165d3239aacb9a0bec16e2bb57 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Fri, 12 Jan 2024 23:46:18 -0800 Subject: [PATCH 18/18] More fixes --- .github/workflows/test_suite_c.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_suite_c.yml b/.github/workflows/test_suite_c.yml index 99076cb..84f0c1b 100644 --- a/.github/workflows/test_suite_c.yml +++ b/.github/workflows/test_suite_c.yml @@ -69,7 +69,7 @@ jobs: valgrind -v --leak-check=full --show-leak-kinds=all tests/test_runner valgrind -v --leak-check=full --show-leak-kinds=all tests/test_status - name: Run LCov - working-directory: bindings/cpp/build + working-directory: bindings/c/build run: | sudo apt update sudo apt install -y lcov