3#include <c++utilities/conversion/stringbuilder.h>
4#include <c++utilities/tests/testutils.h>
6#include <cppunit/TestFixture.h>
7#include <cppunit/extensions/HelperMacros.h>
9#include <openssl/evp.h>
10#include <openssl/sha.h>
17using namespace CPPUNIT_NS;
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" } },
88 : handle(EVP_MD_CTX_new())
94 EVP_MD_CTX_free(handle);
107 const auto mdctx = EvpMdCtx();
109 throw std::runtime_error(
"Unable to create EVP context.");
111 if (EVP_DigestInit_ex(mdctx.handle, EVP_sha256(),
nullptr) != 1) {
112 throw std::runtime_error(
"Unable to init SHA256-EVP context.");
118 file.exceptions(ios_base::eofbit | ios_base::failbit | ios_base::badbit);
119 file.open(testFilePath(
path), ios_base::in | ios_base::binary);
121 char readBuffer[4096];
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.");
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.");
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.");
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();
155 *hexStringIterator =
'\0';
173 CPPUNIT_TEST(verifyChecksums);
174 CPPUNIT_TEST_SUITE_END();
177 void verifyChecksums();
182void TestFileCheck::verifyChecksums()
185 testFile.verifyChecksum();
The TestFileCheck class verifies integrity of all testfiles used in the testsuite of tagparser or tag...
std::ostream & operator<<(std::ostream &os, const TagParser::TagTextEncoding &encoding)
Prints a TagTextEncoding to enable CPPUNIT_ASSERT_EQUAL for tag values.
Contains all classes and functions of the TagInfo library.
The Sha256Checksum struct holds the "hex string representation" of a SHA-256 checksum.
bool operator==(const Sha256Checksum &other) const
Returns whether the current instance equals other ignoring the case.
static constexpr unsigned char toLower(const unsigned char c)
The TestFile struct holds the path (relative to testfile dir) and checksum of a test file.
Sha256Checksum computeSha256Sum() const
Computes the SHA-256 checksums for the file using OpenSSL.
void verifyChecksum() const
Checks whether the expected SHA-256 checksum matches the actual checksum.
Sha256Checksum expectedSha256sum
struct TestFile testFiles[]
CPPUNIT_TEST_SUITE_REGISTRATION(TestFileCheck)