Skip to content
Snippets Groups Projects
Commit 4b651370 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Add tests for PrintCheckpointInfo checkpointing

parent 198e751a
Branches
No related tags found
1 merge request!199Integrate checkpointing
......@@ -14,7 +14,6 @@
#include <algebra/TinyVector.hpp>
#include <iomanip>
#include <iostream>
#include <regex>
#endif // PUGS_HAS_HDF5
......@@ -23,7 +22,7 @@
template <typename T>
void
printAttributeValue(const HighFive::Attribute& attribute)
printAttributeValue(const HighFive::Attribute& attribute, std::ostream& os)
{
std::string delim = "";
......@@ -33,24 +32,25 @@ printAttributeValue(const HighFive::Attribute& attribute)
HighFive::DataSpace data_space = attribute.getSpace();
if (data_space.getNumberDimensions() == 0) {
std::cout << std::boolalpha << delim << attribute.read<T>() << delim;
os << std::boolalpha << delim << attribute.read<T>() << delim;
} else if (data_space.getNumberDimensions() == 1) {
std::vector value = attribute.read<std::vector<T>>();
if (value.size() > 0) {
std::cout << '(' << std::boolalpha << delim << value[0] << delim;
os << '(' << std::boolalpha << delim << value[0] << delim;
for (size_t i = 1; i < value.size(); ++i) {
std::cout << ", " << std::boolalpha << delim << value[i] << delim;
os << ", " << std::boolalpha << delim << value[i] << delim;
}
std::cout << ')';
os << ')';
}
}
}
void
printCheckpointInfo(const std::string& filename)
printCheckpointInfo(const std::string& filename, std::ostream& os)
{
if (parallel::rank() == 0) {
try {
HighFive::SilenceHDF5 m_silence_hdf5{true};
HighFive::File file(filename, HighFive::File::ReadOnly);
std::map<size_t, std::string> checkpoint_name_list;
......@@ -59,11 +59,11 @@ printCheckpointInfo(const std::string& filename)
std::smatch number_string;
const std::regex checkpoint_regex("checkpoint_([0-9]+)");
if (std::regex_match(name, number_string, checkpoint_regex)) {
std::stringstream os;
os << number_string[1].str();
std::stringstream ss;
ss << number_string[1].str();
size_t id = 0;
os >> id;
ss >> id;
checkpoint_name_list[id] = name;
}
......@@ -73,8 +73,8 @@ printCheckpointInfo(const std::string& filename)
HighFive::Group checkpoint = file.getGroup(checkpoint_name);
const std::string creation_date = checkpoint.getAttribute("creation_date").read<std::string>();
std::cout << rang::fgB::yellow << " * " << rang::fg::reset << rang::fgB::magenta << checkpoint_name
<< rang::fg::reset << " [" << rang::fg::green << creation_date << rang::fg::reset << "]\n";
os << rang::fgB::yellow << " * " << rang::fg::reset << rang::fgB::magenta << checkpoint_name << rang::fg::reset
<< " [" << rang::fg::green << creation_date << rang::fg::reset << "]\n";
HighFive::Group saved_symbol_table = checkpoint.getGroup("symbol table");
......@@ -86,21 +86,20 @@ printCheckpointInfo(const std::string& filename)
HighFive::Attribute attribute = saved_symbol_table.getAttribute(symbol_name);
HighFive::DataType data_type = attribute.getDataType();
std::cout << " ";
std::cout << std::setw(25) << std::setfill('.') // << rang::style::bold;
<< std::left << symbol_name + ' ' << std::setfill(' ');
std::cout << ' ';
os << " ";
os << std::setw(25) << std::setfill('.') << std::left << symbol_name + ' ' << std::setfill(' ');
os << ' ';
switch (data_type.getClass()) {
case HighFive::DataTypeClass::Float: {
printAttributeValue<double>(attribute);
printAttributeValue<double>(attribute, os);
break;
}
case HighFive::DataTypeClass::Integer: {
if (data_type == HighFive::AtomicType<uint64_t>()) {
printAttributeValue<uint64_t>(attribute);
printAttributeValue<uint64_t>(attribute, os);
} else if (data_type == HighFive::AtomicType<int64_t>()) {
printAttributeValue<int64_t>(attribute);
printAttributeValue<int64_t>(attribute, os);
}
break;
}
......@@ -108,51 +107,52 @@ printCheckpointInfo(const std::string& filename)
HighFive::DataSpace data_space = attribute.getSpace();
if (data_type == HighFive::AtomicType<TinyVector<1>>()) {
printAttributeValue<TinyVector<1>>(attribute);
printAttributeValue<TinyVector<1>>(attribute, os);
} else if (data_type == HighFive::AtomicType<TinyVector<2>>()) {
printAttributeValue<TinyVector<2>>(attribute);
printAttributeValue<TinyVector<2>>(attribute, os);
} else if (data_type == HighFive::AtomicType<TinyVector<3>>()) {
printAttributeValue<TinyVector<3>>(attribute);
printAttributeValue<TinyVector<3>>(attribute, os);
} else if (data_type == HighFive::AtomicType<TinyMatrix<1>>()) {
printAttributeValue<TinyMatrix<1>>(attribute);
printAttributeValue<TinyMatrix<1>>(attribute, os);
} else if (data_type == HighFive::AtomicType<TinyMatrix<2>>()) {
printAttributeValue<TinyMatrix<2>>(attribute);
printAttributeValue<TinyMatrix<2>>(attribute, os);
} else if (data_type == HighFive::AtomicType<TinyMatrix<3>>()) {
printAttributeValue<TinyMatrix<3>>(attribute);
printAttributeValue<TinyMatrix<3>>(attribute, os);
}
break;
}
case HighFive::DataTypeClass::Enum: {
if (data_type == HighFive::create_datatype<bool>()) {
printAttributeValue<bool>(attribute);
printAttributeValue<bool>(attribute, os);
} else {
std::cout << "????";
os << "????"; // LCOV_EXCL_LINE
}
break;
}
case HighFive::DataTypeClass::String: {
printAttributeValue<std::string>(attribute);
printAttributeValue<std::string>(attribute, os);
break;
}
// LCOV_EXCL_START
default: {
std::ostringstream error_msg;
error_msg << "invalid data type class '" << rang::fgB::yellow << data_type.string() << rang::fg::reset
<< "' for symbol " << rang::fgB::cyan << symbol_name << rang::fg::reset;
throw UnexpectedError(error_msg.str());
}
// LCOV_EXCL_STOP
}
std::cout << rang::style::reset << '\n';
os << rang::style::reset << '\n';
}
if (saved_symbol_table.exist("embedded")) {
HighFive::Group embedded_data_list = saved_symbol_table.getGroup("embedded");
for (auto name : embedded_data_list.listObjectNames()) {
std::cout << " ";
std::cout << std::setw(25) << std::setfill('.') // << rang::style::bold;
<< std::left << name + ' ' << std::setfill(' ');
std::cout << ' ';
std::cout << embedded_data_list.getGroup(name).getAttribute("type").read<std::string>() << '\n';
os << " ";
os << std::setw(25) << std::setfill('.') << std::left << name + ' ' << std::setfill(' ');
os << ' ';
os << embedded_data_list.getGroup(name).getAttribute("type").read<std::string>() << '\n';
}
}
......@@ -166,24 +166,26 @@ printCheckpointInfo(const std::string& filename)
} while (not finished);
}
std::cout << "-------------------------------------------------------\n";
os << "-------------------------------------------------------\n";
for (auto path : std::array{"resuming_checkpoint", "last_checkpoint"}) {
std::cout << rang::fgB::yellow << " * " << rang::fg::reset << rang::style::bold << path << rang::style::reset
<< " -> " << rang::fgB::green << file.getGroup(path).getAttribute("name").read<std::string>()
<< rang::style::reset << '\n';
os << rang::fgB::yellow << " * " << rang::fg::reset << rang::style::bold << path << rang::style::reset << " -> "
<< rang::fgB::green << file.getGroup(path).getAttribute("name").read<std::string>() << rang::style::reset
<< '\n';
}
}
// LCOV_EXCL_START
catch (HighFive::Exception& e) {
std::cerr << rang::fgB::red << "error: " << rang::fg::reset << rang::style::bold << e.what() << rang::style::reset
<< '\n';
}
// LCOV_EXCL_STOP
}
}
#else // PUGS_HAS_HDF5
void
printCheckpointInfo(const std::string&)
printCheckpointInfo(const std::string&, std::ostream&)
{
std::cerr << rang::fgB::red << "error: " << rang::fg::reset << "checkpoint info requires HDF5\n";
}
......
#ifndef PRINT_CHECKPOINT_INFO_HPP
#define PRINT_CHECKPOINT_INFO_HPP
#include <iostream>
#include <string>
void printCheckpointInfo(const std::string& filename);
void printCheckpointInfo(const std::string& filename, std::ostream& os = std::cout);
#endif // PRINT_CHECKPOINT_INFO_HPP
......@@ -54,7 +54,9 @@ readItemArrayVariant(const HighFive::Group& item_array_variant_group)
p_item_array = std::make_shared<ItemArrayVariant>(
readItemArray<TinyMatrix<3>, item_type>(item_array_variant_group, "arrays", connectivity));
} else {
// LCOV_EXCL_START
throw UnexpectedError("unexpected discrete function data type: " + data_type);
// LCOV_EXCL_STOP
}
return p_item_array;
}
......
......@@ -158,6 +158,7 @@ add_executable (unit_tests
)
set(checkpointing_TESTS
test_checkpointing_PrintCheckpointInfo.cpp
test_checkpointing_PrintScriptFrom.cpp
test_checkpointing_ResumingUtils.cpp
test_checkpointing_SetResumeFrom.cpp
......
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_all.hpp>
#include <algebra/TinyMatrix.hpp>
#include <algebra/TinyVector.hpp>
#include <utils/HighFivePugsUtils.hpp>
#include <utils/Messenger.hpp>
#include <utils/checkpointing/PrintCheckpointInfo.hpp>
#include <filesystem>
// clazy:excludeall=non-pod-global-static
TEST_CASE("PrintCheckpointInfo", "[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,...)";
std::string info = R"( * checkpoint_0 [Today]
X1 ...................... [2.7]
X2 ...................... [-2.3,4.1]
a ....................... 1.3
b ....................... true
n ....................... 12
z ....................... -3
mesh0 ................... mesh
* checkpoint_1 [Tomorrow]
X3 ...................... [1.2,1.4,-1]
m ....................... 8
z ....................... -6
tv ...................... ([1,2], [-1.2,3])
* checkpoint_2 [Yesterday]
M1 ...................... [[2.7]]
M2 ...................... [[-2.3,4.1],[-1.8,1.5]]
M3 ...................... [[-2.3,4.1,3.2],[-1.8,1.5,1.7],[-1.2,0.7,1.2]]
s ....................... "foo"
ts ...................... ("foo", "bar")
-------------------------------------------------------
* resuming_checkpoint -> checkpoint_1
* last_checkpoint -> checkpoint_2
)";
{
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);
{
HighFive::Group cp = file.createGroup("/checkpoint_0");
cp.createAttribute("data.pgs", data_file0);
cp.createAttribute("id", 0ul);
cp.createAttribute("creation_date", std::string{"Today"});
cp.createAttribute("checkpoint_number", 0ul);
cp.createAttribute("name", std::string{"checkpoint_0"});
HighFive::Group symbol_table = cp.createGroup("symbol table");
symbol_table.createAttribute("a", 1.3);
symbol_table.createAttribute("n", uint64_t{12});
symbol_table.createAttribute("z", int64_t{-3});
symbol_table.createAttribute("X1", TinyVector<1>{2.7});
symbol_table.createAttribute("X2", TinyVector<2>{-2.3, 4.1});
symbol_table.createAttribute("b", true);
HighFive::Group embedded = symbol_table.createGroup("embedded");
HighFive::Group mesh0 = embedded.createGroup("mesh0");
mesh0.createAttribute("type", std::string{"mesh"});
}
{
HighFive::Group cp = file.createGroup("/checkpoint_1");
cp.createAttribute("data.pgs", data_file1);
cp.createAttribute("id", 1ul);
cp.createAttribute("creation_date", std::string{"Tomorrow"});
cp.createAttribute("checkpoint_number", 1ul);
cp.createAttribute("name", std::string{"checkpoint_1"});
HighFive::Group symbol_table = cp.createGroup("symbol table");
symbol_table.createAttribute("m", uint64_t{8});
symbol_table.createAttribute("z", int64_t{-6});
symbol_table.createAttribute("X3", TinyVector<3>{1.2, 1.4, -1});
HighFive::Group sub_symbol_table = symbol_table.createGroup("symbol table");
sub_symbol_table.createAttribute("tv", std::vector{TinyVector<2>{1, 2}, TinyVector<2>{-1.2, 3}});
file.createHardLink("resuming_checkpoint", cp);
}
{
HighFive::Group cp = file.createGroup("/checkpoint_2");
cp.createAttribute("data.pgs", data_file2);
cp.createAttribute("id", 2ul);
cp.createAttribute("creation_date", std::string{"Yesterday"});
cp.createAttribute("checkpoint_number", 2ul);
cp.createAttribute("name", std::string{"checkpoint_2"});
HighFive::Group symbol_table = cp.createGroup("symbol table");
symbol_table.createAttribute("s", std::string{"foo"});
symbol_table.createAttribute("M1", TinyMatrix<1>{2.7});
symbol_table.createAttribute("M2", TinyMatrix<2>{-2.3, 4.1, //
-1.8, 1.5});
symbol_table.createAttribute("M3", TinyMatrix<3>{-2.3, 4.1, 3.2, //
-1.8, 1.5, 1.7, //
-1.2, 0.7, 1.2});
symbol_table.createAttribute("ts", std::vector<std::string>{"foo", "bar"});
file.createHardLink("last_checkpoint", cp);
}
}
{
std::ostringstream os;
printCheckpointInfo(filename, os);
if (parallel::rank() == 0) {
REQUIRE(os.str() == info);
} else {
REQUIRE(os.str() == "");
}
}
}
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(printCheckpointInfo("foo.h5", os));
if (parallel::rank() == 0) {
std::cerr.clear();
}
REQUIRE(os.str() == "");
#endif // PUGS_HAS_HDF5
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment