From fa91fd02e816acd1b63d3c30c6df692f0a682a54 Mon Sep 17 00:00:00 2001 From: Aaron Fiore Date: Wed, 19 Nov 2025 16:12:28 -0800 Subject: [PATCH 1/3] container: root: factor out internal types to common These types and handlers are too generic to be kept internal only. They can now be used across all root macros, plugins and overall API. --- container/src/root/common/type.hh | 130 ++++++++++++++++++++++++ container/src/root/src/internal/type.hh | 91 +++-------------- 2 files changed, 143 insertions(+), 78 deletions(-) create mode 100644 container/src/root/common/type.hh diff --git a/container/src/root/common/type.hh b/container/src/root/common/type.hh new file mode 100644 index 0000000..a9be988 --- /dev/null +++ b/container/src/root/common/type.hh @@ -0,0 +1,130 @@ +// docker-finance | modern accounting for the power-user +// +// Copyright (C) 2021-2025 Aaron Fiore (Founder, Evergreen Crypto LLC) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! \file +//! \author Aaron Fiore (Founder, Evergreen Crypto LLC) +//! \note File intended to be loaded into ROOT.cern framework / Cling interpreter +//! \since docker-finance 1.1.0 + +#ifndef CONTAINER_SRC_ROOT_COMMON_TYPE_HH_ +#define CONTAINER_SRC_ROOT_COMMON_TYPE_HH_ + +#include +#include + +//! \brief Conditional throw handler +//! \ingroup cpp_type_exceptions +#define THROW_IF(condition, exception, message) \ + if (condition) \ + THROW(exception, message); + +//! \brief Throw handler +//! \ingroup cpp_type_exceptions +#define THROW(exception, message) \ + THROW_IMPL(exception, \ + \n\tFILE = __FILE__ \ + \n\tLINE = __LINE__ \ + \n\tWHAT = message); + +//! \brief Throw handler implementation +//! \warning Should not be called directly, use THROW handlers +//! \ingroup cpp_type_exceptions +#define THROW_IMPL(exception, message) \ + throw exception(THROW_IMPL_EXPAND(message)); + +//! \brief Throw handler implementation (message) +//! \warning Should not be called directly, use THROW handlers +//! \ingroup cpp_type_exceptions +#define THROW_IMPL_EXPAND(message) #message + +//! \namespace dfi +//! \since docker-finance 1.0.0 +namespace dfi +{ +//! \namespace dfi::common +//! \brief Shared common functionality +//! \since docker-finance 1.1.0 +namespace common +{ +//! \namespace dfi::common::type +//! \brief docker-finance defined common types +//! \since docker-finance 1.1.0 +namespace type +{ +//! \brief Base exception class +//! \ingroup cpp_type_exceptions +class Exception : virtual public std::exception +{ + public: + //! \brief Exception type + enum struct kType : uint8_t + { + RuntimeError, + InvalidArgument, + }; + + //! \brief Construct by type with given message + Exception(const kType type, const std::string_view what) + : m_type(type), m_what(what) + { + } + virtual ~Exception() = default; + + Exception(const Exception&) = default; + Exception& operator=(const Exception&) = default; + + Exception(Exception&&) = default; + Exception& operator=(Exception&&) = default; + + public: + //! \return Exeption type + kType type() const noexcept { return m_type; } + + //! \return Exception message + const char* what() const noexcept { return m_what.data(); } + + private: + kType m_type; + std::string_view m_what; +}; + +//! \brief Exception class for runtime errors +//! \ingroup cpp_type_exceptions +struct RuntimeError final : public Exception +{ + explicit RuntimeError(const std::string_view what = {}) + : Exception(Exception::kType::RuntimeError, what) + { + } +}; + +//! \brief Exception class for invalid arguments (logic error) +//! \ingroup cpp_type_exceptions +struct InvalidArgument final : public Exception +{ + explicit InvalidArgument(const std::string_view what = {}) + : Exception(Exception::kType::InvalidArgument, what) + { + } +}; +} // namespace type +} // namespace common +} // namespace dfi + +#endif // CONTAINER_SRC_ROOT_COMMON_TYPE_HH_ + +// # vim: sw=2 sts=2 si ai et diff --git a/container/src/root/src/internal/type.hh b/container/src/root/src/internal/type.hh index abb38d6..7238f34 100644 --- a/container/src/root/src/internal/type.hh +++ b/container/src/root/src/internal/type.hh @@ -30,30 +30,7 @@ #include #include -//! \brief Conditional throw handler -//! \ingroup cpp_type_exceptions -#define THROW_IF(condition, exception, message) \ - if (condition) \ - THROW(exception, message); - -//! \brief Throw handler -//! \ingroup cpp_type_exceptions -#define THROW(exception, message) \ - THROW_IMPL(exception, \ - \n\tFILE = __FILE__ \ - \n\tLINE = __LINE__ \ - \n\tWHAT = message); - -//! \brief Throw handler implementation -//! \warning Should not be called directly, use THROW handlers -//! \ingroup cpp_type_exceptions -#define THROW_IMPL(exception, message) \ - throw exception(THROW_IMPL_EXPAND(message)); - -//! \brief Throw handler implementation (message) -//! \warning Should not be called directly, use THROW handlers -//! \ingroup cpp_type_exceptions -#define THROW_IMPL_EXPAND(message) #message +#include "../../common/type.hh" //! \namespace dfi //! \since docker-finance 1.0.0 @@ -70,62 +47,20 @@ namespace internal //! \todo *_v for all the booleans namespace type { -//! \brief Base exception class -//! \ingroup cpp_type_exceptions -class Exception : virtual public std::exception -{ - public: - //! \brief Exception type - enum struct kType : uint8_t - { - RuntimeError, - InvalidArgument, - }; +//! \deprecated This will be removed in the v2 API; use `dfi::common::type` namespace instead +//! \todo Remove in 2.0.0 +//! \since docker-finance 1.1.0 +using Exception = ::dfi::common::type::Exception; - //! \brief Construct by type with given message - Exception(const kType type, const std::string_view what) - : m_type(type), m_what(what) - { - } - virtual ~Exception() = default; +//! \deprecated This will be removed in the v2 API; use `dfi::common::type` namespace instead +//! \todo Remove in 2.0.0 +//! \since docker-finance 1.1.0 +using RuntimeError = ::dfi::common::type::RuntimeError; - Exception(const Exception&) = default; - Exception& operator=(const Exception&) = default; - - Exception(Exception&&) = default; - Exception& operator=(Exception&&) = default; - - public: - //! \return Exeption type - kType type() const noexcept { return m_type; } - - //! \return Exception message - const char* what() const noexcept { return m_what.data(); } - - private: - kType m_type; - std::string_view m_what; -}; - -//! \brief Exception class for runtime errors -//! \ingroup cpp_type_exceptions -struct RuntimeError final : public Exception -{ - explicit RuntimeError(const std::string_view what = {}) - : Exception(Exception::kType::RuntimeError, what) - { - } -}; - -//! \brief Exception class for invalid arguments (logic error) -//! \ingroup cpp_type_exceptions -struct InvalidArgument final : public Exception -{ - explicit InvalidArgument(const std::string_view what = {}) - : Exception(Exception::kType::InvalidArgument, what) - { - } -}; +//! \deprecated This will be removed in the v2 API; use `dfi::common::type` namespace instead +//! \todo Remove in 2.0.0 +//! \since docker-finance 1.1.0 +using InvalidArgument = ::dfi::common::type::InvalidArgument; //! \ingroup cpp_type_traits template From ca59169116f5fbb49e762ef9b1a9802695fb4f59 Mon Sep 17 00:00:00 2001 From: Aaron Fiore Date: Wed, 19 Nov 2025 16:37:46 -0800 Subject: [PATCH 2/3] container: root: rewrite throw handler, refactor using common types - Refactor using common types that were once internal - Removes ancient macro approaches to C++20 solutions - Changes `Exception` message type to use std::string * std::string_view isn't worthwhile in this context --- container/src/root/common/type.hh | 47 +++--------- container/src/root/common/utility.hh | 71 +++++++++++++++---- container/src/root/macro/web/internal/meta.C | 10 ++- container/src/root/plugin/common/utility.hh | 2 +- container/src/root/src/internal/impl/hash.hh | 6 +- .../src/root/src/internal/impl/random.hh | 9 ++- .../src/root/src/internal/impl/utility.hh | 7 +- container/src/root/src/utility.hh | 5 +- container/src/root/test/common/type.hh | 6 +- container/src/root/test/unit/type.hh | 38 +++++----- container/src/root/test/unit/utility.hh | 54 +++++++------- 11 files changed, 134 insertions(+), 121 deletions(-) diff --git a/container/src/root/common/type.hh b/container/src/root/common/type.hh index a9be988..95650a8 100644 --- a/container/src/root/common/type.hh +++ b/container/src/root/common/type.hh @@ -24,32 +24,7 @@ #define CONTAINER_SRC_ROOT_COMMON_TYPE_HH_ #include -#include - -//! \brief Conditional throw handler -//! \ingroup cpp_type_exceptions -#define THROW_IF(condition, exception, message) \ - if (condition) \ - THROW(exception, message); - -//! \brief Throw handler -//! \ingroup cpp_type_exceptions -#define THROW(exception, message) \ - THROW_IMPL(exception, \ - \n\tFILE = __FILE__ \ - \n\tLINE = __LINE__ \ - \n\tWHAT = message); - -//! \brief Throw handler implementation -//! \warning Should not be called directly, use THROW handlers -//! \ingroup cpp_type_exceptions -#define THROW_IMPL(exception, message) \ - throw exception(THROW_IMPL_EXPAND(message)); - -//! \brief Throw handler implementation (message) -//! \warning Should not be called directly, use THROW handlers -//! \ingroup cpp_type_exceptions -#define THROW_IMPL_EXPAND(message) #message +#include //! \namespace dfi //! \since docker-finance 1.0.0 @@ -70,15 +45,15 @@ namespace type class Exception : virtual public std::exception { public: - //! \brief Exception type + //! \brief Exception type tag enum struct kType : uint8_t { RuntimeError, InvalidArgument, }; - //! \brief Construct by type with given message - Exception(const kType type, const std::string_view what) + //! \brief Construct by type tag with given message + Exception(const kType type, const std::string& what) : m_type(type), m_what(what) { } @@ -91,32 +66,32 @@ class Exception : virtual public std::exception Exception& operator=(Exception&&) = default; public: - //! \return Exeption type + //! \return Exeption type tag kType type() const noexcept { return m_type; } //! \return Exception message - const char* what() const noexcept { return m_what.data(); } + const char* what() const noexcept { return m_what.c_str(); } private: kType m_type; - std::string_view m_what; + std::string m_what; }; -//! \brief Exception class for runtime errors +//! \brief Exception type for runtime errors //! \ingroup cpp_type_exceptions struct RuntimeError final : public Exception { - explicit RuntimeError(const std::string_view what = {}) + explicit RuntimeError(const std::string& what = {}) : Exception(Exception::kType::RuntimeError, what) { } }; -//! \brief Exception class for invalid arguments (logic error) +//! \brief Exception type for invalid arguments (logic error) //! \ingroup cpp_type_exceptions struct InvalidArgument final : public Exception { - explicit InvalidArgument(const std::string_view what = {}) + explicit InvalidArgument(const std::string& what = {}) : Exception(Exception::kType::InvalidArgument, what) { } diff --git a/container/src/root/common/utility.hh b/container/src/root/common/utility.hh index 148146e..f3a385c 100644 --- a/container/src/root/common/utility.hh +++ b/container/src/root/common/utility.hh @@ -30,6 +30,8 @@ #include #include +#include "./type.hh" + //! \namespace dfi //! \since docker-finance 1.0.0 namespace dfi @@ -39,6 +41,51 @@ namespace dfi //! \since docker-finance 1.1.0 namespace common { + +//! \concept Exception +//! \brief Exception type concept for `dfi` exceptions +//! \ingroup cpp_common_impl +//! \since docker-finance 1.1.0 +template +concept Exception = std::derived_from; + +//! \brief Throw exception using `dfi` exception type +//! \param message Message to pass to exception type +//! \param location Source location of exception +//! \ingroup cpp_common_impl +//! \since docker-finance 1.1.0 +template +inline void throw_ex( + const std::string& message = {}, + const std::source_location location = std::source_location::current()) +{ + // TODO(unassigned): when throwing because of heap allocation + std::string msg; + msg += std::string(" \n\tFILE = ") + location.file_name(); + msg += std::string(" \n\tFUNC = ") + location.function_name(); + msg += std::string(" \n\tLINE = ") + location.line(); + msg += std::string(" \n\tWHAT = ") + message; + throw t_exception(msg); +} + +//! \brief Throw exception using `dfi` exception type (but only on condition) +//! \param condition If boolean condition is true, throw +//! \param message Message to pass to exception type +//! \param location Source location of exception +//! \ingroup cpp_common_impl +//! \since docker-finance 1.1.0 +template +inline void throw_ex_if( + const bool condition, + const std::string& message = {}, + const std::source_location location = std::source_location::current()) +{ + if (condition) + { + throw_ex(message, location); + } +} + //! \brief Wrapper to ROOT Cling commands //! \ingroup cpp_common_impl //! \since docker-finance 1.0.0 @@ -69,16 +116,13 @@ class Command static void load(const std::string& path) { std::filesystem::path p(path); - if (!std::filesystem::exists(p)) - { - throw std::runtime_error( - std::string{"'" + path + "' does not exist!"}.c_str()); - } - if (!std::filesystem::is_regular_file(p)) - { - throw std::runtime_error( - std::string{"'" + path + "' is not a regular file!"}.c_str()); - } + + throw_ex_if( + !std::filesystem::exists(p), "'" + path + "' does not exist!"); + + throw_ex_if( + !std::filesystem::is_regular_file(p), + "'" + path + "' is not a regular file!"); std::string cmd{".L " + path}; Command::cmd_handler({cmd}); @@ -101,9 +145,10 @@ class Command std::string get_env(const std::string& var) { const auto* env = gSystem->Getenv(var.c_str()); - if (!env) - throw std::runtime_error( - std::string{var + " is not set or is unavailable"}.c_str()); + + throw_ex_if( + !env, "'" + var + "' is not set or is unavailable"); + return std::string{env}; } diff --git a/container/src/root/macro/web/internal/meta.C b/container/src/root/macro/web/internal/meta.C index 2d1fed8..2e6dfae 100644 --- a/container/src/root/macro/web/internal/meta.C +++ b/container/src/root/macro/web/internal/meta.C @@ -184,7 +184,7 @@ class Meta final //! \param column Existing CSV metadata column static void meta_sample(const std::string& column) { - namespace common = ::dfi::macro::common; + namespace common = ::dfi::common; // Import meta file const std::string path{common::get_env("global_conf_meta")}; @@ -197,14 +197,12 @@ class Meta final available += "\n\t" + col; available += "\n"; - if (!csv->HasColumn(column)) - throw std::runtime_error( - std::string{"\n\nAvailable columns: " + available}.c_str()); + common::throw_ex_if( + !csv->HasColumn(column), "\n\nAvailable columns: " + available); // Aggregate all rows of given column auto count = csv->Count(); - if (!*count) - throw std::runtime_error("Empty CSV"); + common::throw_ex_if(!*count, "Empty CSV"); // Prepare canvas data Meta::CanvasData data; diff --git a/container/src/root/plugin/common/utility.hh b/container/src/root/plugin/common/utility.hh index a124f5d..498933d 100644 --- a/container/src/root/plugin/common/utility.hh +++ b/container/src/root/plugin/common/utility.hh @@ -87,7 +87,7 @@ void load(const std::string& path) } else { - throw std::runtime_error( + ::dfi::common::throw_ex<::dfi::common::type::RuntimeError>( "must be of type 'repo/' or 'custom/'"); } diff --git a/container/src/root/src/internal/impl/hash.hh b/container/src/root/src/internal/impl/hash.hh index a4a99e5..814c6cf 100644 --- a/container/src/root/src/internal/impl/hash.hh +++ b/container/src/root/src/internal/impl/hash.hh @@ -429,10 +429,8 @@ class Hash : public common::HashImpl, public type::Hash //! have any effects." Hash() { - THROW_IF( - ::sodium_init() < 0, - type::RuntimeError, - "sodium_init could not be initialized") + ::dfi::common::throw_ex_if<::dfi::common::type::RuntimeError>( + ::sodium_init() < 0, "sodium_init could not be initialized"); } ~Hash() = default; diff --git a/container/src/root/src/internal/impl/random.hh b/container/src/root/src/internal/impl/random.hh index 837823e..6819f36 100644 --- a/container/src/root/src/internal/impl/random.hh +++ b/container/src/root/src/internal/impl/random.hh @@ -128,7 +128,8 @@ class Random : public common::RandomImpl || std::is_same_v, "Invalid type (only uint16_t or uint32_t supported)"); - THROW_IF(!m_csprng.is_seeded(), type::RuntimeError, "Botan is not seeded") + ::dfi::common::throw_ex_if( + !m_csprng.is_seeded(), "Botan is not seeded"); // WARNING: DO *NOT* set_high_bit to true here! // Otherwise, [0..(~2150*10^6)] WILL NOT BE GENERATED! @@ -222,10 +223,8 @@ class Random : public common::RandomImpl //! have any effects." Random() { - THROW_IF( - ::sodium_init() < 0, - type::RuntimeError, - "sodium_init could not be initialized") + ::dfi::common::throw_ex_if<::dfi::common::type::RuntimeError>( + ::sodium_init() < 0, "sodium_init could not be initialized"); } ~Random() = default; diff --git a/container/src/root/src/internal/impl/utility.hh b/container/src/root/src/internal/impl/utility.hh index 3fd912c..a253fdd 100644 --- a/container/src/root/src/internal/impl/utility.hh +++ b/container/src/root/src/internal/impl/utility.hh @@ -159,8 +159,8 @@ class Tools std::vector random_dist(const t_num min, const t_num max, const uint16_t precision = 8) { - THROW_IF( - min > max, type::InvalidArgument, "minimum is greater than maximum") + ::dfi::common::throw_ex_if<::dfi::common::type::InvalidArgument>( + min > max, "minimum is greater than maximum"); // Get first chunk std::vector chunks; @@ -193,7 +193,8 @@ class Tools std::cout.precision(precision); std::cout << "rounded = " << rounded << '\n' << "max = " << max << std::fixed << std::endl; - THROW(type::RuntimeError, "random distribution not fulfilled") + ::dfi::common::throw_ex<::dfi::common::type::RuntimeError>( + "random distribution not fulfilled"); } return chunks; diff --git a/container/src/root/src/utility.hh b/container/src/root/src/utility.hh index e8a635e..4f6e266 100644 --- a/container/src/root/src/utility.hh +++ b/container/src/root/src/utility.hh @@ -43,6 +43,7 @@ namespace dfi namespace utility { +namespace common = ::dfi::common; namespace type = dfi::internal::type; //! \brief Misc utility tools @@ -86,8 +87,8 @@ class Tools final : protected impl::Tools void print_dist(t_num min, t_num max, const size_t precision = 8) { // Specific to this use-case - THROW_IF( - min < 0 || max < 0, type::InvalidArgument, "no negative values allowed") + common::throw_ex_if( + min < 0 || max < 0, "no negative values allowed"); if (min > max) { diff --git a/container/src/root/test/common/type.hh b/container/src/root/test/common/type.hh index 0a4b3d0..9a6fb24 100644 --- a/container/src/root/test/common/type.hh +++ b/container/src/root/test/common/type.hh @@ -25,7 +25,7 @@ #include -#include +#include #include "../../src/internal/type.hh" @@ -50,8 +50,8 @@ namespace unit struct Exception : public ::testing::Test { protected: - std::string_view what = "better to be caught than thrown"; - using t_type = type::Exception::kType; + std::string what = "better to be caught than thrown"; + using t_type = ::dfi::common::type::Exception::kType; }; } // namespace unit } // namespace tests diff --git a/container/src/root/test/unit/type.hh b/container/src/root/test/unit/type.hh index 414a3f8..15d30aa 100644 --- a/container/src/root/test/unit/type.hh +++ b/container/src/root/test/unit/type.hh @@ -46,6 +46,8 @@ namespace tests namespace unit { +namespace common = ::dfi::common; + // // RuntimeError // @@ -56,11 +58,11 @@ struct RuntimeError : public Exception { }; -TEST_F(RuntimeError, macro_THROW_IF) // cppcheck-suppress syntaxError +TEST_F(RuntimeError, throw_ex_if) // cppcheck-suppress syntaxError { try { - THROW_IF(false, type::RuntimeError, message); + common::throw_ex_if(false, what); } catch (const type::Exception& ex) { @@ -69,16 +71,16 @@ TEST_F(RuntimeError, macro_THROW_IF) // cppcheck-suppress syntaxError } } -TEST_F(RuntimeError, macro_THROW) +TEST_F(RuntimeError, throw_ex) { try { - THROW(type::RuntimeError, message); + common::throw_ex(what); } catch (const type::Exception& ex) { ASSERT_EQ(ex.type(), t_type::RuntimeError); - // NOTE: no case for ex.what() because message is formatted within macro + // NOTE: no case for ex.what() because message is formatted within function } } @@ -108,7 +110,7 @@ TEST_F(RuntimeError, copy_assignment) two = one; ASSERT_EQ(one.type(), two.type()); - ASSERT_EQ(one.what(), two.what()); + ASSERT_STREQ(one.what(), two.what()); } TEST_F(RuntimeError, copy_ctor) @@ -117,7 +119,7 @@ TEST_F(RuntimeError, copy_ctor) type::RuntimeError two(one); ASSERT_EQ(one.type(), two.type()); - ASSERT_EQ(one.what(), two.what()); + ASSERT_STREQ(one.what(), two.what()); } TEST_F(RuntimeError, move_assignment) @@ -128,7 +130,7 @@ TEST_F(RuntimeError, move_assignment) two = std::move(one); ASSERT_EQ(one.type(), two.type()); - ASSERT_EQ(one.what(), two.what()); + ASSERT_STRNE(one.what(), two.what()); } TEST_F(RuntimeError, move_ctor) @@ -137,7 +139,7 @@ TEST_F(RuntimeError, move_ctor) type::RuntimeError two(std::move(one)); ASSERT_EQ(one.type(), two.type()); - ASSERT_EQ(one.what(), two.what()); + ASSERT_STRNE(one.what(), two.what()); } // @@ -150,11 +152,11 @@ struct InvalidArgument : public Exception { }; -TEST_F(InvalidArgument, macro_THROW_IF) // cppcheck-suppress syntaxError +TEST_F(InvalidArgument, throw_ex_if) { try { - THROW_IF(false, type::InvalidArgument, message); + common::throw_ex_if(false, what); } catch (const type::Exception& ex) { @@ -163,16 +165,16 @@ TEST_F(InvalidArgument, macro_THROW_IF) // cppcheck-suppress syntaxError } } -TEST_F(InvalidArgument, macro_THROW) +TEST_F(InvalidArgument, throw_ex) { try { - THROW(type::InvalidArgument, message); + common::throw_ex(what); } catch (const type::Exception& ex) { ASSERT_EQ(ex.type(), t_type::InvalidArgument); - // NOTE: no case for ex.what() because message is formatted within macro + // NOTE: no case for ex.what() because message is formatted within function } } @@ -202,7 +204,7 @@ TEST_F(InvalidArgument, copy_assignment) two = one; ASSERT_EQ(one.type(), two.type()); - ASSERT_EQ(one.what(), two.what()); + ASSERT_STREQ(one.what(), two.what()); } TEST_F(InvalidArgument, copy_ctor) @@ -211,7 +213,7 @@ TEST_F(InvalidArgument, copy_ctor) type::InvalidArgument two(one); ASSERT_EQ(one.type(), two.type()); - ASSERT_EQ(one.what(), two.what()); + ASSERT_STREQ(one.what(), two.what()); } TEST_F(InvalidArgument, move_assignment) @@ -222,7 +224,7 @@ TEST_F(InvalidArgument, move_assignment) two = std::move(one); ASSERT_EQ(one.type(), two.type()); - ASSERT_EQ(one.what(), two.what()); + ASSERT_STRNE(one.what(), two.what()); } TEST_F(InvalidArgument, move_ctor) @@ -231,7 +233,7 @@ TEST_F(InvalidArgument, move_ctor) type::InvalidArgument two(std::move(one)); ASSERT_EQ(one.type(), two.type()); - ASSERT_EQ(one.what(), two.what()); + ASSERT_STRNE(one.what(), two.what()); } } // namespace unit diff --git a/container/src/root/test/unit/utility.hh b/container/src/root/test/unit/utility.hh index e6f2dee..153cc10 100644 --- a/container/src/root/test/unit/utility.hh +++ b/container/src/root/test/unit/utility.hh @@ -60,6 +60,9 @@ namespace tests //! \since docker-finance 1.0.0 namespace unit { + +namespace common = ::dfi::common; + //! \brief Tools utility fixture //! \since docker-finance 1.0.0 struct Tools : public ::testing::Test, public tests::ToolsFixture @@ -296,50 +299,41 @@ struct CommonRawFiles : public ::testing::Test, } catch (...) { - THROW(std::runtime_error, "could not generate path"); + common::throw_ex("could not generate path"); } std::ofstream file_1(path_1), file_2(path_2); - THROW_IF( - !file_1.is_open() || !file_2.is_open(), - std::runtime_error, - "could not create file"); + common::throw_ex_if( + !file_1.is_open() || !file_2.is_open(), "could not create file"); file_1 << "using my_foo = int;\n"; file_1.close(); file_2 << "using my_bar = char;\n"; file_2.close(); - THROW_IF( - file_1.bad() || file_2.bad(), - std::runtime_error, - "could not write to file"); + common::throw_ex_if( + file_1.bad() || file_2.bad(), "could not write to file"); } void TearDown() override { - THROW_IF( - std::remove(path_1.c_str()), - std::runtime_error, - "could not remove file '" + path_1 + "'"); + common::throw_ex_if( + std::remove(path_1.c_str()), "could not remove file '" + path_1 + "'"); - THROW_IF( - std::remove(path_2.c_str()), - std::runtime_error, - "could not remove file '" + path_2 + "'"); + common::throw_ex_if( + std::remove(path_2.c_str()), "could not remove file '" + path_2 + "'"); } }; TEST_F(CommonRawFiles, RawLoadSingle) { ASSERT_THROW( - ::dfi::common::Command::load({path_1 + "should-not-exist"}), - std::runtime_error); + common::Command::load({path_1 + "should-not-exist"}), type::RuntimeError); gInterpreter->ProcessLine("my_foo foo;", ecode.get()); ASSERT_NE(ecode, nullptr); EXPECT_NE(*ecode, EErrorCode::kNoError); - ASSERT_NO_THROW(::dfi::common::Command::load(path_1)); + ASSERT_NO_THROW(common::Command::load(path_1)); gInterpreter->ProcessLine("my_foo foo;", ecode.get()); ASSERT_NE(ecode, nullptr); EXPECT_EQ(*ecode, EErrorCode::kNoError); @@ -348,14 +342,14 @@ TEST_F(CommonRawFiles, RawLoadSingle) TEST_F(CommonRawFiles, RawLoadMultiple) { ASSERT_THROW( - ::dfi::common::Command::load( + common::Command::load( {{path_1 + "should-not-exist"}, {path_2 + "nor-should-this"}}), - std::runtime_error); + type::RuntimeError); gInterpreter->ProcessLine("my_bar bar;", ecode.get()); ASSERT_NE(ecode, nullptr); EXPECT_NE(*ecode, EErrorCode::kNoError); - ASSERT_NO_THROW(::dfi::common::Command::load({path_1, path_2})); + ASSERT_NO_THROW(common::Command::load({path_1, path_2})); gInterpreter->ProcessLine("my_bar bar;", ecode.get()); ASSERT_NE(ecode, nullptr); EXPECT_EQ(*ecode, EErrorCode::kNoError); @@ -373,7 +367,7 @@ struct CommonRepoFiles : public ::testing::Test, TEST_F(CommonRepoFiles, MacroLoad) { ASSERT_THROW( - ::dfi::macro::load("macro/should-not/exist.C"), std::runtime_error); + ::dfi::macro::load("macro/should-not/exist.C"), type::RuntimeError); gInterpreter->ProcessLine( "dfi::macro::common::crypto::botan::Hash h;", ecode.get()); ASSERT_NE(ecode, nullptr); @@ -391,7 +385,7 @@ TEST_F(CommonRepoFiles, MacroLoad) TEST_F(CommonRepoFiles, PluginLoad) { ASSERT_THROW( - ::dfi::plugin::load("repo/should-not/exist.cc"), std::runtime_error); + ::dfi::plugin::load("repo/should-not/exist.cc"), type::RuntimeError); gInterpreter->ProcessLine( "dfi::plugin::my_plugin_namespace::example2();", ecode.get()); ASSERT_NE(ecode, nullptr); @@ -416,19 +410,19 @@ struct CommonFree : public ::testing::Test, public ::dfi::tests::CommonFixture TEST_F(CommonFree, env) { - ASSERT_THROW(::dfi::common::get_env("should-not-exist"), std::runtime_error); - ASSERT_NO_THROW(::dfi::common::get_env("DOCKER_FINANCE_VERSION")); + ASSERT_THROW(common::get_env("should-not-exist"), type::RuntimeError); + ASSERT_NO_THROW(common::get_env("DOCKER_FINANCE_VERSION")); } TEST_F(CommonFree, exec) { - ASSERT_NE(::dfi::common::exec("should-not-exist"), 0); - ASSERT_EQ(::dfi::common::exec("pwd"), 0); + ASSERT_NE(common::exec("should-not-exist"), 0); + ASSERT_EQ(common::exec("pwd"), 0); } TEST_F(CommonFree, make_timestamp) { - ASSERT_EQ(::dfi::common::make_timestamp().size(), 20); + ASSERT_EQ(common::make_timestamp().size(), 20); } } // namespace unit From 9faebb6ceae75d6fa696c98de42282e990ca76e8 Mon Sep 17 00:00:00 2001 From: Aaron Fiore Date: Thu, 20 Nov 2025 11:54:18 -0800 Subject: [PATCH 3/3] container: plugins: root: fix example3()'s usage of throw handler The old macros should *not* have been used in any example; as they were intended for internal use only. This was noted in Doxygen ...by not noting them as publicly consumable. --- container/plugins/root/example.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/container/plugins/root/example.cc b/container/plugins/root/example.cc index c4ed7a1..6d6be48 100644 --- a/container/plugins/root/example.cc +++ b/container/plugins/root/example.cc @@ -108,7 +108,7 @@ void example2() //! \ingroup cpp_plugin_impl void example3() { - namespace common = ::dfi::macro::common; + namespace common = ::dfi::common; const std::string base{ common::get_env("global_basename") + " " @@ -122,10 +122,8 @@ void example3() auto exec_cmd = [&make_cmd](const std::string& cmd) { // shell 0 = success - THROW_IF( - common::exec("bash -i -c '" + make_cmd(cmd) + "'"), - std::runtime_error, - "command failed") + common::throw_ex_if( + common::exec("bash -i -c '" + make_cmd(cmd) + "'"), "command failed"); }; std::cout << "\nImporting journals...\n";