feat: Integrate GoogleTest for unit testing and update CI configuration

This commit is contained in:
Max Lübke 2024-12-06 09:28:53 +01:00
parent a986242852
commit 6981373deb
8 changed files with 256 additions and 260 deletions

View File

@ -1,27 +1,26 @@
image: git.gfz-potsdam.de:5000/naaice/tug:ci image: gcc:14
before_script:
- apt-get update && apt-get install -y cmake ninja-build libeigen3-dev git
stages: stages:
- build
- test - test
- static_analyze - static_analyze
- doc - doc
build_release:
stage: build
artifacts:
paths:
- build/test/testTug
expire_in: 100s
script:
- mkdir build && cd build
- cmake -DCMAKE_BUILD_TYPE=Release -DTUG_ENABLE_TESTING=ON ..
- make -j$(nproc)
- cp ../test/FTCS_11_11_7000.csv test/
test: test:
stage: test stage: test
script: script:
- ./build/test/testTug - mkdir build && cd build
- cmake -DCMAKE_BUILD_TYPE=Release -DTUG_ENABLE_TESTING=ON -G Ninja ..
- ninja
- ctest --output-junit test_results.xml
artifacts:
when: always
paths:
- build/test_results.xml
reports:
junit: build/test_results.xml
pages: pages:
stage: doc stage: doc

View File

@ -90,6 +90,7 @@ install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/tug DESTINATION include) install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/tug DESTINATION include)
if(TUG_ENABLE_TESTING) if(TUG_ENABLE_TESTING)
enable_testing()
add_subdirectory(test) add_subdirectory(test)
endif() endif()

View File

@ -1,7 +1,24 @@
find_package(doctest REQUIRED) include(FetchContent)
add_executable(testTug setup.cpp testSimulation.cpp testGrid.cpp testFTCS.cpp testBoundary.cpp) FetchContent_Declare(
target_link_libraries(testTug doctest::doctest tug) googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.15.2
)
FetchContent_MakeAvailable(googletest)
add_executable(testTug
testSimulation.cpp
testGrid.cpp
testFTCS.cpp
testBoundary.cpp
)
target_link_libraries(testTug tug GTest::gtest_main)
include(GoogleTest)
gtest_discover_tests(testTug)
# get relative path of the CSV file # get relative path of the CSV file
get_filename_component(testSimulationCSV "FTCS_11_11_7000.csv" REALPATH) get_filename_component(testSimulationCSV "FTCS_11_11_7000.csv" REALPATH)
@ -9,8 +26,3 @@ get_filename_component(testSimulationCSV "FTCS_11_11_7000.csv" REALPATH)
configure_file(testSimulation.hpp.in testSimulation.hpp) configure_file(testSimulation.hpp.in testSimulation.hpp)
# include test directory with generated header file from above # include test directory with generated header file from above
target_include_directories(testTug PUBLIC "${CMAKE_CURRENT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/src") target_include_directories(testTug PUBLIC "${CMAKE_CURRENT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/src")
add_custom_target(
check
COMMAND $<TARGET_FILE:testTug>
DEPENDS testTug)

View File

