...
 
Commits (3)
...@@ -10,7 +10,7 @@ variables: ...@@ -10,7 +10,7 @@ variables:
BASE_IMAGE: dorie/dune-env BASE_IMAGE: dorie/dune-env
# Use semantic versioning (not the version of DUNE) and bump according to # Use semantic versioning (not the version of DUNE) and bump according to
# to whether changes are backwards-compatible or not. # to whether changes are backwards-compatible or not.
IMAGE_VERSION: "1.2" IMAGE_VERSION: "1.3"
DUNE_ENV_IMAGE: ${BASE_IMAGE}:img-v${IMAGE_VERSION} DUNE_ENV_IMAGE: ${BASE_IMAGE}:img-v${IMAGE_VERSION}
CMAKE_FLAGS: CMAKE_FLAGS:
......
...@@ -48,7 +48,7 @@ add_subdirectory("python") ...@@ -48,7 +48,7 @@ add_subdirectory("python")
add_subdirectory("doc") add_subdirectory("doc")
add_subdirectory("dune") add_subdirectory("dune")
add_subdirectory("lib") add_subdirectory("lib")
if(dune-testtools_FOUND) if(DORIE_TESTING)
add_subdirectory("test") add_subdirectory("test")
endif() endif()
......
...@@ -41,11 +41,23 @@ find_package (yaml-cpp 0.5.2 REQUIRED) ...@@ -41,11 +41,23 @@ find_package (yaml-cpp 0.5.2 REQUIRED)
# muparser # muparser
find_package (muparser REQUIRED) find_package (muparser REQUIRED)
# BOOST Unit Test framework
find_package(Boost 1.62
COMPONENTS unit_test_framework)
# Report the DUNE libs # Report the DUNE libs
message (STATUS "DUNE Libraries: ${DUNE_LIBS}") message (STATUS "DUNE Libraries: ${DUNE_LIBS}")
# Remove CMake policy stack # Remove CMake policy stack
cmake_policy(POP) cmake_policy(POP)
# Add DORiE testing functions # Check if testing is enabled
include(DorieTesting) if (dune-testtools_FOUND AND TARGET Boost::unit_test_framework)
message(STATUS "Testing enabled: dune-testtools and Boost Unit Test found.")
set(DORIE_TESTING TRUE)
# include the DORiE testing macros
include(DorieTesting)
else()
message(STATUS "Testing disabled: dune-testtools and Boost Unit Test "
"not found.")
endif()
...@@ -82,6 +82,13 @@ function(dorie_add_unit_test) ...@@ -82,6 +82,13 @@ function(dorie_add_unit_test)
target_link_libraries(${UNIT_TEST_TARGET} target_link_libraries(${UNIT_TEST_TARGET}
muparser::muparser hdf5 yaml-cpp spdlog) muparser::muparser hdf5 yaml-cpp spdlog)
add_coverage_links(${UNIT_TEST_TARGET}) add_coverage_links(${UNIT_TEST_TARGET})
# add Boost Unit Test links and compile options
target_link_libraries(${UNIT_TEST_TARGET} Boost::unit_test_framework)
# NOTE: Might lead to issues if linked to the static unit test library
target_compile_definitions(${UNIT_TEST_TARGET}
PRIVATE BOOST_TEST_DYN_LINK)
add_dependencies(build_unit_tests ${UNIT_TEST_TARGET}) add_dependencies(build_unit_tests ${UNIT_TEST_TARGET})
endfunction() endfunction()
......
...@@ -19,6 +19,7 @@ RUN apt-get clean \ ...@@ -19,6 +19,7 @@ RUN apt-get clean \
gfortran \ gfortran \
git \ git \
libatlas-base-dev \ libatlas-base-dev \
libboost-test-dev \
libfftw3-dev \ libfftw3-dev \
libfftw3-mpi-dev \ libfftw3-mpi-dev \
libfreetype6-dev \ libfreetype6-dev \
......
add_subdirectory("common") add_subdirectory("common")
add_subdirectory("model") add_subdirectory("model")
if(dune-testtools_FOUND) if(DORIE_TESTING)
add_subdirectory("test") add_subdirectory("test")
endif() endif()
......
#define BOOST_TEST_MODULE simulation base test
#include <boost/test/unit_test.hpp>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#include <cassert>
#include <dune/common/parallel/mpihelper.hh>
#include <dune/common/float_cmp.hh> #include <dune/common/float_cmp.hh>
#include <dune/common/parallel/mpihelper.hh>
#include <dune/dorie/common/simulation_base.hh> #include <dune/dorie/common/simulation_base.hh>
/// Dummy model for testing. /// Fixture for all test cases
/** Makes sure that all functions of SimulationBase are properly overridden struct DummyFixture
* and called.
*/
class DummyModel : public Dune::Dorie::SimulationBase
{ {
public: /// Initialize the DUNE MPI Helper from the command line arguments
DummyModel(Dune::MPIHelper& helper) Dune::MPIHelper& helper = Dune::MPIHelper::instance(
: Dune::Dorie::SimulationBase("dummy", boost::unit_test::framework::master_test_suite().argc,
"debug", boost::unit_test::framework::master_test_suite().argv
helper, );
Dune::Dorie::OutputPolicy::None,
Dune::Dorie::AdaptivityPolicy::None) /// Dummy model for testing only. Implements all pure virtual methods.
, _dt(.1) class DummyModel : public Dune::Dorie::SimulationBase
, _current_time(begin_time()) {
, _end_time(1.0) private:
, _grid_was_adapted(false) using Base = Dune::Dorie::SimulationBase;
, _data_was_written(false)
{} public:
DummyModel (Dune::MPIHelper& helper) :
double begin_time() const override { return 0.; } Base("dummy",
double end_time() const override { return _end_time; } "debug",
double current_time() const override { return _current_time; } helper,
void suggest_timestep(double dt) override { _dt = std::min(dt,_dt); } Dune::Dorie::OutputPolicy::None,
void step() override { _current_time+=_dt; } Dune::Dorie::AdaptivityPolicy::None),
_dt(.1),
/// Do nothing. _current_time(begin_time()),
void mark_grid () override {}; _end_time(1.0),
_grid_was_adapted(false),
/// Adapt the grid in our minds. _data_was_written(false)
void adapt_grid () override { }
{
_grid_was_adapted = true; double begin_time() const override { return 0.; }
} double end_time() const override { return _end_time; }
double current_time() const override { return _current_time; }
void write_data() const override void suggest_timestep(double dt) override { _dt = std::min(dt,_dt); }
{ void step() override { _current_time+=_dt; }
this->_log->info("Current time: {}", _current_time);
_data_was_written = true; /// Do nothing.
} void mark_grid () override {};
private: /// Adapt the grid in our minds.
double _dt; void adapt_grid () override
double _current_time; {
_grid_was_adapted = true;
public: }
double _end_time;
bool _grid_was_adapted; void write_data() const override
mutable bool _data_was_written; {
this->_log->info("Current time: {}", _current_time);
_data_was_written = true;
}
private:
double _dt;
double _current_time;
public:
double _end_time;
bool _grid_was_adapted;
mutable bool _data_was_written;
} model = DummyModel(helper);
}; };
int main(int argc, char **argv) /// Create a new suite using the fixture in every test case
BOOST_FIXTURE_TEST_SUITE(suite, DummyFixture);
/// Test if the model is correctly initialized
BOOST_AUTO_TEST_CASE (initialize)
{
BOOST_TEST(model._end_time == 1.0);
BOOST_TEST(model._grid_was_adapted == false);
BOOST_TEST(model._data_was_written == false);
BOOST_TEST(model.begin_time() == 0.0);
BOOST_TEST(model.current_time() == 0.0);
const bool output_policy =
(model.output_policy() == Dune::Dorie::OutputPolicy::None);
BOOST_TEST(output_policy);
const bool adaptivity_policy =
(model.adaptivity_policy() == Dune::Dorie::AdaptivityPolicy::None);
BOOST_TEST(adaptivity_policy);
}
/// Test if policies are correctly set
BOOST_AUTO_TEST_CASE (policies)
{ {
auto& helper = Dune::MPIHelper::instance(argc, argv); const auto adapt_policy = Dune::Dorie::AdaptivityPolicy::WaterFlux;
model.set_policy(adapt_policy);
bool policy_correct = (model.adaptivity_policy() == adapt_policy);
BOOST_TEST(policy_correct);
const auto output_policy = Dune::Dorie::OutputPolicy::EndOfRichardsStep;
model.set_policy(output_policy);
policy_correct = (model.output_policy() == output_policy);
BOOST_TEST(policy_correct);
}
try { /// Test if the model correctly performs the run() algorithm
DummyModel model(helper); BOOST_AUTO_TEST_CASE (run)
{
// perform a step
model.step();
BOOST_TEST(Dune::FloatCmp::eq(model.current_time(),
model.begin_time() + 0.1));
// run the model without adaptivity // run multiple steps
model.run(); model.run();
assert(not model._grid_was_adapted); BOOST_TEST(Dune::FloatCmp::eq(model.current_time(),
assert(not model._data_was_written); model.end_time()));
assert(Dune::FloatCmp::ge(model.current_time(), model.end_time())); BOOST_TEST(not model._grid_was_adapted);
BOOST_TEST(not model._data_was_written);
// now set adaptivity // set new policies
model.set_policy(Dune::Dorie::AdaptivityPolicy::WaterFlux); model.set_policy(Dune::Dorie::AdaptivityPolicy::WaterFlux);
model.set_policy(Dune::Dorie::OutputPolicy::EndOfRichardsStep); model.set_policy(Dune::Dorie::OutputPolicy::EndOfRichardsStep);
model._end_time += 1.0; model._end_time += 1.0;
// run multiple steps, check if policies are applied
model.run(); model.run();
assert(model._grid_was_adapted); BOOST_TEST(Dune::FloatCmp::eq(model.current_time(),
assert(model._data_was_written); model.end_time()));
assert(Dune::FloatCmp::ge(model.current_time(), model.end_time())); BOOST_TEST(model._grid_was_adapted);
BOOST_TEST(model._data_was_written);
} catch (Dune::Exception& e) {
std::cout << e.what() << std::endl;
return 1;
} catch (...) {
std::cerr << "Exception occurred!" << std::endl;
return 1;
}
return 0;
} }
BOOST_AUTO_TEST_SUITE_END()