diff --git a/src/utils/checkpointing/Checkpoint.cpp b/src/utils/checkpointing/Checkpoint.cpp index ffd8c1c4649a521f2d0ca247c9a44d9cbd3c4297..61d850ea091ed41b1e5b9afed6fb3a7fb3415c4b 100644 --- a/src/utils/checkpointing/Checkpoint.cpp +++ b/src/utils/checkpointing/Checkpoint.cpp @@ -32,6 +32,7 @@ void checkpoint() { try { + HighFive::SilenceHDF5 m_silence_hdf5{true}; auto create_props = HighFive::FileCreateProps{}; create_props.add(HighFive::FileSpaceStrategy(H5F_FSPACE_STRATEGY_FSM_AGGR, true, 0)); diff --git a/src/utils/checkpointing/PrintScriptFrom.cpp b/src/utils/checkpointing/PrintScriptFrom.cpp index 9e324d1132cbe25989d89b61325df28b1bad2735..41c80c1b767945db0ade360d84bce4fbee8d62bf 100644 --- a/src/utils/checkpointing/PrintScriptFrom.cpp +++ b/src/utils/checkpointing/PrintScriptFrom.cpp @@ -11,9 +11,10 @@ #include <utils/HighFivePugsUtils.hpp> void -printScriptFrom(const std::string& filename, const uint64_t& checkpoint_number) +printScriptFrom(const std::string& filename, const uint64_t& checkpoint_number, std::ostream& os) { try { + HighFive::SilenceHDF5 m_silence_hdf5{true}; HighFive::File file(filename, HighFive::File::ReadWrite); const std::string checkpoint_name = "checkpoint_" + std::to_string(checkpoint_number); @@ -25,7 +26,7 @@ printScriptFrom(const std::string& filename, const uint64_t& checkpoint_number) } HighFive::Group checkpoint = file.getGroup(checkpoint_name); - std::cout << checkpoint.getAttribute("data.pgs").read<std::string>(); + os << checkpoint.getAttribute("data.pgs").read<std::string>(); } catch (HighFive::Exception& e) { throw NormalError(e.what()); @@ -35,7 +36,7 @@ printScriptFrom(const std::string& filename, const uint64_t& checkpoint_number) #else // PUGS_HAS_HDF5 void -printScriptFrom(const std::string&, const uint64_t&) +printScriptFrom(const std::string&, const uint64_t&, std::ostream&) { std::cerr << rang::fgB::red << "error: " << rang::fg::reset << "printing checkpoint's script requires HDF5\n"; } diff --git a/src/utils/checkpointing/PrintScriptFrom.hpp b/src/utils/checkpointing/PrintScriptFrom.hpp index c3807c7af000280698406050ffa3320effb05eb6..416a0c76dc5126e19699d22bba5926050f9bbb33 100644 --- a/src/utils/checkpointing/PrintScriptFrom.hpp +++ b/src/utils/checkpointing/PrintScriptFrom.hpp @@ -2,8 +2,9 @@ #define PRINT_SCRIPT_FROM_HPP #include <cstdint> +#include <iostream> #include <string> -void printScriptFrom(const std::string& filename, const uint64_t& checkpoint_number); +void printScriptFrom(const std::string& filename, const uint64_t& checkpoint_number, std::ostream& os = std::cout); #endif // PRINT_SCRIPT_FROM_HPP diff --git a/src/utils/checkpointing/Resume.cpp b/src/utils/checkpointing/Resume.cpp index dbb539771547fc485cbb3642a9a3b24216fd907c..184011049c31febd92f53439bf1389b49fbbd6f2 100644 --- a/src/utils/checkpointing/Resume.cpp +++ b/src/utils/checkpointing/Resume.cpp @@ -25,6 +25,7 @@ void resume() { try { + HighFive::SilenceHDF5 m_silence_hdf5{true}; checkpointing::ResumingData::create(); HighFive::File file(ResumingManager::getInstance().filename(), HighFive::File::ReadOnly); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e7fdbcaf69e289aefc77edd687a1e1696ddd210e..cc7c59a0cbfd31f4a977f71983dbdf2e0a7e31ce 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -158,6 +158,7 @@ add_executable (unit_tests ) set(checkpointing_TESTS + test_checkpointing_PrintScriptFrom.cpp test_checkpointing_ResumingUtils.cpp ) @@ -167,21 +168,21 @@ if(PUGS_HAS_HDF5) test_checkpointing_Connectivity.cpp test_checkpointing_DiscreteFunctionVariant.cpp test_checkpointing_HFTypes.cpp - test_checkpointing_ItemArray.cpp - test_checkpointing_ItemArrayVariant.cpp - test_checkpointing_ItemValue.cpp - test_checkpointing_ItemValueVariant.cpp - test_checkpointing_OStream.cpp test_checkpointing_IBoundaryDescriptor.cpp test_checkpointing_IBoundaryConditionDescriptor.cpp test_checkpointing_IQuadratureDescriptor.cpp test_checkpointing_IDiscreteFunctionDescriptor.cpp test_checkpointing_IInterfaceDescriptor.cpp test_checkpointing_INamedDiscreteData.cpp + test_checkpointing_ItemArray.cpp + test_checkpointing_ItemArrayVariant.cpp test_checkpointing_ItemType.cpp + test_checkpointing_ItemValue.cpp + test_checkpointing_ItemValueVariant.cpp test_checkpointing_IWriter.cpp test_checkpointing_IZoneDescriptor.cpp test_checkpointing_Mesh.cpp + test_checkpointing_OStream.cpp test_checkpointing_SubItemArrayPerItemVariant.cpp test_checkpointing_SubItemValuePerItemVariant.cpp test_checkpointing_Table.cpp diff --git a/tests/test_checkpointing_PrintScriptFrom.cpp b/tests/test_checkpointing_PrintScriptFrom.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64e9d9fffcd985d9e5841c8210d32af31c28edb7 --- /dev/null +++ b/tests/test_checkpointing_PrintScriptFrom.cpp @@ -0,0 +1,109 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <utils/HighFivePugsUtils.hpp> +#include <utils/Messenger.hpp> +#include <utils/checkpointing/PrintScriptFrom.hpp> + +#include <filesystem> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("PrintScriptFrom", "[utils/checkpointing]") +{ +#ifdef PUGS_HAS_HDF5 + + std::string tmp_dirname; + { + { + if (parallel::rank() == 0) { + tmp_dirname = [&]() -> std::string { + std::string temp_filename = std::filesystem::temp_directory_path() / "pugs_checkpointing_XXXXXX"; + return std::string{mkdtemp(&temp_filename[0])}; + }(); + } + parallel::broadcast(tmp_dirname, 0); + } + std::filesystem::path path = tmp_dirname; + const std::string filename = path / "checkpoint.h5"; + + const std::string data_file0 = R"(Un tiens vaut mieux que deux tu l'auras, +Un tiens vaut mieux que deux tu l'auras,...)"; + const std::string data_file1 = R"(All work and no play makes Jack a dull boy, +All work and no play makes Jack a dull boy,...)"; + const std::string data_file2 = R"(solo trabajo y nada de juego hacen de Jack un chico aburrido, +solo trabajo y nada de juego hacen de Jack un chico aburrido,...)"; + + { + HighFive::FileAccessProps fapl; + fapl.add(HighFive::MPIOFileAccess{MPI_COMM_WORLD, MPI_INFO_NULL}); + fapl.add(HighFive::MPIOCollectiveMetadata{}); + HighFive::File file = HighFive::File(filename, HighFive::File::Truncate, fapl); + + file.createGroup("/checkpoint_0").createAttribute("data.pgs", data_file0); + file.createGroup("/checkpoint_1").createAttribute("data.pgs", data_file1); + file.createGroup("/checkpoint_2").createAttribute("data.pgs", data_file2); + } + + { + std::ostringstream os; + printScriptFrom(filename, 0, os); + REQUIRE(os.str() == data_file0); + } + + { + std::ostringstream os; + printScriptFrom(filename, 1, os); + REQUIRE(os.str() == data_file1); + } + + { + std::ostringstream os; + printScriptFrom(filename, 2, os); + REQUIRE(os.str() == data_file2); + } + + { + std::ostringstream error_msg; + error_msg << "error: cannot find checkpoint " << 12 << " in " << filename; + REQUIRE_THROWS_WITH(printScriptFrom(filename, 12), error_msg.str()); + } + + { + const std::string malformed_filename = path / "malformed.h5"; + + { + HighFive::FileAccessProps fapl; + fapl.add(HighFive::MPIOFileAccess{MPI_COMM_WORLD, MPI_INFO_NULL}); + fapl.add(HighFive::MPIOCollectiveMetadata{}); + HighFive::File file = HighFive::File(malformed_filename, HighFive::File::Truncate, fapl); + + file.createGroup("/checkpoint_0"); + } + REQUIRE_THROWS_WITH(printScriptFrom(malformed_filename, 0), + "error: Unable to open the attribute \"data.pgs\": (Attribute) Object not found"); + } + } + + parallel::barrier(); + if (parallel::rank() == 0) { + std::filesystem::remove_all(std::filesystem::path{tmp_dirname}); + } + +#else // PUGS_HAS_HDF5 + + if (parallel::rank() == 0) { + std::cerr.setstate(std::ios::badbit); + } + + std::ostringstream os; + REQUIRE_NOTHROW(printScriptFrom("foo.h5", 0, os)); + + if (parallel::rank() == 0) { + std::cerr.clear(); + } + + REQUIRE(os.str() == ""); + +#endif // PUGS_HAS_HDF5 +}