Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
deb6c84
mv GrackleCtxPack out of test_ghost_zone and refactor
mabruzzo Dec 16, 2025
c4495e7
transfer grtest_api_fixture out of test_ghost_zone
mabruzzo Dec 16, 2025
268b9b4
introduce some basic tests of ratequery
mabruzzo Dec 17, 2025
cd7deac
add more ratequery tests
mabruzzo Dec 17, 2025
2425701
tweak the name of the test_ghost_zone tests
mabruzzo Dec 17, 2025
37fad17
factor out machinery for creating adaptor
mabruzzo Dec 18, 2025
39e1c0c
fix a broken header include
mabruzzo Dec 19, 2025
2f42f95
Merge branch 'ncc/factor-out-grtest' into ncc/adjust-api-tests
mabruzzo Jan 13, 2026
952b3db
Merge branch 'ncc/factor-out-grtest' into ncc/adjust-api-tests
mabruzzo Jan 21, 2026
4588646
minor bugfix
mabruzzo Jan 21, 2026
a969544
a few minor tweaks
mabruzzo Jan 21, 2026
21c4d29
Shift definition GrackleCtxPack to its own file
mabruzzo Jan 22, 2026
2da8d07
add wrappers to set chemistry_data params
mabruzzo Jan 22, 2026
774b305
grtestutils: chemistry_data parameter machinery
mabruzzo Jan 22, 2026
1ea8dd8
grtestutils: refactor presets to use ParamVal
mabruzzo Jan 24, 2026
61c7fcf
make it possible to more concisely initialize a vector of key-value p…
mabruzzo Jan 23, 2026
af25b64
rename FullConfPreset->SimpleConfPreset
mabruzzo Jan 23, 2026
151cc5f
grtestutils: introduce Status type
mabruzzo Jan 23, 2026
26139f2
relocate some logic and address compiler warning
mabruzzo Jan 23, 2026
9f248fb
Replace SimpleConfPreset with ParamConf
mabruzzo Jan 25, 2026
9e4c7dd
introduce GRTest_MAKE_CTX_PACK
mabruzzo Jan 25, 2026
f56e7df
minor bugfix
mabruzzo Feb 5, 2026
fa8852c
adjust preset
mabruzzo Feb 2, 2026
12ddbf9
Merge branch 'newchem-cpp' into ncc/adjust-grackle-ctx
mabruzzo Feb 5, 2026
f2e7ec0
another minor bugfix
mabruzzo Feb 5, 2026
db2693d
hopefully this is the last fix
mabruzzo Feb 5, 2026
49fb844
Merge branch 'newchem-cpp' into ncc/adjust-grackle-ctx
mabruzzo Feb 11, 2026
3cc80cf
rearranging files
mabruzzo Feb 13, 2026
4d5fff2
move/adjust string formatting routines
mabruzzo Feb 2, 2026
61beb16
Initial introduction of FieldContainer
mabruzzo Jan 25, 2026
105fa86
introduce fill_field_vals
mabruzzo Jan 29, 2026
cf6be15
refactor GridLayout
mabruzzo Jan 30, 2026
77a8c3f
improve FieldContainer and lightly refactor fill_field_vals
mabruzzo Feb 2, 2026
3b33ec4
refactor test_ghost_zone
mabruzzo Feb 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .clang-format-ignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ tests/grtestutils/utils.cpp
tests/grtestutils/utils.hpp
tests/grtestutils/googletest/check_allclose.hpp
tests/unit/test_chemistry_struct_synced.cpp
tests/unit/test_ghost_zone.cpp
tests/unit/test_interpolators_comparisons.cpp
tests/unit/test_linalg.cpp
tests/unit/test_status_reporting.cpp
Expand Down
16 changes: 16 additions & 0 deletions src/clib/status_reporting.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,22 @@ ERRFMT_ATTR_(2) void grimpl_print_err_msg_(
#define GrPrintErrMsg(...) \
grimpl_print_err_msg_(__GRIMPL_SRCLOC__, __VA_ARGS__);

/// @def GR_INTERNAL_UNREACHABLE_ERROR()
/// @brief function-like macro that aborts with a (lethal) error message
/// indicating that
///
/// This macro should be treated as a function with the signature:
///
/// [[noreturn]] void GR_INTERNAL_UNREACHABLE_ERROR();
///
/// @note
/// Unlike gcc/clang's __builtin_unreachable or C++23's std::unreachable, this
/// aborts the program with an error if its executed (the other cases produce
/// undefined behavior). (An argument could be made for conditionally compiling
/// this macro into the alternatives to test speed)
#define GR_INTERNAL_UNREACHABLE_ERROR() \
{ grimpl_abort_with_internal_err_(__GRIMPL_SRCLOC__, \
"location shouldn't be reachable"); }

// undefine the attributes so we avoid leaking them
// ------------------------------------------------
Expand Down
12 changes: 11 additions & 1 deletion tests/grtestutils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,21 @@ add_library(grtestutils
# files outside of the googletest subdirectory
# -> these shouldn't include headers from the googletest subdirectory
cmd.hpp cmd.cpp
utils.hpp utils.cpp
iterator_adaptor.hpp
os.hpp os.cpp
utils.hpp utils.cpp

harness/grackle_ctx_pack.cpp harness/grackle_ctx_pack.hpp
harness/field_container.cpp harness/field_container.hpp
harness/field_info_detail.cpp harness/field_info_detail.hpp
harness/fill_field_vals.hpp
harness/param.cpp harness/param.hpp
harness/preset.cpp harness/preset.hpp
harness/status.cpp harness/status.hpp

# files in the googletest subdirectory (reminder: should just be headers!)
googletest/check_allclose.hpp
googletest/fixtures.hpp
)

target_link_libraries(grtestutils
Expand Down
69 changes: 15 additions & 54 deletions tests/grtestutils/googletest/check_allclose.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,7 @@
#include <vector>
#include <gtest/gtest.h>

/// equivalent of %g (this is extremely crude!)
std::string pretty_format_(double val) {
char buf[30];
snprintf(buf, 30, "%g", val);
return std::string(buf);
}

/// formats a std::vector as a string
///
/// @note
/// This is highly inefficient, partially because it consists of code written
/// from before we adopted googletest
inline std::string vec_to_string(const std::vector<double>& vec) {
std::string out = "{";

std::size_t len = vec.size();

std::size_t pause_start;
std::size_t pause_stop;

if (len > 30){
pause_start = 3;
pause_stop = len - 3;
} else {
pause_start = len *2;
pause_stop = pause_start;
}

for (std::size_t i = 0; i < len; i++) {
if ((i > pause_start) && (i < pause_stop)) { continue; }

if (i == pause_stop) {
out += ", ... ";
} else if (i != 0) {
out += ", ";
}

const int BUF_SIZE = 30;
char buf[BUF_SIZE];
snprintf(buf, BUF_SIZE, "%g", vec[i]);
out += buf;
}
return out + "}";
}
#include "grtestutils/utils.hpp"

/// this compares 2 std::vectors
///
Expand Down Expand Up @@ -107,24 +64,28 @@ inline testing::AssertionResult check_allclose(

if (num_mismatches == 0) { return testing::AssertionSuccess(); }

std::string actual_vec_str = vec_to_string(actual);
std::string ref_vec_str = vec_to_string(desired);
std::string actual_vec_str = grtest::ptr_to_string(actual.data(),
actual.size());
std::string ref_vec_str = grtest::ptr_to_string(desired.data(),
desired.size());

using grtest::to_pretty_string;

return testing::AssertionFailure()
<< "\narrays are unequal for the tolerance: "
<< "rtol = " << pretty_format_(rtol) << ", "
<< "atol = " << pretty_format_(atol) << '\n'
<< "rtol = " << to_pretty_string(rtol) << ", "
<< "atol = " << to_pretty_string(atol) << '\n'
<< err_msg << '\n' // custom error message
<< "Mismatched elements: " << num_mismatches << " / " << actual.size()
<< '\n'
<< "Max absolute difference: " << pretty_format_(max_absDiff) << ", "
<< "Max absolute difference: " << to_pretty_string(max_absDiff) << ", "
<< "ind = " << max_absDiff_ind << ", "
<< "actual = " << pretty_format_(actual[max_absDiff_ind]) << ", "
<< "reference = " << pretty_format_(desired[max_absDiff_ind]) << '\n'
<< "Max relative difference: " << pretty_format_(max_relDiff) << ", "
<< "actual = " << to_pretty_string(actual[max_absDiff_ind]) << ", "
<< "reference = " << to_pretty_string(desired[max_absDiff_ind]) << '\n'
<< "Max relative difference: " << to_pretty_string(max_relDiff) << ", "
<< "ind = " << max_absDiff_ind << ", "
<< "actual = " << pretty_format_(actual[max_relDiff_ind]) << ", "
<< "desired = " << pretty_format_(desired[max_relDiff_ind]) << '\n'
<< "actual = " << to_pretty_string(actual[max_relDiff_ind]) << ", "
<< "desired = " << to_pretty_string(desired[max_relDiff_ind]) << '\n'
<< "actual: " << actual_vec_str << '\n'
<< "desired: " << ref_vec_str << '\n';
}
Expand Down
156 changes: 156 additions & 0 deletions tests/grtestutils/googletest/fixtures.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
//===----------------------------------------------------------------------===//
//
// See the LICENSE file for license and copyright information
// SPDX-License-Identifier: NCSA AND BSD-3-Clause
//
//===----------------------------------------------------------------------===//
///
/// @file
/// Define machinery for creating GoogleTest Fixtures to help test Grackle's
/// C API.
///
//===----------------------------------------------------------------------===//

#ifndef GRTEST_FIXTURE
#define GRTEST_FIXTURE

#include <gtest/gtest.h>
// because we include gtest.h here, we should NOT include this file in any
// grtest source files (in other words, this should be a header-only file)

#include "../harness/grackle_ctx_pack.hpp"
#include "../harness/preset.hpp"
#include "../harness/status.hpp"

#include <utility> // std::move

// C Pre-Processor weirdness requires an additional level of indirection
// if we want B to be passed __LINE__ and actually expand to a line number
#define GRTest_CONCAT_TOKEN_HELPER_(a, b) a##b
#define GRTest_CONCAT_TOKEN_(a, b) GRTest_CONCAT_TOKEN_HELPER_(a, b)

/// Construct a GrackleCtxPack with googletest error checking
///
/// In more detail, this calls `GrackleCtxPack::create(conf)`, performs
/// associated error-checking and then stores the result in `lhs`. This is
/// roughly analogous to
/// \code{C++}
/// RsltPairT rslt_pair = ::grtest::GrackleCtxPack::create(conf);
/// if (!rslt_pair.second.is_err()) {
/// /* handle the error with Googletest machinery */
/// }
/// lhs = std::move(rslt_pair.first);
/// \endcode
/// In the above pseudocode, 2 simplifications were made:
/// - `RsltPairT` replaced std::pair<::grtest::GrackleCtxPack, ::grtest::Status>
/// - the variable name `rslt_pair` replaces a more unique variable name
///
/// @param[in, out] lhs If construction of the pack succeeds, then this will
/// be on the left hand side of the final assignment expression
/// @param[in] conf Expands to eSimpleConfPreset
///
/// @par Motivation
/// This exists so that one-off test-cases don't need to create a full-blown
/// fixture to check a given configuration (they can use this macro instead)
///
/// @warning
/// Because the error-checking logic may trigger skipping of a test or a test
/// failure, this **MUST** be called within the body of a test-case or in the
/// `SetUp()`/`TearDown()` method of a fixture. In other words, **DO NOT** call
/// this in a helper function. For more context, see:
/// https://google.github.io/googletest/advanced.html#assertion-placement
///
/// @par Broader Thoughts
/// I really don't like this. But, it currently seems like the most pragmatic
/// solution for now...
/// - Part of the issue is that I have ambitions to reuse the GrackleCtxPack
/// for benchmarking and possibly fuzz/property testing and I didn't want to
/// pigeonhole ourselves...
/// - Now that error-handling of `GrackleCtxPack::create` has improved, and we
/// can provide a detailed description as to why construction failed (without
/// writing much extra code), I'm starting to think that we should replace
/// this with a simple function that either returns a fully-constructed
/// GrackleCtxPack or aborts the program
/// - notably, this choice means that this gets rid of test-skipping
/// functionallity.
/// - I think the fact that this solution would abort the program rather than
/// gracefully reporting a problem is probably ok... Since error-reporting
/// is more robust, it would probably be straight-forward to write
/// alternative functions with specialized handling on a case-by-case basis
/// (e.g. for tests that check Grackle's behavior for deliberately invalid
/// configuration options)
/// - I'm inclined to stick with this macro for now, until the better handling
/// approach becomes a little more obvious...
#define GRTest_MAKE_CTX_PACK(lhs, conf) \
/* GRTest_CONCAT_TOK(rslt, __LINE__) is the temporary variable's name */ \
std::pair<::grtest::GrackleCtxPack, ::grtest::Status> GRTest_CONCAT_TOKEN_( \
rslt, __LINE__) = ::grtest::GrackleCtxPack::create(conf); \
\
/* Check whether construction succeeded */ \
if (GRTest_CONCAT_TOKEN_(rslt, __LINE__).second.is_missing_std_file()) { \
GTEST_SKIP() << GRTest_CONCAT_TOKEN_(rslt, __LINE__).second.to_string(); \
} else if (GRTest_CONCAT_TOKEN_(rslt, __LINE__).second.is_err()) { \
FAIL() << GRTest_CONCAT_TOKEN_(rslt, __LINE__).second.to_string() \
<< " occurred for:\n" \
<< conf.stringify(false, " "); \
} \
\
/* store the result in lhs */ \
lhs = std::move(GRTest_CONCAT_TOKEN_(rslt, __LINE__).first)

namespace grtest {

/// test-fixture that can used to run one or more tests with a chemistry data
/// configuration initialized from a given chemistry presets.
///
/// This sets up a GrackleCtxPack (where the contents are configured with
/// appropriate presets) and deallocates that memory at the end of the test.
///
/// How To Use
/// ==========
/// To make use of this fixture in a test-suite called `MyFeatureTest`, you
/// need to either:
/// 1. make a type alias (via `using` or `typedef`), named `MyFeatureTest`, of
/// the relevant instantiation of this class template, OR
/// 2. make a subclass, named `MyFeatureTest`, of the relevant instantiation of
/// this class template
template <ChemPreset chem_preset, InitialUnitPreset unit_preset>
class ConfigPresetFixture : public testing::Test {
protected:
void SetUp() override {
// called immediately after the constructor (but before the test-case)
ParamConf conf = ParamConf::SimplePreset(chem_preset, unit_preset);
GRTest_MAKE_CTX_PACK(pack, conf);
}

GrackleCtxPack pack;
};

/// defines a parameterized test-fixture that can be used to run a parametrized
/// set of tests that are initialized with different chemistry data presets.
///
/// This sets up a GrackleCtxPack (where the contents are configured with
/// appropriate presets) and deallocates that memory at the end of the test.
///
/// How To Use
/// ==========
/// To make use of this fixture in a test-suite called `MyFeatureTest`, you
/// need to either:
/// 1. make a type alias (via `using` or `typedef`), named `MyFeatureTest`, of
/// this class, OR
/// 2. make a subclass, named `MyFeatureTest`, of this class
class ParametrizedConfigPresetFixture
: public testing::TestWithParam<ParamConf> {
protected:
void SetUp() override {
// called immediately after the constructor (but before the test-case)
ParamConf conf = GetParam();
GRTest_MAKE_CTX_PACK(pack, conf);
}

GrackleCtxPack pack;
};

} // namespace grtest

#endif // GRTEST_FIXTURE
Loading