test: add test cases for Field class

This commit is contained in:
Max Luebke 2023-03-03 14:16:26 +01:00
parent 1129761df3
commit 357936b639
4 changed files with 198 additions and 0 deletions

View File

@ -24,9 +24,19 @@ add_subdirectory(data)
add_subdirectory(app)
add_subdirectory(bench/dolo_diffu_inner)
# as tug will also pull in doctest as a dependency
set(TUG_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
add_subdirectory(ext/tug EXCLUDE_FROM_ALL)
add_subdirectory(ext/phreeqcrm EXCLUDE_FROM_ALL)
option(POET_ENABLE_TESTING "Build test suite for POET" OFF)
if (POET_ENABLE_TESTING)
add_subdirectory(ext/doctest EXCLUDE_FROM_ALL)
add_subdirectory(test)
endif()
option(BUILD_DOC "Build documentation with doxygen" OFF)
if(BUILD_DOC)

11
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,11 @@
file(GLOB test_SRC
CONFIGURE_DEPENDS
"*.cpp" "*.c")
add_executable(testPOET ${test_SRC})
target_link_libraries(testPOET doctest poet_lib)
add_custom_target(check
COMMAND $<TARGET_FILE:testPOET>
DEPENDS testPOET
)

2
test/setup.cpp Normal file
View File

@ -0,0 +1,2 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>

175
test/testDataStructures.cpp Normal file
View File

@ -0,0 +1,175 @@
#include <algorithm>
#include <array>
#include <cstdint>
#include <doctest/doctest.h>
#include <iostream>
#include <poet/Field.hpp>
#include <string>
#include <vector>
using namespace poet;
#define CHECK_AND_FAIL_LOOP(val1, val2) \
if (val1 != val2) { \
FAIL_CHECK("Value differs: ", val1, " != ", val2); \
}
TEST_CASE("Field") {
constexpr uint32_t VEC_SIZE = 5;
constexpr uint32_t VEC_COUNT = 3;
constexpr double INIT_VAL = 1;
Field dut(VEC_SIZE);
std::vector<std::string> names = {"C", "Ca", "Na"};
std::vector<FieldColumn> init_values(names.size(),
FieldColumn(VEC_SIZE, INIT_VAL));
SUBCASE("Initialize field with 2D vector") {
dut.InitFromVec(init_values, names);
auto props = dut.GetProps();
CHECK_EQ(names.size(), props.size());
const auto res = dut["C"];
CHECK_EQ(res.size(), VEC_SIZE);
for (const auto &elem : res) {
CHECK_AND_FAIL_LOOP(elem, INIT_VAL);
}
}
SUBCASE("Initialize field with 2D vector") {
std::vector<double> init_values(VEC_SIZE * VEC_COUNT, 1);
dut.InitFromVec(init_values, names);
auto props = dut.GetProps();
CHECK_EQ(names.size(), props.size());
const auto res = dut["C"];
CHECK_EQ(res.size(), VEC_SIZE);
for (const auto &elem : res) {
CHECK_AND_FAIL_LOOP(elem, INIT_VAL);
}
}
dut.InitFromVec(init_values, names);
SUBCASE("Return vector") {
std::vector<double> output = dut.AsVector();
CHECK(output.size() == VEC_SIZE * VEC_COUNT);
}
constexpr double NEW_VAL = 2.;
std::vector<double> new_val_vec(VEC_SIZE, NEW_VAL);
dut["C"] = new_val_vec;
SUBCASE("Check manipulation of column") {
auto test_it = new_val_vec.begin();
for (const auto &val : dut["C"]) {
CHECK_EQ(val, *test_it);
test_it++;
}
}
SUBCASE("Check correctly manipulated values of 1D vector") {
auto out_res = dut.AsVector();
auto out_it = out_res.begin();
for (uint32_t i = 0; i < VEC_SIZE; i++, out_it++) {
CHECK_AND_FAIL_LOOP(NEW_VAL, *out_it);
}
for (; out_it != out_res.end(); out_it++) {
CHECK_AND_FAIL_LOOP(INIT_VAL, *out_it);
}
}
std::vector<double> new_field(VEC_SIZE * VEC_COUNT);
for (uint32_t i = 0; i < VEC_COUNT; i++) {
for (uint32_t j = 0; j < VEC_SIZE; j++) {
new_field[j + (i * VEC_SIZE)] = (double)(i + 1) / (double)(j + 1);
}
}
dut.SetFromVector(new_field);
SUBCASE("SetFromVector return correct field vector") {
auto ret_vec = dut.AsVector();
auto ret_it = ret_vec.begin();
auto new_it = new_field.begin();
for (; ret_it != ret_vec.end(); ret_it++, new_it++) {
CHECK_AND_FAIL_LOOP(*ret_it, *new_it);
}
}
SUBCASE("Get single column with new values") {
auto new_it = new_field.begin() + 2 * VEC_SIZE;
auto ret_vec = dut["Na"];
auto ret_it = ret_vec.begin();
CHECK_EQ(ret_vec.size(), VEC_SIZE);
for (; ret_it != ret_vec.end(); ret_it++, new_it++) {
CHECK_AND_FAIL_LOOP(*ret_it, *new_it);
}
}
std::vector<double> mg_vec = {1, 2, 3, 4, 5};
dut["Mg"] = mg_vec;
SUBCASE("Operator creates new element and places it at the end") {
auto new_props = dut.GetProps();
CHECK_EQ(new_props.size(), 4);
CHECK_EQ(new_props[3], "Mg");
auto ret_vec = dut.As2DVector();
auto mg_vec_it = mg_vec.begin();
for (const auto &val : ret_vec[3]) {
CHECK_AND_FAIL_LOOP(val, *(mg_vec_it++));
}
}
// reset field
names = dut.GetProps();
dut.SetFromVector(
std::vector<FieldColumn>(names.size(), FieldColumn(VEC_SIZE, INIT_VAL)));
constexpr double SOME_OTHER_VAL = -0.5;
Field some_other_field(VEC_SIZE);
std::vector<std::string> some_other_props = {"Na", "Cl"};
std::vector<double> some_other_values(VEC_SIZE * some_other_props.size(),
SOME_OTHER_VAL);
some_other_field.InitFromVec(some_other_values, some_other_props);
SUBCASE("Update existing field from another field") {
dut.UpdateFromField(some_other_field);
auto ret_vec = dut.As2DVector();
auto ret_it = ret_vec.begin();
for (const auto &prop : names) {
const auto &curr_vec = *(ret_it++);
for (const auto &val : curr_vec) {
CHECK_AND_FAIL_LOOP((prop == "Na" ? SOME_OTHER_VAL : INIT_VAL), val);
}
}
}
}