Skip to content

Commit 08bff7b

Browse files
committed
Removing MD5 checkusum based verification
1 parent 0305eda commit 08bff7b

4 files changed

Lines changed: 122 additions & 92 deletions

File tree

docs/installation.rst

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ libraries are available to you:
2121
* `GZIP <https://www.gnu.org/software/gzip/>`_ (gzip data compression)
2222
* `LZMA <https://7-zip.org/>`_ (lzma data compression)
2323
* `CPPUnit <https://sourceforge.net/projects/cppunit/>`_ (unit testing)
24-
* `OpenSSL <https://www.openssl.org/>`_ (unit testing; MD5 checksums)
2524

2625
.. note::
2726
* The instructions covered in this guide assume you are running a
@@ -33,8 +32,7 @@ libraries are available to you:
3332
To ensure that all the packages are installed, one can run the following::
3433

3534
sudo apt install build-essential cmake libtclap-dev libboost-all-dev \
36-
pkg-config libcppunit-dev libeigen3-dev liblzma-dev zlib1g-dev libbz2-dev \
37-
libssl-dev
35+
pkg-config libcppunit-dev libeigen3-dev liblzma-dev zlib1g-dev libbz2-dev
3836

3937
Standard compilation
4038
--------------------

src/test/CMakeLists.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
#*************************************************************************/
2020

2121
pkg_check_modules(CPPUNIT REQUIRED IMPORTED_TARGET cppunit)
22-
pkg_check_modules(CRYPTO REQUIRED IMPORTED_TARGET libcrypto)
23-
2422
add_library(unittest STATIC unittest.cpp)
2523
target_compile_features(unittest PUBLIC cxx_std_17)
2624

@@ -63,7 +61,6 @@ foreach(testexec ${EXECUTABLES})
6361
unittest
6462
den2objsources
6563
PkgConfig::CPPUNIT
66-
PkgConfig::CRYPTO
6764
)
6865

6966
add_test(NAME ${testexec} COMMAND ${testexec})

src/test/test_file_creation.cpp

Lines changed: 105 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -29,106 +29,134 @@ void TestFileCreation::tearDown() {
2929
}
3030

3131
void TestFileCreation::test_ply_file() {
32-
// set number of threads to 1
33-
omp_set_num_threads(1);
34-
35-
// read scalar field
36-
ScalarField sf("co_2pi_x.cub", ScalarFieldInputFileType::SFF_CUB);
37-
sf.read();
38-
39-
// perform marching cubes algorithm
40-
IsoSurface is(&sf);
41-
is.marching_cubes(0.01);
42-
43-
// construct mesh
44-
IsoSurfaceMesh ism(&sf, &is);
45-
ism.construct_mesh(true);
32+
const auto ref = this->generate_mesh();
33+
this->assert_ply_shape("test.ply", ref);
34+
}
4635

47-
// create file
48-
ism.write_to_file("test.ply", "co molecule 2pi_x orbital test", "molecule");
36+
void TestFileCreation::test_stl_file() {
37+
const auto ref = this->generate_mesh();
38+
this->assert_stl_shape("test.stl", ref);
39+
}
4940

50-
// test md5sum
51-
CPPUNIT_ASSERT_EQUAL(this->md5("test.ply"), std::string("ec143f6ebf9b72761803c3b091f54bf3"));
41+
void TestFileCreation::test_obj_file() {
42+
const auto ref = this->generate_mesh();
43+
this->assert_obj_shape("test.obj", ref);
5244
}
5345

