diff --git a/include/dca/phys/parameters/output_parameters.hpp b/include/dca/phys/parameters/output_parameters.hpp index 864a52421..c1b870074 100644 --- a/include/dca/phys/parameters/output_parameters.hpp +++ b/include/dca/phys/parameters/output_parameters.hpp @@ -14,6 +14,7 @@ #ifndef DCA_PHYS_PARAMETERS_OUTPUT_PARAMETERS_HPP #define DCA_PHYS_PARAMETERS_OUTPUT_PARAMETERS_HPP +#include #include #include #include "dca/io/io_types.hpp" @@ -64,6 +65,12 @@ class OutputParameters { template void readWrite(ReaderOrWriter& reader_or_writer); + // Throws std::invalid_argument if the parsed parameters describe state that cannot be + // used in a run (e.g. the configured output directory does not exist on disk). Intended + // to be called by Parameters::readInput on the rank that parsed the input file. + // Issue #300: surface bad input at parse time instead of crashing later in HDF5. + void validate() const; + const std::string& get_directory() const { return directory_; } @@ -272,6 +279,11 @@ void OutputParameters::readWrite(ReaderOrWriter& reader_or_writer) { } } +inline void OutputParameters::validate() const { + if (!std::filesystem::exists(directory_)) + throw std::invalid_argument("Output directory does not exist: " + directory_); +} + } // namespace params } // namespace phys } // namespace dca diff --git a/include/dca/phys/parameters/parameters.hpp b/include/dca/phys/parameters/parameters.hpp index 56c4be6ff..57636ab0d 100644 --- a/include/dca/phys/parameters/parameters.hpp +++ b/include/dca/phys/parameters/parameters.hpp @@ -281,6 +281,7 @@ void ParametersreadWrite(read_obj); read_obj.close_file(); + OutputParameters::validate(); } } diff --git a/test/unit/phys/parameters/output_parameters/missing_directory.json b/test/unit/phys/parameters/output_parameters/missing_directory.json new file mode 100644 index 000000000..1ff57317f --- /dev/null +++ b/test/unit/phys/parameters/output_parameters/missing_directory.json @@ -0,0 +1,5 @@ +{ + "output": { + "directory": "/nonexistent/path/for/dca_input_validation_test" + } +} diff --git a/test/unit/phys/parameters/output_parameters/output_parameters_test.cpp b/test/unit/phys/parameters/output_parameters/output_parameters_test.cpp index a8f19a75b..7a9ac7cfb 100644 --- a/test/unit/phys/parameters/output_parameters/output_parameters_test.cpp +++ b/test/unit/phys/parameters/output_parameters/output_parameters_test.cpp @@ -12,6 +12,8 @@ // TODO: Add tests for get_buffer_size, pack, unpack and writing. +#include + #include "dca/config/haves_defines.hpp" #include "dca/phys/parameters/output_parameters.hpp" #include "dca/testing/gtest_h_w_warning_blocking.h" @@ -88,3 +90,18 @@ TEST(OutputParametersTest, ReadAll) { EXPECT_TRUE(pars.dump_Gamma_lattice()); EXPECT_TRUE(pars.dump_chi_0_lattice()); } + +// Issue #300, bug #1: a non-existent output.directory should produce a clear error at +// parameter-read time. readWrite() parses the directory string without touching the +// disk; validate() is where the existence check and the throw live. +TEST(OutputParametersTest, MissingDirectoryThrows) { + dca::io::JSONReader reader; + dca::phys::params::OutputParameters pars; + + reader.open_file(DCA_SOURCE_DIR + "/test/unit/phys/parameters/output_parameters/missing_directory.json"); + pars.readWrite(reader); + reader.close_file(); + + EXPECT_THROW(pars.validate(), std::invalid_argument); +}