@ -1,11 +1,13 @@
#include <Eigen/Core> #include <Eigen/Core>
#include <Eigen/Dense> #include <Eigen/Dense>
#include <fstream> #include <fstream>
#include <ios>
#include <iostream>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <gtest/gtest.h>
#define TUG_TEST(x) TEST(Tug, x)
inline Eigen::MatrixXd CSV2Eigen(std::string file2Convert) { inline Eigen::MatrixXd CSV2Eigen(std::string file2Convert) {
std::vector<double> matrixEntries; std::vector<double> matrixEntries;

View File

@ -1,36 +1,31 @@
#include <doctest/doctest.h>
#include <iostream>
#include <stdio.h>
#include <string>
#include <tug/Boundary.hpp> #include <tug/Boundary.hpp>
#include <typeinfo>
#include <utility> #include <utility>
#include <vector> #include <vector>
using namespace std; using namespace std;
using namespace tug; using namespace tug;
TEST_CASE("BoundaryElement") { #include <gtest/gtest.h>
#define BOUNDARY_TEST(x) TEST(Boundary, x)
BOUNDARY_TEST(Element) {
SUBCASE("Closed case") {
BoundaryElement boundaryElementClosed = BoundaryElement<double>(); BoundaryElement boundaryElementClosed = BoundaryElement<double>();
CHECK_NOTHROW(BoundaryElement<double>()); EXPECT_NO_THROW(BoundaryElement<double>());
CHECK_EQ(boundaryElementClosed.getType(), BC_TYPE_CLOSED); EXPECT_EQ(boundaryElementClosed.getType(), BC_TYPE_CLOSED);
CHECK_EQ(boundaryElementClosed.getValue(), -1); EXPECT_DOUBLE_EQ(boundaryElementClosed.getValue(), -1);
CHECK_THROWS(boundaryElementClosed.setValue(0.2)); EXPECT_ANY_THROW(boundaryElementClosed.setValue(0.2));
}
SUBCASE("Constant case") {
BoundaryElement boundaryElementConstant = BoundaryElement(0.1); BoundaryElement boundaryElementConstant = BoundaryElement(0.1);
CHECK_NOTHROW(BoundaryElement(0.1)); EXPECT_NO_THROW(BoundaryElement(0.1));
CHECK_EQ(boundaryElementConstant.getType(), BC_TYPE_CONSTANT); EXPECT_EQ(boundaryElementConstant.getType(), BC_TYPE_CONSTANT);
CHECK_EQ(boundaryElementConstant.getValue(), 0.1); EXPECT_DOUBLE_EQ(boundaryElementConstant.getValue(), 0.1);
CHECK_NOTHROW(boundaryElementConstant.setValue(0.2)); EXPECT_NO_THROW(boundaryElementConstant.setValue(0.2));
CHECK_EQ(boundaryElementConstant.getValue(), 0.2); EXPECT_DOUBLE_EQ(boundaryElementConstant.getValue(), 0.2);
}
} }
TEST_CASE("Boundary Class") { BOUNDARY_TEST(Class) {
Grid grid1D = Grid64(10); Grid grid1D = Grid64(10);
Grid grid2D = Grid64(10, 12); Grid grid2D = Grid64(10, 12);
Boundary boundary1D = Boundary(grid1D); Boundary boundary1D = Boundary(grid1D);
@ -47,56 +42,56 @@ TEST_CASE("Boundary Class") {
std::vector<std::pair<bool, double>> col_ibc(10, std::make_pair(false, -1)); std::vector<std::pair<bool, double>> col_ibc(10, std::make_pair(false, -1));
col_ibc[0] = innerBoundary; col_ibc[0] = innerBoundary;
SUBCASE("Boundaries 1D case") { {
CHECK_NOTHROW(Boundary boundary(grid1D)); EXPECT_NO_THROW(Boundary boundary(grid1D));
CHECK_EQ(boundary1D.getBoundarySide(BC_SIDE_LEFT).size(), 1); EXPECT_EQ(boundary1D.getBoundarySide(BC_SIDE_LEFT).size(), 1);
CHECK_EQ(boundary1D.getBoundarySide(BC_SIDE_RIGHT).size(), 1); EXPECT_EQ(boundary1D.getBoundarySide(BC_SIDE_RIGHT).size(), 1);
CHECK_EQ(boundary1D.getBoundaryElementType(BC_SIDE_LEFT, 0), EXPECT_EQ(boundary1D.getBoundaryElementType(BC_SIDE_LEFT, 0),
BC_TYPE_CLOSED); BC_TYPE_CLOSED);
CHECK_THROWS(boundary1D.getBoundarySide(BC_SIDE_TOP)); EXPECT_ANY_THROW(boundary1D.getBoundarySide(BC_SIDE_TOP));
CHECK_THROWS(boundary1D.getBoundarySide(BC_SIDE_BOTTOM)); EXPECT_ANY_THROW(boundary1D.getBoundarySide(BC_SIDE_BOTTOM));
CHECK_NOTHROW(boundary1D.setBoundarySideClosed(BC_SIDE_LEFT)); EXPECT_NO_THROW(boundary1D.setBoundarySideClosed(BC_SIDE_LEFT));
CHECK_THROWS(boundary1D.setBoundarySideClosed(BC_SIDE_TOP)); EXPECT_ANY_THROW(boundary1D.setBoundarySideClosed(BC_SIDE_TOP));
CHECK_NOTHROW(boundary1D.setBoundarySideConstant(BC_SIDE_LEFT, 1.0)); EXPECT_NO_THROW(boundary1D.setBoundarySideConstant(BC_SIDE_LEFT, 1.0));
CHECK_EQ(boundary1D.getBoundaryElementValue(BC_SIDE_LEFT, 0), 1.0); EXPECT_DOUBLE_EQ(boundary1D.getBoundaryElementValue(BC_SIDE_LEFT, 0), 1.0);
CHECK_THROWS(boundary1D.getBoundaryElementValue(BC_SIDE_LEFT, 2)); EXPECT_ANY_THROW(boundary1D.getBoundaryElementValue(BC_SIDE_LEFT, 2));
CHECK_EQ(boundary1D.getBoundaryElementType(BC_SIDE_LEFT, 0), EXPECT_EQ(boundary1D.getBoundaryElementType(BC_SIDE_LEFT, 0),
BC_TYPE_CONSTANT); BC_TYPE_CONSTANT);
CHECK_EQ(boundary1D.getBoundaryElement(BC_SIDE_LEFT, 0).getType(), EXPECT_EQ(boundary1D.getBoundaryElement(BC_SIDE_LEFT, 0).getType(),
boundary1DVector[0].getType()); boundary1DVector[0].getType());
CHECK_NOTHROW(boundary1D.setInnerBoundary(0, inner_condition_value)); EXPECT_NO_THROW(boundary1D.setInnerBoundary(0, inner_condition_value));
CHECK_THROWS(boundary1D.setInnerBoundary(0, 0, inner_condition_value)); EXPECT_ANY_THROW(boundary1D.setInnerBoundary(0, 0, inner_condition_value));
CHECK_EQ(boundary1D.getInnerBoundary(0), innerBoundary); EXPECT_EQ(boundary1D.getInnerBoundary(0), innerBoundary);
CHECK_EQ(boundary1D.getInnerBoundary(1).first, false); EXPECT_FALSE(boundary1D.getInnerBoundary(1).first);
} }
SUBCASE("Boundaries 2D case") { {
CHECK_NOTHROW(Boundary boundary(grid1D)); EXPECT_NO_THROW(Boundary boundary(grid1D));
CHECK_EQ(boundary2D.getBoundarySide(BC_SIDE_LEFT).size(), 10); EXPECT_EQ(boundary2D.getBoundarySide(BC_SIDE_LEFT).size(), 10);
CHECK_EQ(boundary2D.getBoundarySide(BC_SIDE_RIGHT).size(), 10); EXPECT_EQ(boundary2D.getBoundarySide(BC_SIDE_RIGHT).size(), 10);
CHECK_EQ(boundary2D.getBoundarySide(BC_SIDE_TOP).size(), 12); EXPECT_EQ(boundary2D.getBoundarySide(BC_SIDE_TOP).size(), 12);
CHECK_EQ(boundary2D.getBoundarySide(BC_SIDE_BOTTOM).size(), 12); EXPECT_EQ(boundary2D.getBoundarySide(BC_SIDE_BOTTOM).size(), 12);
CHECK_EQ(boundary2D.getBoundaryElementType(BC_SIDE_LEFT, 0), EXPECT_EQ(boundary2D.getBoundaryElementType(BC_SIDE_LEFT, 0),
BC_TYPE_CLOSED); BC_TYPE_CLOSED);
CHECK_NOTHROW(boundary2D.getBoundarySide(BC_SIDE_TOP)); EXPECT_NO_THROW(boundary2D.getBoundarySide(BC_SIDE_TOP));
CHECK_NOTHROW(boundary2D.getBoundarySide(BC_SIDE_BOTTOM)); EXPECT_NO_THROW(boundary2D.getBoundarySide(BC_SIDE_BOTTOM));
CHECK_NOTHROW(boundary2D.setBoundarySideClosed(BC_SIDE_LEFT)); EXPECT_NO_THROW(boundary2D.setBoundarySideClosed(BC_SIDE_LEFT));
CHECK_NOTHROW(boundary2D.setBoundarySideClosed(BC_SIDE_TOP)); EXPECT_NO_THROW(boundary2D.setBoundarySideClosed(BC_SIDE_TOP));
CHECK_NOTHROW(boundary2D.setBoundarySideConstant(BC_SIDE_LEFT, 1.0)); EXPECT_NO_THROW(boundary2D.setBoundarySideConstant(BC_SIDE_LEFT, 1.0));
CHECK_EQ(boundary2D.getBoundaryElementValue(BC_SIDE_LEFT, 0), 1.0); EXPECT_DOUBLE_EQ(boundary2D.getBoundaryElementValue(BC_SIDE_LEFT, 0), 1.0);
CHECK_THROWS(boundary2D.getBoundaryElementValue(BC_SIDE_LEFT, 12)); EXPECT_ANY_THROW(boundary2D.getBoundaryElementValue(BC_SIDE_LEFT, 12));
CHECK_EQ(boundary2D.getBoundaryElementType(BC_SIDE_LEFT, 0), EXPECT_EQ(boundary2D.getBoundaryElementType(BC_SIDE_LEFT, 0),
BC_TYPE_CONSTANT); BC_TYPE_CONSTANT);
CHECK_EQ(boundary2D.getBoundaryElement(BC_SIDE_LEFT, 0).getType(), EXPECT_EQ(boundary2D.getBoundaryElement(BC_SIDE_LEFT, 0).getType(),
boundary1DVector[0].getType()); boundary1DVector[0].getType());
CHECK_THROWS(boundary2D.setInnerBoundary(0, inner_condition_value)); EXPECT_ANY_THROW(boundary2D.setInnerBoundary(0, inner_condition_value));
CHECK_NOTHROW(boundary2D.setInnerBoundary(0, 1, inner_condition_value)); EXPECT_NO_THROW(boundary2D.setInnerBoundary(0, 1, inner_condition_value));
CHECK_EQ(boundary2D.getInnerBoundary(0, 1), innerBoundary); EXPECT_EQ(boundary2D.getInnerBoundary(0, 1), innerBoundary);
CHECK_EQ(boundary2D.getInnerBoundary(0, 2).first, false); EXPECT_FALSE(boundary2D.getInnerBoundary(0, 2).first);
CHECK_EQ(boundary2D.getInnerBoundaryRow(0), row_ibc); EXPECT_EQ(boundary2D.getInnerBoundaryRow(0), row_ibc);
CHECK_EQ(boundary2D.getInnerBoundaryCol(1), col_ibc); EXPECT_EQ(boundary2D.getInnerBoundaryCol(1), col_ibc);
} }
} }

View File

@ -1,10 +1,9 @@
#include <gtest/gtest.h>
#include <tug/Core/TugUtils.hpp> #include <tug/Core/TugUtils.hpp>
#include <doctest/doctest.h> #include <gtest/gtest.h>
#include <limits>
TEST_CASE("Maths") { TEST(FTCS, calcAlphaIntercell) {
SUBCASE("mean between two alphas") {
double alpha1 = 10; double alpha1 = 10;
double alpha2 = 20; double alpha2 = 20;
double average = 15; double average = 15;
@ -14,7 +13,6 @@ TEST_CASE("Maths") {
// double difference = std::fabs(calcAlphaIntercell(alpha1, alpha2) - // double difference = std::fabs(calcAlphaIntercell(alpha1, alpha2) -
// harmonicMean); CHECK(difference < // harmonicMean); CHECK(difference <
// std::numeric_limits<double>::epsilon()); // std::numeric_limits<double>::epsilon());
CHECK_EQ(calcAlphaIntercell(alpha1, alpha2), harmonicMean); EXPECT_DOUBLE_EQ(calcAlphaIntercell(alpha1, alpha2), harmonicMean);
CHECK_EQ(calcAlphaIntercell(alpha1, alpha2, false), average); EXPECT_DOUBLE_EQ(calcAlphaIntercell(alpha1, alpha2, false), average);
}
} }

View File

@ -1,258 +1,252 @@
#include <Eigen/Core> #include <Eigen/Core>
#include <doctest/doctest.h>
#include <tug/Grid.hpp> #include <tug/Grid.hpp>
#include <vector> #include <vector>
#include <gtest/gtest.h>
using namespace Eigen; using namespace Eigen;
using namespace std; using namespace std;
using namespace tug; using namespace tug;
TEST_CASE("1D Grid, too small length") { #define GRID_TEST(x) TEST(Grid, x)
int l = 2;
CHECK_THROWS(Grid64(l)); GRID_TEST(InvalidConstructorParams) {
EXPECT_ANY_THROW(Grid64(2));
EXPECT_ANY_THROW(Grid64(1, 4));
EXPECT_ANY_THROW(Grid64(4, 1));
} }
TEST_CASE("2D Grid64, too small side") { GRID_TEST(Grid64OneDimensional) {
int r = 1;
int c = 4;
CHECK_THROWS(Grid64(r, c));
r = 4;
c = 1;
CHECK_THROWS(Grid64(r, c));
}
TEST_CASE("1D Grid64") {
int l = 12; int l = 12;
Grid64 grid(l); Grid64 grid(l);
SUBCASE("correct construction") { {
CHECK_EQ(grid.getDim(), 1); EXPECT_EQ(grid.getDim(), 1);
CHECK_EQ(grid.getLength(), l); EXPECT_EQ(grid.getLength(), l);
CHECK_EQ(grid.getCol(), l); EXPECT_EQ(grid.getCol(), l);
CHECK_EQ(grid.getRow(), 1); EXPECT_EQ(grid.getRow(), 1);
CHECK_EQ(grid.getConcentrations().rows(), 1); EXPECT_EQ(grid.getConcentrations().rows(), 1);
CHECK_EQ(grid.getConcentrations().cols(), l); EXPECT_EQ(grid.getConcentrations().cols(), l);
CHECK_EQ(grid.getAlpha().rows(), 1); EXPECT_EQ(grid.getAlpha().rows(), 1);
CHECK_EQ(grid.getAlpha().cols(), l); EXPECT_EQ(grid.getAlpha().cols(), l);
CHECK_EQ(grid.getDeltaCol(), 1); EXPECT_EQ(grid.getDeltaCol(), 1);
CHECK_THROWS(grid.getAlphaX()); EXPECT_ANY_THROW(grid.getAlphaX());
CHECK_THROWS(grid.getAlphaY()); EXPECT_ANY_THROW(grid.getAlphaY());
CHECK_THROWS(grid.getDeltaRow()); EXPECT_ANY_THROW(grid.getDeltaRow());
} }
SUBCASE("setting concentrations") { {
// correct concentrations matrix // correct concentrations matrix
MatrixXd concentrations = MatrixXd::Constant(1, l, 3); MatrixXd concentrations = MatrixXd::Constant(1, l, 3);
CHECK_NOTHROW(grid.setConcentrations(concentrations)); EXPECT_NO_THROW(grid.setConcentrations(concentrations));
// false concentrations matrix // false concentrations matrix
MatrixXd wConcentrations = MatrixXd::Constant(2, l, 4); MatrixXd wConcentrations = MatrixXd::Constant(2, l, 4);
CHECK_THROWS(grid.setConcentrations(wConcentrations)); EXPECT_ANY_THROW(grid.setConcentrations(wConcentrations));
} }
SUBCASE("setting alpha") { {
// correct alpha matrix // correct alpha matrix
MatrixXd alpha = MatrixXd::Constant(1, l, 3); MatrixXd alpha = MatrixXd::Constant(1, l, 3);
CHECK_NOTHROW(grid.setAlpha(alpha)); EXPECT_NO_THROW(grid.setAlpha(alpha));
CHECK_THROWS(grid.setAlpha(alpha, alpha)); EXPECT_ANY_THROW(grid.setAlpha(alpha, alpha));
grid.setAlpha(alpha); grid.setAlpha(alpha);
CHECK_EQ(grid.getAlpha(), alpha); EXPECT_EQ(grid.getAlpha(), alpha);
CHECK_THROWS(grid.getAlphaX()); EXPECT_ANY_THROW(grid.getAlphaX());
CHECK_THROWS(grid.getAlphaY()); EXPECT_ANY_THROW(grid.getAlphaY());
// false alpha matrix // false alpha matrix
MatrixXd wAlpha = MatrixXd::Constant(3, l, 2); MatrixXd wAlpha = MatrixXd::Constant(3, l, 2);
CHECK_THROWS(grid.setAlpha(wAlpha)); EXPECT_ANY_THROW(grid.setAlpha(wAlpha));
} }
SUBCASE("setting domain") { {
int d = 8; int d = 8;
// set 1D domain // set 1D domain
CHECK_NOTHROW(grid.setDomain(d)); EXPECT_NO_THROW(grid.setDomain(d));
// set 2D domain // set 2D domain
CHECK_THROWS(grid.setDomain(d, d)); EXPECT_ANY_THROW(grid.setDomain(d, d));
grid.setDomain(d); grid.setDomain(d);
CHECK_EQ(grid.getDeltaCol(), double(d) / double(l)); EXPECT_DOUBLE_EQ(grid.getDeltaCol(), double(d) / double(l));
CHECK_THROWS(grid.getDeltaRow()); EXPECT_ANY_THROW(grid.getDeltaRow());
// set too small domain // set too small domain
d = 0; d = 0;
CHECK_THROWS(grid.setDomain(d)); EXPECT_ANY_THROW(grid.setDomain(d));
d = -2; d = -2;
CHECK_THROWS(grid.setDomain(d)); EXPECT_ANY_THROW(grid.setDomain(d));
} }
} }
TEST_CASE("2D Grid64 quadratic") { GRID_TEST(Grid64Quadratic) {
int rc = 12; int rc = 12;
Grid64 grid(rc, rc); Grid64 grid(rc, rc);
SUBCASE("correct construction") { {
CHECK_EQ(grid.getDim(), 2); EXPECT_EQ(grid.getDim(), 2);
CHECK_THROWS(grid.getLength()); EXPECT_ANY_THROW(grid.getLength());
CHECK_EQ(grid.getCol(), rc); EXPECT_EQ(grid.getCol(), rc);
CHECK_EQ(grid.getRow(), rc); EXPECT_EQ(grid.getRow(), rc);
CHECK_EQ(grid.getConcentrations().rows(), rc); EXPECT_EQ(grid.getConcentrations().rows(), rc);
CHECK_EQ(grid.getConcentrations().cols(), rc); EXPECT_EQ(grid.getConcentrations().cols(), rc);
CHECK_THROWS(grid.getAlpha()); EXPECT_ANY_THROW(grid.getAlpha());
CHECK_EQ(grid.getAlphaX().rows(), rc); EXPECT_EQ(grid.getAlphaX().rows(), rc);
CHECK_EQ(grid.getAlphaX().cols(), rc); EXPECT_EQ(grid.getAlphaX().cols(), rc);
CHECK_EQ(grid.getAlphaY().rows(), rc); EXPECT_EQ(grid.getAlphaY().rows(), rc);
CHECK_EQ(grid.getAlphaY().cols(), rc); EXPECT_EQ(grid.getAlphaY().cols(), rc);
CHECK_EQ(grid.getDeltaRow(), 1); EXPECT_EQ(grid.getDeltaRow(), 1);
CHECK_EQ(grid.getDeltaCol(), 1); EXPECT_EQ(grid.getDeltaCol(), 1);
} }
SUBCASE("setting concentrations") { {
// correct concentrations matrix // correct concentrations matrix
MatrixXd concentrations = MatrixXd::Constant(rc, rc, 2); MatrixXd concentrations = MatrixXd::Constant(rc, rc, 2);
CHECK_NOTHROW(grid.setConcentrations(concentrations)); EXPECT_NO_THROW(grid.setConcentrations(concentrations));
// false concentrations matrix // false concentrations matrix
MatrixXd wConcentrations = MatrixXd::Constant(rc, rc + 3, 1); MatrixXd wConcentrations = MatrixXd::Constant(rc, rc + 3, 1);
CHECK_THROWS(grid.setConcentrations(wConcentrations)); EXPECT_ANY_THROW(grid.setConcentrations(wConcentrations));
wConcentrations = MatrixXd::Constant(rc + 3, rc, 4); wConcentrations = MatrixXd::Constant(rc + 3, rc, 4);
CHECK_THROWS(grid.setConcentrations(wConcentrations)); EXPECT_ANY_THROW(grid.setConcentrations(wConcentrations));
wConcentrations = MatrixXd::Constant(rc + 2, rc + 4, 6); wConcentrations = MatrixXd::Constant(rc + 2, rc + 4, 6);
CHECK_THROWS(grid.setConcentrations(wConcentrations)); EXPECT_ANY_THROW(grid.setConcentrations(wConcentrations));
} }
SUBCASE("setting alphas") { {
// correct alpha matrices // correct alpha matrices
MatrixXd alphax = MatrixXd::Constant(rc, rc, 2); MatrixXd alphax = MatrixXd::Constant(rc, rc, 2);
MatrixXd alphay = MatrixXd::Constant(rc, rc, 4); MatrixXd alphay = MatrixXd::Constant(rc, rc, 4);
CHECK_NOTHROW(grid.setAlpha(alphax, alphay)); EXPECT_NO_THROW(grid.setAlpha(alphax, alphay));
CHECK_THROWS(grid.setAlpha(alphax)); EXPECT_ANY_THROW(grid.setAlpha(alphax));
grid.setAlpha(alphax, alphay); grid.setAlpha(alphax, alphay);
CHECK_EQ(grid.getAlphaX(), alphax); EXPECT_EQ(grid.getAlphaX(), alphax);
CHECK_EQ(grid.getAlphaY(), alphay); EXPECT_EQ(grid.getAlphaY(), alphay);
CHECK_THROWS(grid.getAlpha()); EXPECT_ANY_THROW(grid.getAlpha());
// false alpha matrices // false alpha matrices
alphax = MatrixXd::Constant(rc + 3, rc + 1, 3); alphax = MatrixXd::Constant(rc + 3, rc + 1, 3);
CHECK_THROWS(grid.setAlpha(alphax, alphay)); EXPECT_ANY_THROW(grid.setAlpha(alphax, alphay));
alphay = MatrixXd::Constant(rc + 2, rc + 1, 3); alphay = MatrixXd::Constant(rc + 2, rc + 1, 3);
CHECK_THROWS(grid.setAlpha(alphax, alphay)); EXPECT_ANY_THROW(grid.setAlpha(alphax, alphay));
} }
SUBCASE("setting domain") { {
int dr = 8; int dr = 8;
int dc = 9; int dc = 9;
// set 1D domain // set 1D domain
CHECK_THROWS(grid.setDomain(dr)); EXPECT_ANY_THROW(grid.setDomain(dr));
// set 2D domain // set 2D domain
CHECK_NOTHROW(grid.setDomain(dr, dc)); EXPECT_NO_THROW(grid.setDomain(dr, dc));
grid.setDomain(dr, dc); grid.setDomain(dr, dc);
CHECK_EQ(grid.getDeltaCol(), double(dc) / double(rc)); EXPECT_DOUBLE_EQ(grid.getDeltaCol(), double(dc) / double(rc));
CHECK_EQ(grid.getDeltaRow(), double(dr) / double(rc)); EXPECT_DOUBLE_EQ(grid.getDeltaRow(), double(dr) / double(rc));
// set too small domain // set too small domain
dr = 0; dr = 0;
CHECK_THROWS(grid.setDomain(dr, dc)); EXPECT_ANY_THROW(grid.setDomain(dr, dc));
dr = 8; dr = 8;
dc = 0; dc = 0;
CHECK_THROWS(grid.setDomain(dr, dc)); EXPECT_ANY_THROW(grid.setDomain(dr, dc));
dr = -2; dr = -2;
CHECK_THROWS(grid.setDomain(dr, dc)); EXPECT_ANY_THROW(grid.setDomain(dr, dc));
} }
} }
TEST_CASE("2D Grid64 non-quadratic") { GRID_TEST(Grid64NonQuadratic) {
int r = 12; int r = 12;
int c = 15; int c = 15;
Grid64 grid(r, c); Grid64 grid(r, c);
SUBCASE("correct construction") { {
CHECK_EQ(grid.getDim(), 2); EXPECT_EQ(grid.getDim(), 2);
CHECK_THROWS(grid.getLength()); EXPECT_ANY_THROW(grid.getLength());
CHECK_EQ(grid.getCol(), c); EXPECT_EQ(grid.getCol(), c);
CHECK_EQ(grid.getRow(), r); EXPECT_EQ(grid.getRow(), r);
CHECK_EQ(grid.getConcentrations().rows(), r); EXPECT_EQ(grid.getConcentrations().rows(), r);
CHECK_EQ(grid.getConcentrations().cols(), c); EXPECT_EQ(grid.getConcentrations().cols(), c);
CHECK_THROWS(grid.getAlpha()); EXPECT_ANY_THROW(grid.getAlpha());
CHECK_EQ(grid.getAlphaX().rows(), r); EXPECT_EQ(grid.getAlphaX().rows(), r);
CHECK_EQ(grid.getAlphaX().cols(), c); EXPECT_EQ(grid.getAlphaX().cols(), c);
CHECK_EQ(grid.getAlphaY().rows(), r); EXPECT_EQ(grid.getAlphaY().rows(), r);
CHECK_EQ(grid.getAlphaY().cols(), c); EXPECT_EQ(grid.getAlphaY().cols(), c);
CHECK_EQ(grid.getDeltaRow(), 1); EXPECT_EQ(grid.getDeltaRow(), 1);
CHECK_EQ(grid.getDeltaCol(), 1); EXPECT_EQ(grid.getDeltaCol(), 1);
} }
SUBCASE("setting concentrations") { {
// correct concentrations matrix // correct concentrations matrix
MatrixXd concentrations = MatrixXd::Constant(r, c, 2); MatrixXd concentrations = MatrixXd::Constant(r, c, 2);
CHECK_NOTHROW(grid.setConcentrations(concentrations)); EXPECT_NO_THROW(grid.setConcentrations(concentrations));
// false concentrations matrix // false concentrations matrix
MatrixXd wConcentrations = MatrixXd::Constant(r, c + 3, 6); MatrixXd wConcentrations = MatrixXd::Constant(r, c + 3, 6);
CHECK_THROWS(grid.setConcentrations(wConcentrations)); EXPECT_ANY_THROW(grid.setConcentrations(wConcentrations));
wConcentrations = MatrixXd::Constant(r + 3, c, 3); wConcentrations = MatrixXd::Constant(r + 3, c, 3);
CHECK_THROWS(grid.setConcentrations(wConcentrations)); EXPECT_ANY_THROW(grid.setConcentrations(wConcentrations));
wConcentrations = MatrixXd::Constant(r + 2, c + 4, 2); wConcentrations = MatrixXd::Constant(r + 2, c + 4, 2);
CHECK_THROWS(grid.setConcentrations(wConcentrations)); EXPECT_ANY_THROW(grid.setConcentrations(wConcentrations));
} }
SUBCASE("setting alphas") { {
// correct alpha matrices // correct alpha matrices
MatrixXd alphax = MatrixXd::Constant(r, c, 2); MatrixXd alphax = MatrixXd::Constant(r, c, 2);
MatrixXd alphay = MatrixXd::Constant(r, c, 4); MatrixXd alphay = MatrixXd::Constant(r, c, 4);
CHECK_NOTHROW(grid.setAlpha(alphax, alphay)); EXPECT_NO_THROW(grid.setAlpha(alphax, alphay));
CHECK_THROWS(grid.setAlpha(alphax)); EXPECT_ANY_THROW(grid.setAlpha(alphax));
grid.setAlpha(alphax, alphay); grid.setAlpha(alphax, alphay);
CHECK_EQ(grid.getAlphaX(), alphax); EXPECT_EQ(grid.getAlphaX(), alphax);
CHECK_EQ(grid.getAlphaY(), alphay); EXPECT_EQ(grid.getAlphaY(), alphay);
CHECK_THROWS(grid.getAlpha()); EXPECT_ANY_THROW(grid.getAlpha());
// false alpha matrices // false alpha matrices
alphax = MatrixXd::Constant(r + 3, c + 1, 3); alphax = MatrixXd::Constant(r + 3, c + 1, 3);
CHECK_THROWS(grid.setAlpha(alphax, alphay)); EXPECT_ANY_THROW(grid.setAlpha(alphax, alphay));
alphay = MatrixXd::Constant(r + 2, c + 1, 5); alphay = MatrixXd::Constant(r + 2, c + 1, 5);
CHECK_THROWS(grid.setAlpha(alphax, alphay)); EXPECT_ANY_THROW(grid.setAlpha(alphax, alphay));
} }
SUBCASE("setting domain") { {
int dr = 8; int dr = 8;
int dc = 9; int dc = 9;
// set 1D domain // set 1D domain
CHECK_THROWS(grid.setDomain(dr)); EXPECT_ANY_THROW(grid.setDomain(dr));
// set 2D domain // set 2D domain
CHECK_NOTHROW(grid.setDomain(dr, dc)); EXPECT_NO_THROW(grid.setDomain(dr, dc));
grid.setDomain(dr, dc); grid.setDomain(dr, dc);
CHECK_EQ(grid.getDeltaCol(), double(dc) / double(c)); EXPECT_DOUBLE_EQ(grid.getDeltaCol(), double(dc) / double(c));
CHECK_EQ(grid.getDeltaRow(), double(dr) / double(r)); EXPECT_DOUBLE_EQ(grid.getDeltaRow(), double(dr) / double(r));
// set too small domain // set too small domain
dr = 0; dr = 0;
CHECK_THROWS(grid.setDomain(dr, dc)); EXPECT_ANY_THROW(grid.setDomain(dr, dc));
dr = 8; dr = 8;
dc = -1; dc = -1;
CHECK_THROWS(grid.setDomain(dr, dc)); EXPECT_ANY_THROW(grid.setDomain(dr, dc));
dr = -2; dr = -2;
CHECK_THROWS(grid.setDomain(dr, dc)); EXPECT_ANY_THROW(grid.setDomain(dr, dc));
} }
SUBCASE("set concentration from pointer") { {
std::vector<double> concentrations(r * c); std::vector<double> concentrations(r * c);
for (int i = 0; i < r * c; i++) { for (int i = 0; i < r * c; i++) {
@ -261,8 +255,8 @@ TEST_CASE("2D Grid64 non-quadratic") {
grid.setConcentrations(concentrations.data()); grid.setConcentrations(concentrations.data());
CHECK_EQ(grid.getConcentrations()(0, 0), 0); EXPECT_DOUBLE_EQ(grid.getConcentrations()(0, 0), 0);
CHECK_EQ(grid.getConcentrations()(0, 1), 1); EXPECT_DOUBLE_EQ(grid.getConcentrations()(0, 1), 1);
CHECK_EQ(grid.getConcentrations()(1, 0), c); EXPECT_DOUBLE_EQ(grid.getConcentrations()(1, 0), c);
} }
} }

View File

@ -1,14 +1,16 @@
#include "TestUtils.hpp" #include "TestUtils.hpp"
#include <gtest/gtest.h>
#include <stdexcept>
#include <tug/Simulation.hpp> #include <tug/Simulation.hpp>
#include <Eigen/src/Core/Matrix.h> #include <Eigen/src/Core/Matrix.h>
#include <doctest/doctest.h>
#include <stdio.h>
#include <string> #include <string>
// include the configured header file // include the configured header file
#include <testSimulation.hpp> #include <testSimulation.hpp>
#define DIFFUSION_TEST(x) TEST(Diffusion, x)
using namespace Eigen; using namespace Eigen;
using namespace std; using namespace std;
using namespace tug; using namespace tug;
@ -51,7 +53,7 @@ Grid64 setupSimulation(double timestep, int iterations) {
constexpr double timestep = 0.001; constexpr double timestep = 0.001;
constexpr double iterations = 7000; constexpr double iterations = 7000;
TEST_CASE("equality to reference matrix with FTCS") { DIFFUSION_TEST(EqualityFTCS) {
// set string from the header file // set string from the header file
string test_path = testSimulationCSVDir; string test_path = testSimulationCSVDir;
MatrixXd reference = CSV2Eigen(test_path); MatrixXd reference = CSV2Eigen(test_path);
@ -69,10 +71,10 @@ TEST_CASE("equality to reference matrix with FTCS") {
sim.run(); sim.run();
cout << endl; cout << endl;
CHECK(checkSimilarity(reference, grid.getConcentrations(), 0.1) == true); EXPECT_TRUE(checkSimilarity(reference, grid.getConcentrations(), 0.1));
} }
TEST_CASE("equality to reference matrix with BTCS") { DIFFUSION_TEST(EqualityBTCS) {
// set string from the header file // set string from the header file
string test_path = testSimulationCSVDir; string test_path = testSimulationCSVDir;
MatrixXd reference = CSV2Eigen(test_path); MatrixXd reference = CSV2Eigen(test_path);
@ -89,39 +91,35 @@ TEST_CASE("equality to reference matrix with BTCS") {
sim.run(); sim.run();
cout << endl; cout << endl;
CHECK(checkSimilarityV2(reference, grid.getConcentrations(), 0.01) == true); EXPECT_TRUE(checkSimilarityV2(reference, grid.getConcentrations(), 0.01));
} }
TEST_CASE("Initialize environment") { DIFFUSION_TEST(InitializeEnvironment) {
int rc = 12; int rc = 12;
Grid64 grid(rc, rc); Grid64 grid(rc, rc);
Boundary boundary(grid); Boundary boundary(grid);
CHECK_NOTHROW(Simulation sim(grid, boundary)); EXPECT_NO_THROW(Simulation sim(grid, boundary));
} }
TEST_CASE("Simulation environment") { DIFFUSION_TEST(SimulationEnvironment) {
int rc = 12; int rc = 12;
Grid64 grid(rc, rc); Grid64 grid(rc, rc);
Boundary boundary(grid); Boundary boundary(grid);
Simulation<double, tug::FTCS_APPROACH> sim(grid, boundary); Simulation<double, tug::FTCS_APPROACH> sim(grid, boundary);
SUBCASE("default paremeters") { CHECK_EQ(sim.getIterations(), -1); } EXPECT_EQ(sim.getIterations(), -1);
SUBCASE("set iterations") { EXPECT_NO_THROW(sim.setIterations(2000));
CHECK_NOTHROW(sim.setIterations(2000)); EXPECT_EQ(sim.getIterations(), 2000);
CHECK_EQ(sim.getIterations(), 2000); EXPECT_THROW(sim.setIterations(-300), std::invalid_argument);
CHECK_THROWS(sim.setIterations(-300));
EXPECT_NO_THROW(sim.setTimestep(0.1));
EXPECT_DOUBLE_EQ(sim.getTimestep(), 0.1);
EXPECT_THROW(sim.setTimestep(-0.3), std::invalid_argument);
} }
SUBCASE("set timestep") { DIFFUSION_TEST(ClosedBoundaries) {
CHECK_NOTHROW(sim.setTimestep(0.1));
CHECK_EQ(sim.getTimestep(), 0.1);
CHECK_THROWS(sim.setTimestep(-0.3));
}
}
TEST_CASE("Closed Boundaries - no change expected") {
constexpr std::uint32_t nrows = 5; constexpr std::uint32_t nrows = 5;
constexpr std::uint32_t ncols = 5; constexpr std::uint32_t ncols = 5;
@ -148,11 +146,10 @@ TEST_CASE("Closed Boundaries - no change expected") {
MatrixXd input_values(concentrations); MatrixXd input_values(concentrations);
sim.run(); sim.run();
CHECK(checkSimilarityV2(input_values, grid.getConcentrations(), 1E-12) == EXPECT_TRUE(checkSimilarityV2(input_values, grid.getConcentrations(), 1E-12));
true);
} }
TEST_CASE("Constant inner cell - 'absorbing' concentration") { DIFFUSION_TEST(ConstantInnerCell) {
constexpr std::uint32_t nrows = 5; constexpr std::uint32_t nrows = 5;
constexpr std::uint32_t ncols = 5; constexpr std::uint32_t ncols = 5;
@ -176,12 +173,10 @@ TEST_CASE("Constant inner cell - 'absorbing' concentration") {
MatrixXd input_values(concentrations); MatrixXd input_values(concentrations);
sim.run(); sim.run();
CHECK(grid.getConcentrations()(2, 2) == 0); EXPECT_DOUBLE_EQ(grid.getConcentrations()(2, 2), 0);
CHECK(grid.getConcentrations().sum() < input_values.sum()); EXPECT_LT(grid.getConcentrations().sum(), input_values.sum());
const bool greater_one = (grid.getConcentrations().array() > 1.0).any(); EXPECT_FALSE((grid.getConcentrations().array() > 1.0).any());
CHECK(greater_one == false);
const bool less_zero = (grid.getConcentrations().array() < 0.0).any(); EXPECT_FALSE((grid.getConcentrations().array() < 0.0).any());
CHECK(less_zero == false);
} }