Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expanding test suite #8

Merged
merged 4 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Build
run: cd build && make -j
- name: Perform unit tests
run: cd build && OMP_NUM_THREADS=1 make test # suppress parallel sections for tests
run: cd build && make test
- name: Perform code coverage
run: |
cd build
Expand Down
3 changes: 2 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ find_package(BZip2 REQUIRED)
find_package(CPPUNIT REQUIRED) # for unit tests
pkg_check_modules(TCLAP tclap REQUIRED)
pkg_check_modules(EIGEN eigen3 REQUIRED)
pkg_check_modules(CRYPTO libcrypto REQUIRED) # for unit tests

# Set include folders
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
Expand Down Expand Up @@ -137,4 +138,4 @@ endif()
###
# Installing
##
install (TARGETS den2obj DESTINATION bin)
install (TARGETS den2obj DESTINATION bin)
4 changes: 2 additions & 2 deletions src/isosurface_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ void IsoSurfaceMesh::write_to_file(const std::string& filename, const std::strin

if(filename.substr(filename.size()-4) == ".obj") {
std::cout << "Writing mesh as Wavefront file (.obj)." << std::endl;
this->write_obj(filename, path.filename().string(), path.filename().string());
this->write_obj(filename, header, name);
} else if(filename.substr(filename.size()-4) == ".ply") {
std::cout << "Writing mesh as Standford Triangle Format file (.ply)." << std::endl;
this->write_ply(filename, path.filename().string(), path.filename().string());
this->write_ply(filename, header, name);
} else if(filename.substr(filename.size()-4) == ".stl") {
std::cout << "Writing mesh as Stereolithography file (.stl)." << std::endl;
this->write_stl(filename);
Expand Down
17 changes: 14 additions & 3 deletions src/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,33 @@ add_library(unittest STATIC unittest.cpp)
# set executables
SET(EXECUTABLES TestIsosurface TestScalarField TestD2OFileFormat)

# remove this test from the list as it takes too long
# only add this test when not using GCOV
if(NOT USE_GCOV)
list(APPEND EXECUTABLES TestGenerator)
endif()

# only add this test when not using GCOV
if(USE_GCOV)
list(APPEND EXECUTABLES TestFileCreation)
endif()

#######################################################
# Add executables
#######################################################
add_executable(TestIsosurface test_isosurface.cpp)
add_executable(TestScalarField test_scalarfield.cpp)
add_executable(TestD2OFileFormat test_d2o_fileformat.cpp)

# remove this test from the list as it takes too long
# only add this test when not using GCOV
if(NOT USE_GCOV)
add_executable(TestGenerator test_generator.cpp)
endif()

# only add this test when not using OpenVDB
if(USE_GCOV)
add_executable(TestFileCreation test_file_creation.cpp)
endif()

#######################################################
# Link mkmsources and other dependencies
#######################################################
Expand All @@ -51,7 +61,7 @@ endif()

# add unpacking of dataset to the test suite
add_test(NAME DatasetSetup COMMAND tar -xvjf dataset.tar.bz2)
add_test(NAME DatasetCleanup COMMAND rm -rvf CHGCAR_* PARCHG_*)
add_test(NAME DatasetCleanup COMMAND rm -rvf CHGCAR_* PARCHG_* *.d2o *.cub)
set_tests_properties(DatasetSetup PROPERTIES FIXTURES_SETUP Dataset)
set_tests_properties(DatasetCleanup PROPERTIES FIXTURES_CLEANUP Dataset)

Expand All @@ -66,6 +76,7 @@ foreach(testexec ${EXECUTABLES})
${LIBLZMA_LIBRARIES}
${ZLIB_LIBRARIES}
${BZIP2_LIBRARIES}
${CRYPTO_LIBRARIES}
-lgcov)
set_target_properties(${testexec} PROPERTIES COMPILE_FLAGS "--coverage")
add_test(NAME ${testexec} COMMAND ${testexec})
Expand Down
134 changes: 134 additions & 0 deletions src/test/test_file_creation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**************************************************************************
* *
* Author: Ivo Filot <i.a.w.filot@tue.nl> *
* *
* DEN2OBJ is free software: *
* you can redistribute it and/or modify it under the terms of the *
* GNU General Public License as published by the Free Software *
* Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* DEN2OBJ is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty *
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see http://www.gnu.org/licenses/. *
* *
**************************************************************************/

#include "test_file_creation.h"

CPPUNIT_TEST_SUITE_REGISTRATION( TestFileCreation );

void TestFileCreation::setUp() {
}

void TestFileCreation::tearDown() {
}

void TestFileCreation::test_ply_file() {
// set number of threads to 1
omp_set_num_threads(1);

// read scalar field
ScalarField sf("co_2pi_x.cub", ScalarFieldInputFileType::SFF_CUB);
sf.read();

// perform marching cubes algorithm
IsoSurface is(&sf);
is.marching_cubes(0.01);

// construct mesh
IsoSurfaceMesh ism(&sf, &is);
ism.construct_mesh(true);

// create file
ism.write_to_file("test.ply", "co molecule 2pi_x orbital test", "molecule");

// test md5sum
CPPUNIT_ASSERT_EQUAL(this->md5("test.ply"), std::string("ec143f6ebf9b72761803c3b091f54bf3"));
}

void TestFileCreation::test_stl_file() {
// set number of threads to 1
omp_set_num_threads(1);

// read scalar field
ScalarField sf("co_2pi_x.cub", ScalarFieldInputFileType::SFF_CUB);
sf.read();

// perform marching cubes algorithm
IsoSurface is(&sf);
is.marching_cubes(0.01);

// construct mesh
IsoSurfaceMesh ism(&sf, &is);
ism.construct_mesh(true);

// create file
ism.write_to_file("test.stl", "co molecule 2pi_x orbital test", "molecule");

// test md5sum
CPPUNIT_ASSERT_EQUAL(this->md5("test.stl"), std::string("c2194ba639caf5092654862bb9f93298"));
}

void TestFileCreation::test_obj_file() {
// set number of threads to 1
omp_set_num_threads(1);

// read scalar field
ScalarField sf("co_2pi_x.cub", ScalarFieldInputFileType::SFF_CUB);
sf.read();

// perform marching cubes algorithm
IsoSurface is(&sf);
is.marching_cubes(0.01);

// construct mesh
IsoSurfaceMesh ism(&sf, &is);
ism.construct_mesh(true);

// create file
ism.write_to_file("test.obj", "co molecule 2pi_x orbital test", "molecule");

// test md5sum
CPPUNIT_ASSERT_EQUAL(this->md5("test.obj"), std::string("e2b3e09f9c010dac99a7bc0137c187ec"));
}

/**
* @brief Calculate MD5 checksum of a file
*
* @param[in] name Path to the file
*
* @return 32 byte string containing md5 checksum
*/
std::string TestFileCreation::md5(const std::string& filename) {
// read the file
std::ifstream mfile(filename, std::ios::binary | std::ios::ate);
std::streamsize size = mfile.tellg();
mfile.seekg(0, std::ios::beg);
char buffer[size];
mfile.read(buffer, size);
mfile.close();

// output variable for hash
unsigned char hash[MD5_DIGEST_LENGTH];

// calculate the md5 hash
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
EVP_MD_CTX_init(ctx);
const EVP_MD *md_type = EVP_md5();
EVP_DigestInit_ex(ctx, md_type, NULL);
EVP_DigestUpdate(ctx, buffer, size);
EVP_DigestFinal_ex(ctx, hash, NULL);
EVP_MD_CTX_destroy(ctx);

// output as a 32-byte hex-string
std::stringstream ss;
for(int i = 0; i < MD5_DIGEST_LENGTH; i++){
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>( hash[i] );
}
return ss.str();
}
62 changes: 62 additions & 0 deletions src/test/test_file_creation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**************************************************************************
* *
* Author: Ivo Filot <i.a.w.filot@tue.nl> *
* *
* DEN2OBJ is free software: *
* you can redistribute it and/or modify it under the terms of the *
* GNU General Public License as published by the Free Software *
* Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* DEN2OBJ is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty *
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see http://www.gnu.org/licenses/. *
* *
**************************************************************************/

#ifndef _TEST_FILE_CREATION
#define _TEST_FILE_CREATION

#include <cppunit/extensions/HelperMacros.h>

// we need these for the MD5 checksums
#include <iomanip>
#include <openssl/md5.h>
#include <openssl/evp.h>

#include "scalar_field.h"
#include "isosurface.h"
#include "isosurface_mesh.h"

/**
* Test that verifies file creation (obj, stl and ply)
*
* Because the marching cubes algorithm uses OpenMP parallellization, we need
* to set the number of threads to 1 to obtain consistent results. With
* higher number of cores, the results are subject to race conditions, leading
* to different (although not incorrect) results preventing the use of a simple
* MD5 checksum for file validation.
*/
class TestFileCreation : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE( TestFileCreation );
CPPUNIT_TEST( test_ply_file );
CPPUNIT_TEST( test_stl_file );
CPPUNIT_TEST( test_obj_file );
CPPUNIT_TEST_SUITE_END();

public:
void setUp();
void test_ply_file();
void test_stl_file();
void test_obj_file();
void tearDown();

private:
std::string md5(const std::string &str);
};

