Tag Parser
12.5.3
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
Toggle main menu visibility
Loading...
Searching...
No Matches
tests
testfilecheck.cpp
Go to the documentation of this file.
1
#include "
../caseinsensitivecomparer.h
"
2
3
#include <c++utilities/conversion/stringbuilder.h>
4
#include <c++utilities/tests/testutils.h>
5
6
#include <cppunit/TestFixture.h>
7
#include <cppunit/extensions/HelperMacros.h>
8
9
#include <openssl/evp.h>
10
#include <openssl/sha.h>
11
12
#include <fstream>
13
14
using namespace
std;
15
using namespace
CppUtilities
;
16
using namespace
TagParser
;
17
using namespace
CPPUNIT_NS;
18
22
struct
Sha256Checksum
{
23
char
checksum
[65];
24
bool
operator==
(
const
Sha256Checksum
&other)
const
;
25
};
26
30
bool
Sha256Checksum::operator==
(
const
Sha256Checksum
&other)
const
31
{
32
for
(
const
char
*i1 =
checksum
, *i2 = other.
checksum
, *end =
checksum
+
sizeof
(
checksum
); i1 != end; ++i1, ++i2) {
33
if
(
CaseInsensitiveCharComparer::toLower
(
static_cast<
unsigned
char
>
(*i1))
34
!=
CaseInsensitiveCharComparer::toLower
(
static_cast<
unsigned
char
>
(*i2))) {
35
return
false
;
36
}
37
}
38
return
true
;
39
}
40
41
ostream &
operator<<
(ostream &os,
const
Sha256Checksum
&checksum)
42
{
43
os << checksum.
checksum
;
44
return
os;
45
}
46
51
struct
TestFile
{
52
const
char
*
path
;
53
Sha256Checksum
expectedSha256sum
;
54
Sha256Checksum
computeSha256Sum
()
const
;
55
void
verifyChecksum
()
const
;
56
}
const
testFiles
[] = {
57
{
"matroska_wave1/logo3_256x256.png"
, {
"810b9172607e281d9a3969018c7d6521de240cc3688fecf598444e666aa6b4dc"
} },
58
{
"matroska_wave1/test1.mkv"
, {
"0996a309ff2095910b9d30d5253b044d637154297ddf7d0bda7f3adedf5addc1"
} },
59
{
"matroska_wave1/test2.mkv"
, {
"5b53d306e56f9bda6e80c3fbd9f3ccd20cc885770449d1fc0b5bec35c71d61e2"
} },
60
{
"matroska_wave1/test3.mkv"
, {
"1722b0d93a6ef1a14dd513bd031cd5901c233b45aa3e3c87be0b0d7348d7d1b5"
} },
61
{
"matroska_wave1/test4.mkv"
, {
"43df750a2a01a37949791b717051b41522081a266b71d113be4b713063843699"
} },
62
{
"matroska_wave1/test5.mkv"
, {
"92acdc33bb0b5d7a4d9b0d6ca792230a78c786a30179dc9999cee41c28642842"
} },
63
{
"matroska_wave1/test6.mkv"
, {
"7cad84b434116e023d340dd584ac833b93f03fb1bd7ea2727fa45de50af0abb9"
} },
64
{
"matroska_wave1/test7.mkv"
, {
"95b21c92ad5a4fe00914ff5009e2a64f12fd4c5fb9cb1c3c888ab50bf0ffe483"
} },
65
{
"matroska_wave1/test8.mkv"
, {
"9dddcd1550b814dae44d62e2b9f27c0eca31d5e190df2220cbf7492e3d6c63da"
} },
66
{
"mtx-test-data/mkv/handbrake-chapters-2.mkv"
, {
"eccc55f3b59a77086b3ffb914525d312c7886eae34e3933352dea2f6f6a1974c"
} },
67
{
"mtx-test-data/mkv/tags.mkv"
, {
"4330019afc3d846600c1ded38158fcac081297f4e56c749251c236f4871e0287"
} },
68
{
"mkv/nested-tags.xml"
, {
"85cfcc94920f114e52fd1aa3df24706cd2710626e065a2c8c55dd209ec8dc8ce"
} },
69
{
"mp4/test1.m4a"
, {
"4f16e0a22525bd13ba859431406d7f5991e0b4f155c51e10e5f32b0c97034b36"
} },
70
{
"mp4/android-8.1-camera-recoding.mp4"
, {
"e7c5624872de1c9c2fb52dd954cef53adc337a6ba88342ff516dde5d4ef374dc"
} },
71
{
"mtx-test-data/aac/he-aacv2-ps.m4a"
, {
"be54be0ae45b0184583ced8a84a881a1652a449feb7f6a917e11f60efabb68ac"
} },
72
{
"mtx-test-data/alac/othertest-itunes.m4a"
, {
"5e9c64cde00902211533fbe38aaa67ef5f79a945e1d717951b78b4bbf9ff84e8"
} },
73
{
"mtx-test-data/mp3/id3-tag-and-xing-header.mp3"
, {
"4a9187b05dc74d32e5a3de53494fde9db8c6c25d46082f86de6f424ad28daacf"
} },
74
{
"mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"
, {
"30c915d5656de049d66fd70b0966a33faf038af42365a2bb973e5c2fc0ba2038"
} },
75
{
"mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"
, {
"fbf929bf8300fc6e53c5c5b7fde4ed2a427fef2d4fd093511c672083039abbf1"
} },
76
{
"mtx-test-data/mp4/dash/dragon-age-inquisition-H1LkM6IVlm4-video.mp4"
, {
"864891f4510f3fa9c49c19e671171cec08ceb331362cf7161419b957be090d47"
} },
77
{
"mtx-test-data/ogg/qt4dance_medium.ogg"
, {
"0b5429da9713be171c6ae0da69621261e8d5ddc9db3da872e5ade1a1c883decd"
} },
78
{
"mtx-test-data/opus/v-opus.ogg"
, {
"e12adece4dbcccf2471b61c3ebd7c6576dee351d85809ab6f01d6f324d65b417"
} },
79
{
"misc/multiple_id3v2_4_values.mp3"
, {
"da012a41213cdc49b2afe1457625d8baced1a64e2351f17b520bf82c6bfe4e03"
} },
80
{
"ogg/noise-without-cover.opus"
, {
"ff578894c0c47aed4cc41ae94dee2886fe2c556593e44f731135f47bca870464"
} },
81
{
"ogg/noise-broken-segment-termination.opus"
, {
"12835cf12b5b9fa70c239ae05e9d5bb768e715a2d61ef6301ed4af673088de45"
} },
82
{
"ogg/example-cover.png"
, {
"897e1a2d0cfb79c1fe5068108bb34610c3758bd0b9a7e90c1702c4e6972e0801"
} },
83
};
84
86
struct
EvpMdCtx {
87
EvpMdCtx()
88
: handle(EVP_MD_CTX_new())
89
{
90
}
91
~EvpMdCtx()
92
{
93
if
(handle) {
94
EVP_MD_CTX_free(handle);
95
}
96
}
97
EVP_MD_CTX *handle;
98
};
100
104
Sha256Checksum
TestFile::computeSha256Sum
()
const
105
{
106
// init sha256 hashing
107
const
auto
mdctx = EvpMdCtx();
108
if
(!mdctx.handle) {
109
throw
std::runtime_error(
"Unable to create EVP context."
);
110
}
111
if
(EVP_DigestInit_ex(mdctx.handle, EVP_sha256(),
nullptr
) != 1) {
112
throw
std::runtime_error(
"Unable to init SHA256-EVP context."
);
113
}
114
115
// read and hash file
116
{
117
ifstream file;
118
file.exceptions(ios_base::eofbit | ios_base::failbit | ios_base::badbit);
119
file.open(testFilePath(
path
), ios_base::in | ios_base::binary);
120
121
char
readBuffer[4096];
122
try
{
123
for
(;;) {
124
file.read(readBuffer,
sizeof
(readBuffer));
125
if
(EVP_DigestUpdate(mdctx.handle, readBuffer,
static_cast<
std::size_t
>
(file.gcount())) != 1) {
126
throw
std::runtime_error(
"Unable to update SHA256-EVP."
);
127
}
128
}
129
}
catch
(
const
std::ios_base::failure &) {
130
if
(file.eof() && !file.bad()) {
131
if
(EVP_DigestUpdate(mdctx.handle, readBuffer,
static_cast<
std::size_t
>
(file.gcount())) != 1) {
132
throw
std::runtime_error(
"Unable to update SHA256-EVP."
);
133
}
134
}
else
{
135
throw
;
136
}
137
}
138
}
139
140
// compute final hash
141
unsigned
char
hash[SHA256_DIGEST_LENGTH];
142
auto
length =
static_cast<
unsigned
int
>
(SHA256_DIGEST_LENGTH);
143
if
(EVP_DigestFinal_ex(mdctx.handle, hash, &length) != 1) {
144
throw
std::runtime_error(
"Unable to finalize SHA256-EVP."
);
145
}
146
147
// convert to "hex string"
148
Sha256Checksum
hexString;
149
char
*hexStringIterator = hexString.
checksum
;
150
for
(
unsigned
char
hashNumber : hash) {
151
const
string
digits = numberToString(hashNumber,
static_cast<
unsigned
char
>
(16));
152
*(hexStringIterator++) = digits.size() < 2 ?
'0'
: digits.front();
153
*(hexStringIterator++) = digits.back();
154
}
155
*hexStringIterator =
'\0'
;
156
return
hexString;
157
}
158
162
void
TestFile::verifyChecksum
()
const
163
{
164
CPPUNIT_ASSERT_EQUAL_MESSAGE(argsToString(
"integrity of testfile \""
,
path
,
'\"'
),
expectedSha256sum
,
computeSha256Sum
());
165
}
166
171
class
TestFileCheck
:
public
TestFixture {
172
CPPUNIT_TEST_SUITE(
TestFileCheck
);
173
CPPUNIT_TEST(verifyChecksums);
174
CPPUNIT_TEST_SUITE_END();
175
176
private
:
177
void
verifyChecksums();
178
};
179
180
CPPUNIT_TEST_SUITE_REGISTRATION
(
TestFileCheck
);
181
182
void
TestFileCheck::verifyChecksums()
183
{
184
for
(
const
TestFile
&testFile :
testFiles
) {
185
testFile.verifyChecksum();
186
}
187
}
caseinsensitivecomparer.h
TestFileCheck
The TestFileCheck class verifies integrity of all testfiles used in the testsuite of tagparser or tag...
Definition
testfilecheck.cpp:171
CppUtilities
Definition
abstractcontainer.h:16
CppUtilities::operator<<
std::ostream & operator<<(std::ostream &os, const TagParser::TagTextEncoding &encoding)
Prints a TagTextEncoding to enable CPPUNIT_ASSERT_EQUAL for tag values.
Definition
helper.cpp:8
TagParser
Contains all classes and functions of the TagInfo library.
Definition
aaccodebook.h:10
Sha256Checksum
The Sha256Checksum struct holds the "hex string representation" of a SHA-256 checksum.
Definition
testfilecheck.cpp:22
Sha256Checksum::checksum
char checksum[65]
Definition
testfilecheck.cpp:23
Sha256Checksum::operator==
bool operator==(const Sha256Checksum &other) const
Returns whether the current instance equals other ignoring the case.
Definition
testfilecheck.cpp:30
TagParser::CaseInsensitiveCharComparer::toLower
static constexpr unsigned char toLower(const unsigned char c)
Definition
caseinsensitivecomparer.h:16
TestFile
The TestFile struct holds the path (relative to testfile dir) and checksum of a test file.
Definition
testfilecheck.cpp:51
TestFile::computeSha256Sum
Sha256Checksum computeSha256Sum() const
Computes the SHA-256 checksums for the file using OpenSSL.
Definition
testfilecheck.cpp:104
TestFile::path
const char * path
Definition
testfilecheck.cpp:52
TestFile::verifyChecksum
void verifyChecksum() const
Checks whether the expected SHA-256 checksum matches the actual checksum.
Definition
testfilecheck.cpp:162
TestFile::expectedSha256sum
Sha256Checksum expectedSha256sum
Definition
testfilecheck.cpp:53
testFiles
struct TestFile testFiles[]
CPPUNIT_TEST_SUITE_REGISTRATION
CPPUNIT_TEST_SUITE_REGISTRATION(MediaFileInfoTests)
Generated on
for Tag Parser by
1.18.0