From a78628a4c2902fea39edefa7c0946c5ca2a15d86 Mon Sep 17 00:00:00 2001 From: Matthew Falcone Date: Thu, 25 Jun 2026 14:52:04 +0100 Subject: [PATCH 1/4] Add tests for internal namespace --- include/util/hippoUtils.h | 35 ++++++++++++++++++-- unit/src/InternalTests.C | 69 +++++++++++++++++++++++++++++++++++++++ unit/src/SampleTest.C | 32 ------------------ 3 files changed, 101 insertions(+), 35 deletions(-) create mode 100644 unit/src/InternalTests.C delete mode 100644 unit/src/SampleTest.C diff --git a/include/util/hippoUtils.h b/include/util/hippoUtils.h index d684bab6..95623622 100644 --- a/include/util/hippoUtils.h +++ b/include/util/hippoUtils.h @@ -1,22 +1,51 @@ #pragma once +#include "MooseError.h" #include +#include namespace Hippo { +namespace +{ +template +std::string +getDemangleName() +{ + const char * mangled = typeid(T).name(); + int status = 0; + std::unique_ptr demangled(abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status)); + + return status == 0 ? demangled.get() : mangled; +} +} + namespace internal { template inline void copyParamFromParam(InputParameters & dst, const InputParameters & src, const std::string & name_in) { - if (src.isParamValid(name_in)) - dst.set(name_in) = src.get(name_in); + if (!src.have_parameter(name_in)) + mooseError("Parameter '", + name_in, + "' of type ", + getDemangleName(), + " not found in src parameters."); + + if (!dst.have_parameter(name_in)) + mooseError("Parameter '", + name_in, + "' of type ", + getDemangleName(), + " not found in dst parameters."); + + dst.set(name_in) = src.get(name_in); } template inline std::string -listFromVector(std::vector vec, StrType sep = ", ") +listFromVector(std::vector vec, const char * sep = ", ") { if (vec.size() == 0) return std::string(); diff --git a/unit/src/InternalTests.C b/unit/src/InternalTests.C new file mode 100644 index 00000000..1f8f3c8f --- /dev/null +++ b/unit/src/InternalTests.C @@ -0,0 +1,69 @@ +#include "gtest/gtest.h" +#include + +#include "InputParameters.h" +#include "hippoUtils.h" + +#define EXPECT_THROW_MSG(statement, msg) \ + try statement catch (const std::exception & e) \ + { \ + const std::string err_msg{std::string(e.what()) + " vs " + msg}; \ + EXPECT_TRUE(std::regex_search(e.what(), std::regex(msg))) << err_msg; \ + } + +InputParameters +setupParameters() +{ + libMesh::Parameters params; + params.insert("param1"); + params.insert("param2"); + + return InputParameters(params); +} + +TEST(HippoTestInternals, copyParamTest) +{ + InputParameters src(setupParameters()); + InputParameters dst(setupParameters()); + + // Add parameters unique to each parameter set + src.addParam("param3", ""); + dst.addParam("param4", ""); + + // Set source parameters + src.set("param1") = 4.2; + src.set("param2") = 2.1; + + // Test copies + Hippo::internal::copyParamFromParam(dst, src, "param1"); + EXPECT_DOUBLE_EQ(dst.get("param1"), 4.2); + Hippo::internal::copyParamFromParam(dst, src, "param2"); + EXPECT_DOUBLE_EQ(dst.get("param2"), 2.1); + + // Check missing parameters results in an excection + EXPECT_THROW_MSG( + { Hippo::internal::copyParamFromParam(dst, src, "param4"); }, + "Parameter 'param4' of type double not found in src parameters."); + EXPECT_THROW_MSG( + { Hippo::internal::copyParamFromParam(dst, src, "param3"); }, + "Parameter 'param3' of type double not found in dst parameters."); + + // Check error through if the type is wrong + EXPECT_THROW_MSG( + { Hippo::internal::copyParamFromParam(dst, src, "param1"); }, + "Parameter 'param1' of type .* not found in src parameters."); +} + +TEST(HippoTestInternals, ListFromVectorTest) +{ + std::vector vec1{"item 1"}; + std::vector vec2{"item 1", "item 2"}; + + // Check lists of different sizes + EXPECT_EQ(Hippo::internal::listFromVector(std::vector()), ""); + EXPECT_EQ(Hippo::internal::listFromVector(vec1), "item 1"); + EXPECT_EQ(Hippo::internal::listFromVector(vec2), "item 1, item 2"); + + // Check separator usage + EXPECT_EQ(Hippo::internal::listFromVector(vec2, " "), "item 1 item 2"); +} diff --git a/unit/src/SampleTest.C b/unit/src/SampleTest.C deleted file mode 100644 index da0782db..00000000 --- a/unit/src/SampleTest.C +++ /dev/null @@ -1,32 +0,0 @@ -//* This file is part of the MOOSE framework -//* https://www.mooseframework.org -//* -//* All rights reserved, see COPYRIGHT for full restrictions -//* https://github.com/idaholab/moose/blob/master/COPYRIGHT -//* -//* Licensed under LGPL 2.1, please see LICENSE for details -//* https://www.gnu.org/licenses/lgpl-2.1.html - -#include "gtest/gtest.h" - -TEST(MySampleTests, descriptiveTestName) -{ - // compare equality - EXPECT_EQ(2, 1 + 1); - EXPECT_DOUBLE_EQ(2 * 3.5, 1.0 * 8 - 1); - - // compare equality and immediately terminate this test if it fails - // ASSERT_EQ(2, 1); - - // this won't run if you uncomment the above test because above assert will fail - ASSERT_NO_THROW(1 + 1); - - // for a complete list of assertions and for more unit testing documentation see: - // https://github.com/google/googletest/blob/master/googletest/docs/Primer.md -} - -TEST(MySampleTests, anotherTest) -{ - EXPECT_LE(1, 2); - // ... -} From 846b85740ef1b7d425800aa9bfd6e54ab63ad20e Mon Sep 17 00:00:00 2001 From: Matthew Falcone Date: Thu, 25 Jun 2026 14:54:16 +0100 Subject: [PATCH 2/4] Add some comments --- unit/src/InternalTests.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unit/src/InternalTests.C b/unit/src/InternalTests.C index 1f8f3c8f..348dbf5f 100644 --- a/unit/src/InternalTests.C +++ b/unit/src/InternalTests.C @@ -36,9 +36,9 @@ TEST(HippoTestInternals, copyParamTest) // Test copies Hippo::internal::copyParamFromParam(dst, src, "param1"); - EXPECT_DOUBLE_EQ(dst.get("param1"), 4.2); + EXPECT_DOUBLE_EQ(dst.get("param1"), 4.2) << "param1 doesn't match expect value"; Hippo::internal::copyParamFromParam(dst, src, "param2"); - EXPECT_DOUBLE_EQ(dst.get("param2"), 2.1); + EXPECT_DOUBLE_EQ(dst.get("param2"), 2.1) << "param2 doesn't match expect value"; // Check missing parameters results in an excection EXPECT_THROW_MSG( From a989733b8339a3fc0ba59c2b83601b77745df5f2 Mon Sep 17 00:00:00 2001 From: Matthew Falcone Date: Thu, 25 Jun 2026 14:58:47 +0100 Subject: [PATCH 3/4] Add unit tests to CI --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 479f7aad..68e0705b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,9 @@ jobs: - name: Test production container run: | apptainer exec --writable-tmpfs hippo-release-${{ github.sha }}.sif bash -c "cd /opt/hippo && ./run_tests" + - name: Run unit tests in container + run: | + apptainer exec --writable-tmpfs hippo-release-${{ github.sha }}.sif bash -c "cd /opt/hippo/unit && make && ./run_tests" - name: Docs shell: bash run: | From e30031c71d36bf0542bcf4df3ce6c1ab36776e70 Mon Sep 17 00:00:00 2001 From: Matthew Falcone Date: Fri, 26 Jun 2026 16:34:33 +0100 Subject: [PATCH 4/4] Fix introduced memory bug and add tests --- include/util/hippoUtils.h | 9 ++++++--- unit/src/InternalTests.C | 12 +++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/util/hippoUtils.h b/include/util/hippoUtils.h index 95623622..05b77ff0 100644 --- a/include/util/hippoUtils.h +++ b/include/util/hippoUtils.h @@ -26,21 +26,24 @@ template inline void copyParamFromParam(InputParameters & dst, const InputParameters & src, const std::string & name_in) { + // Check the parameter is available in both src and dst if (!src.have_parameter(name_in)) mooseError("Parameter '", name_in, "' of type ", getDemangleName(), - " not found in src parameters."); + " not available in src parameters."); if (!dst.have_parameter(name_in)) mooseError("Parameter '", name_in, "' of type ", getDemangleName(), - " not found in dst parameters."); + " not available in dst parameters."); - dst.set(name_in) = src.get(name_in); + // Only set the parameter, if it has been set in src + if (src.isParamSetByUser(name_in)) + dst.set(name_in) = src.get(name_in); } template diff --git a/unit/src/InternalTests.C b/unit/src/InternalTests.C index 348dbf5f..99d58e39 100644 --- a/unit/src/InternalTests.C +++ b/unit/src/InternalTests.C @@ -30,6 +30,12 @@ TEST(HippoTestInternals, copyParamTest) src.addParam("param3", ""); dst.addParam("param4", ""); + Hippo::internal::copyParamFromParam(dst, src, "param1"); + Hippo::internal::copyParamFromParam(dst, src, "param2"); + + EXPECT_FALSE(dst.isParamSetByUser("param1")) << "param1 should not be set if src is not set"; + EXPECT_FALSE(dst.isParamSetByUser("param2")) << "param2 should not be set if src is not set"; + // Set source parameters src.set("param1") = 4.2; src.set("param2") = 2.1; @@ -43,15 +49,15 @@ TEST(HippoTestInternals, copyParamTest) // Check missing parameters results in an excection EXPECT_THROW_MSG( { Hippo::internal::copyParamFromParam(dst, src, "param4"); }, - "Parameter 'param4' of type double not found in src parameters."); + "Parameter 'param4' of type double not available in src parameters."); EXPECT_THROW_MSG( { Hippo::internal::copyParamFromParam(dst, src, "param3"); }, - "Parameter 'param3' of type double not found in dst parameters."); + "Parameter 'param3' of type double not available in dst parameters."); // Check error through if the type is wrong EXPECT_THROW_MSG( { Hippo::internal::copyParamFromParam(dst, src, "param1"); }, - "Parameter 'param1' of type .* not found in src parameters."); + "Parameter 'param1' of type .* not available in src parameters."); } TEST(HippoTestInternals, ListFromVectorTest)