#endif
7 changes: 6 additions & 1 deletion src/test/test_scalarfield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void TestScalarField::setUp() {
void TestScalarField::tearDown() {
}

void TestScalarField::testReading() {
void TestScalarField::testReadingCHGCAR() {
// create scalar field
ScalarField sf("CHGCAR_CH4", ScalarFieldInputFileType::SFF_CHGCAR);
CPPUNIT_ASSERT_EQUAL( (uint)0, sf.get_size() );
Expand Down Expand Up @@ -90,3 +90,8 @@ void TestScalarField::testReading() {
sf.get_value_interp(0.0,0.0,10.0),
1e-12);
}

void TestScalarField::testReadingCUB() {
// test reading sf file
ScalarField sf("co_2pi_x.cub", ScalarFieldInputFileType::SFF_CUB);
}
7 changes: 4 additions & 3 deletions src/test/test_scalarfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@
class TestScalarField : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( TestScalarField );
CPPUNIT_TEST( testReading );
CPPUNIT_TEST( testReadingCHGCAR );
CPPUNIT_TEST( testReadingCUB );
CPPUNIT_TEST_SUITE_END();

public:
void setUp();
void tearDown();

void testReading();
void testD2OFileFormat();
void testReadingCHGCAR();
void testReadingCUB();

private:
};
Expand Down
5 changes: 5 additions & 0 deletions src/test/testinput/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CHGCAR*
PARCHG*
LOCPOT*
*.d2o
*.cub
Binary file removed src/test/testinput/ch4.d2o
Binary file not shown.
Binary file modified src/test/testinput/dataset.tar.bz2
Binary file not shown.