54-
void TestFileCreation::test_stl_file() {
46+
TestFileCreation::MeshReference TestFileCreation::generate_mesh() const {
5547
// set number of threads to 1
5648
omp_set_num_threads(1);
5749

5850
// read scalar field
5951
ScalarField sf("co_2pi_x.cub", ScalarFieldInputFileType::SFF_CUB);
6052
sf.read();
61-
53+
6254
// perform marching cubes algorithm
6355
IsoSurface is(&sf);
6456
is.marching_cubes(0.01);
65-
57+
6658
// construct mesh
6759
IsoSurfaceMesh ism(&sf, &is);
6860
ism.construct_mesh(true);
6961

70-
// create file
62+
// create files for all supported output formats
63+
ism.write_to_file("test.ply", "co molecule 2pi_x orbital test", "molecule");
7164
ism.write_to_file("test.stl", "co molecule 2pi_x orbital test", "molecule");
65+
ism.write_to_file("test.obj", "co molecule 2pi_x orbital test", "molecule");
7266

73-
// test md5sum
74-
CPPUNIT_ASSERT_EQUAL(this->md5("test.stl"), std::string("c2194ba639caf5092654862bb9f93298"));
67+
return {
68+
ism.get_vertices().size(),
69+
ism.get_normals().size(),
70+
ism.get_texcoords().size() / 6
71+
};
7572
}
7673

77-
void TestFileCreation::test_obj_file() {
78-
// set number of threads to 1
79-
omp_set_num_threads(1);
74+
void TestFileCreation::assert_obj_shape(const std::string& filename, const MeshReference& ref) const {
75+
CPPUNIT_ASSERT(std::filesystem::exists(filename));
76+
77+
std::ifstream infile(filename);
78+
CPPUNIT_ASSERT(infile.good());
79+
80+
std::string line;
81+
size_t vertex_lines = 0;
82+
size_t normal_lines = 0;
83+
size_t face_lines = 0;
84+
85+
while(std::getline(infile, line)) {
86+
if(line.rfind("v ", 0) == 0) {
87+
vertex_lines++;
88+
} else if(line.rfind("vn ", 0) == 0) {
89+
normal_lines++;
90+
} else if(line.rfind("f ", 0) == 0) {
91+
face_lines++;
92+
}
93+
}
8094

81-
// read scalar field
82-
ScalarField sf("co_2pi_x.cub", ScalarFieldInputFileType::SFF_CUB);
83-
sf.read();
84-
85-
// perform marching cubes algorithm
86-
IsoSurface is(&sf);
87-
is.marching_cubes(0.01);
88-
89-
// construct mesh
90-
IsoSurfaceMesh ism(&sf, &is);
91-
ism.construct_mesh(true);
95+
CPPUNIT_ASSERT_EQUAL(ref.vertices, vertex_lines);
96+
CPPUNIT_ASSERT_EQUAL(ref.normals, normal_lines);
97+
CPPUNIT_ASSERT_EQUAL(ref.triangles, face_lines);
98+
}
9299

93-
// create file
94-
ism.write_to_file("test.obj", "co molecule 2pi_x orbital test", "molecule");
100+
void TestFileCreation::assert_ply_shape(const std::string& filename, const MeshReference& ref) const {
101+
CPPUNIT_ASSERT(std::filesystem::exists(filename));
102+
103+
std::ifstream infile(filename, std::ios::binary);
104+
CPPUNIT_ASSERT(infile.good());
105+
106+
std::string line;
107+
size_t header_size = 0;
108+
size_t header_vertices = 0;
109+
size_t header_faces = 0;
110+
bool seen_ply = false;
111+
bool seen_binary_format = false;
112+
113+
while(std::getline(infile, line)) {
114+
header_size += line.size() + 1;
115+
116+
if(line == "ply") {
117+
seen_ply = true;
118+
}
119+
if(line == "format binary_little_endian 1.0" || line == "format binary_big_endian 1.0") {
120+
seen_binary_format = true;
121+
}
122+
if(line.rfind("element vertex ", 0) == 0) {
123+
header_vertices = std::stoul(line.substr(15));
124+
}
125+
if(line.rfind("element face ", 0) == 0) {
126+
header_faces = std::stoul(line.substr(13));
127+
}
128+
if(line == "end_header") {
129+
break;
130+
}
131+
}
132+
133+
CPPUNIT_ASSERT(seen_ply);
134+
CPPUNIT_ASSERT(seen_binary_format);
135+
CPPUNIT_ASSERT_EQUAL(ref.vertices, header_vertices);
136+
CPPUNIT_ASSERT_EQUAL(ref.triangles, header_faces);
95137

96-
// test md5sum
97-
CPPUNIT_ASSERT_EQUAL(this->md5("test.obj"), std::string("e2b3e09f9c010dac99a7bc0137c187ec"));
138+
const size_t expected_binary_size =
139+
ref.vertices * (6 * sizeof(float)) +
140+
ref.triangles * (sizeof(uint8_t) + 3 * sizeof(unsigned int));
141+
142+
CPPUNIT_ASSERT_EQUAL(header_size + expected_binary_size, (size_t)std::filesystem::file_size(filename));
98143
}
99144

100-
/**
101-
* @brief Calculate MD5 checksum of a file
102-
*
103-
* @param[in] name Path to the file
104-
*
105-
* @return 32 byte string containing md5 checksum
106-
*/
107-
std::string TestFileCreation::md5(const std::string& filename) {
108-
// read the file
109-
std::ifstream mfile(filename, std::ios::binary | std::ios::ate);
110-
std::streamsize size = mfile.tellg();
111-
mfile.seekg(0, std::ios::beg);
112-
char buffer[size];
113-
mfile.read(buffer, size);
114-
mfile.close();
115-
116-
// output variable for hash
117-
unsigned char hash[MD5_DIGEST_LENGTH];
118-
119-
// calculate the md5 hash
120-
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
121-
EVP_MD_CTX_init(ctx);
122-
const EVP_MD *md_type = EVP_md5();
123-
EVP_DigestInit_ex(ctx, md_type, NULL);
124-
EVP_DigestUpdate(ctx, buffer, size);
125-
EVP_DigestFinal_ex(ctx, hash, NULL);
126-
EVP_MD_CTX_destroy(ctx);
127-
128-
// output as a 32-byte hex-string
129-
std::stringstream ss;
130-
for(int i = 0; i < MD5_DIGEST_LENGTH; i++){
131-
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>( hash[i] );
132-
}
133-
return ss.str();
134-
}
145+
void TestFileCreation::assert_stl_shape(const std::string& filename, const MeshReference& ref) const {
146+
CPPUNIT_ASSERT(std::filesystem::exists(filename));
147+
148+
std::ifstream infile(filename, std::ios::binary);
149+
CPPUNIT_ASSERT(infile.good());
150+
151+
// skip header
152+
infile.seekg(80, std::ios::beg);
153+
154+
uint32_t triangle_count = 0;
155+
infile.read(reinterpret_cast<char*>(&triangle_count), sizeof(uint32_t));
156+
CPPUNIT_ASSERT(infile.good());
157+
158+
CPPUNIT_ASSERT_EQUAL(static_cast<uint32_t>(ref.triangles), triangle_count);
159+
160+
const size_t expected_size = 80 + sizeof(uint32_t) + ref.triangles * (12 * sizeof(float) + sizeof(uint16_t));
161+
CPPUNIT_ASSERT_EQUAL(expected_size, (size_t)std::filesystem::file_size(filename));
162+
}

src/test/test_file_creation.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,21 @@
2323

2424
#include <cppunit/extensions/HelperMacros.h>
2525

26-
// we need these for the MD5 checksums
27-
#include <iomanip>
28-
#include <openssl/md5.h>
29-
#include <openssl/evp.h>
26+
#include <cstdint>
27+
#include <filesystem>
28+
#include <string>
3029

3130
#include "scalar_field.h"
3231
#include "isosurface.h"
3332
#include "isosurface_mesh.h"
3433

3534
/**
3635
* Test that verifies file creation (obj, stl and ply)
37-
*
36+
*
3837
* Because the marching cubes algorithm uses OpenMP parallellization, we need
3938
* to set the number of threads to 1 to obtain consistent results. With
4039
* higher number of cores, the results are subject to race conditions, leading
41-
* to different (although not incorrect) results preventing the use of a simple
42-
* MD5 checksum for file validation.
40+
* to different (although not incorrect) results.
4341
*/
4442
class TestFileCreation : public CppUnit::TestFixture {
4543
CPPUNIT_TEST_SUITE( TestFileCreation );
@@ -56,7 +54,16 @@ class TestFileCreation : public CppUnit::TestFixture {
5654
void tearDown();
5755

5856
private:
59-
std::string md5(const std::string &str);
57+
struct MeshReference {
58+
size_t vertices;
59+
size_t normals;
60+
size_t triangles;
61+
};
62+
63+
MeshReference generate_mesh() const;
64+
void assert_obj_shape(const std::string& filename, const MeshReference& ref) const;
65+
void assert_ply_shape(const std::string& filename, const MeshReference& ref) const;
66+
void assert_stl_shape(const std::string& filename, const MeshReference& ref) const;
6067
};
6168

62-
#endif
69+
#endif

0 commit comments

Comments
 (0)