3 #include "../aspectratio.h"
4 #include "../backuphelper.h"
5 #include "../diagnostics.h"
6 #include "../exceptions.h"
8 #include "../mediafileinfo.h"
9 #include "../mediaformat.h"
10 #include "../positioninset.h"
11 #include "../progressfeedback.h"
12 #include "../signature.h"
14 #include "../tagtarget.h"
16 #include <c++utilities/conversion/stringbuilder.h>
17 #include <c++utilities/tests/testutils.h>
20 #include <cppunit/TestFixture.h>
21 #include <cppunit/extensions/HelperMacros.h>
29 using namespace CppUtilities::Literals;
31 using namespace CPPUNIT_NS;
38 CPPUNIT_TEST(testSize);
39 CPPUNIT_TEST(testTagTarget);
40 CPPUNIT_TEST(testSignature);
41 CPPUNIT_TEST(testMargin);
42 CPPUNIT_TEST(testAspectRatio);
43 CPPUNIT_TEST(testMediaFormat);
44 CPPUNIT_TEST(testPositionInSet);
45 CPPUNIT_TEST(testProgressFeedback);
46 CPPUNIT_TEST(testAbortableProgressFeedback);
47 CPPUNIT_TEST(testDiagnostics);
48 CPPUNIT_TEST(testBackupFile);
49 CPPUNIT_TEST_SUITE_END();
52 void setUp()
override;
53 void tearDown()
override;
60 void testAspectRatio();
61 void testMediaFormat();
62 void testPositionInSet();
63 void testProgressFeedback();
64 void testAbortableProgressFeedback();
65 void testDiagnostics();
66 void testBackupFile();
81 static_assert(
Size().isNull(),
"Size::isNull()");
82 static_assert(!
Size(3, 4).isNull(),
"Size::isNull()");
83 static_assert(
Size(3, 4).resolution() == 12,
"Size::resolution");
85 Size size(1920, 1080);
86 CPPUNIT_ASSERT_EQUAL(
"width: 1920, height: 1080"s, size.
toString());
87 CPPUNIT_ASSERT_EQUAL(
"1080p"s,
string(size.
abbreviation()));
90 CPPUNIT_ASSERT_EQUAL(
"720p"s,
string(size.
abbreviation()));
96 CPPUNIT_ASSERT(target.
isEmpty());
97 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"default level is 50",
static_cast<std::uint64_t
>(50), target.
level());
98 CPPUNIT_ASSERT_EQUAL(
"level 50"s, target.
toString(TagTargetLevel::Unspecified));
99 target =
TagTarget(30, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 });
100 CPPUNIT_ASSERT(!target.
isEmpty());
101 const auto mapping = [](std::uint64_t level) {
return level == 30 ?
TagTargetLevel::Track : TagTargetLevel::Unspecified; };
102 CPPUNIT_ASSERT_EQUAL(
103 "level 30 'track, song, chapter', track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
106 CPPUNIT_ASSERT_EQUAL(
"level 40, track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
109 CPPUNIT_ASSERT_EQUAL(
"level 40 'test', track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
111 CPPUNIT_ASSERT(target ==
TagTarget(40, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 }));
113 CPPUNIT_ASSERT(target.
isEmpty());
118 const unsigned char xzHead[12] = { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x04, 0xe6, 0xd6, 0xb4, 0x46 };
121 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(
reinterpret_cast<const char *
>(xzHead), 3));
122 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(
reinterpret_cast<const char *
>(xzHead), 2));
123 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(
reinterpret_cast<const char *
>(xzHead), 0));
125 const auto containerFormat =
parseSignature(
reinterpret_cast<const char *
>(xzHead),
sizeof(xzHead));
134 static_assert(
Margin().isNull(),
"empty margin");
135 static_assert(!
Margin(0, 2).isNull(),
"non-empty margin");
137 CPPUNIT_ASSERT_EQUAL(
"top: 1; left: 2; bottom: 3; right: 4"s,
Margin(1, 2, 3, 4).toString());
142 static_assert(!
AspectRatio().isValid(),
"invalid aspect ratio");
143 static_assert(
AspectRatio(16, 9).isValid(),
"valid aspect ratio");
144 static_assert(
AspectRatio(16, 9).isExtended(),
"extended aspect ratio");
147 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(16), ratio.
numerator);
148 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(11), ratio.
denominator);
150 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(0), ratio2.
numerator);
151 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(0), ratio2.
denominator);
158 CPPUNIT_ASSERT_EQUAL(
"Advanced Audio Coding"s,
string(aac.
name()));
159 CPPUNIT_ASSERT_EQUAL(
"AAC"s,
string(aac.
abbreviation()));
166 CPPUNIT_ASSERT_EQUAL(
"Advanced Audio Coding Low Complexity Profile"s,
string(aac.
name()));
167 CPPUNIT_ASSERT_EQUAL(
"MPEG-4 AAC-LC"s,
string(aac.
abbreviation()));
169 CPPUNIT_ASSERT_EQUAL(
"Spectral Band Replication / HE-AAC"s,
string(aac.
extensionName()));
175 CPPUNIT_ASSERT(empty.
isNull());
176 CPPUNIT_ASSERT_EQUAL(0, empty.
position());
177 CPPUNIT_ASSERT_EQUAL(0, empty.
total());
178 CPPUNIT_ASSERT_EQUAL(
""s, empty.
toString());
181 CPPUNIT_ASSERT(!oneOfThree.
isNull());
182 CPPUNIT_ASSERT_EQUAL(1, oneOfThree.
position());
183 CPPUNIT_ASSERT_EQUAL(3, oneOfThree.
total());
184 CPPUNIT_ASSERT_EQUAL(
"1/3"s, oneOfThree.
toString());
187 CPPUNIT_ASSERT(!posOnly.
isNull());
188 CPPUNIT_ASSERT_EQUAL(5, posOnly.
position());
189 CPPUNIT_ASSERT_EQUAL(0, posOnly.
total());
190 CPPUNIT_ASSERT_EQUAL(
"5"s, posOnly.
toString());
193 CPPUNIT_ASSERT(!totalOnly.
isNull());
194 CPPUNIT_ASSERT_EQUAL(0, totalOnly.
position());
195 CPPUNIT_ASSERT_EQUAL(5, totalOnly.
total());
196 CPPUNIT_ASSERT_EQUAL(
"/5"s, totalOnly.
toString());
201 unsigned int steps = 0;
203 unsigned int stepPercentage;
204 unsigned int overallPercentage = 0;
209 step = progress.
step();
217 CPPUNIT_ASSERT_EQUAL(0u, steps);
219 CPPUNIT_ASSERT_EQUAL(0u, steps);
220 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
222 CPPUNIT_ASSERT_EQUAL(1u, steps);
223 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
224 CPPUNIT_ASSERT_EQUAL(45u, stepPercentage);
225 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
227 CPPUNIT_ASSERT_EQUAL(1u, steps);
228 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
229 CPPUNIT_ASSERT_EQUAL(60u, stepPercentage);
230 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
232 CPPUNIT_ASSERT_EQUAL(1u, steps);
233 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
234 CPPUNIT_ASSERT_EQUAL(75u, stepPercentage);
235 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
240 unsigned int steps = 0;
242 unsigned int stepPercentage;
243 unsigned int overallPercentage = 0;
248 step = progress.
step();
257 CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"stop does nothing if not aborted", progress.
stopIfAborted());
258 CPPUNIT_ASSERT_EQUAL(0u, steps);
260 CPPUNIT_ASSERT_EQUAL(0u, steps);
261 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
263 CPPUNIT_ASSERT_EQUAL(1u, steps);
264 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
265 CPPUNIT_ASSERT_EQUAL(45u, stepPercentage);
266 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
267 CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"next step continues if not aborted", progress.
nextStepOrStop(
"bar", 33));
268 CPPUNIT_ASSERT_EQUAL(2u, steps);
269 CPPUNIT_ASSERT_EQUAL(
"bar"s, step);
270 CPPUNIT_ASSERT_EQUAL(33u, stepPercentage);
271 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
275 CPPUNIT_ASSERT_EQUAL(2u, steps);
276 CPPUNIT_ASSERT_EQUAL(
"bar"s, step);
277 CPPUNIT_ASSERT_EQUAL(33u, stepPercentage);
278 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
285 diag.emplace_back(DiagLevel::Warning,
"warning msg",
"context");
286 CPPUNIT_ASSERT_EQUAL(DiagLevel::Warning, diag.
level());
287 CPPUNIT_ASSERT(!diag.
has(DiagLevel::Critical));
288 diag.emplace_back(DiagLevel::Critical,
"critical msg",
"context");
289 CPPUNIT_ASSERT_EQUAL(DiagLevel::Critical, diag.
level());
290 CPPUNIT_ASSERT(diag.
has(DiagLevel::Critical));
295 using namespace BackupHelper;
304 string backupPath1, backupPath2;
305 NativeFileStream backupStream1, backupStream2;
307 CPPUNIT_ASSERT_EQUAL(workingDir +
"/unsupported.bin.bak", backupPath1);
310 file.
stream().open(file.
path(), ios_base::out);
311 file.
stream() <<
"test1" << endl;
315 CPPUNIT_ASSERT_EQUAL(workingDir +
"/unsupported.bin.1.bak", backupPath2);
318 backupStream2.close();
319 remove(backupPath2.data());
320 file.
stream().open(file.
path(), ios_base::out);
321 file.
stream() <<
"test2" << endl;
326 CPPUNIT_FAIL(
"renaming failed because backup dir does not exist");
327 }
catch (
const std::ios_base::failure &failure) {
328 TESTUTILS_ASSERT_LIKE(
"renaming error",
"Unable to rename original file before rewriting it: .*"s,
string(failure.what()));
330 backupStream2.clear();
331 workingCopyPath(
"bak/unsupported.bin", WorkingCopyMode::NoCopy);
333 CPPUNIT_ASSERT_EQUAL(workingDir +
"/bak/unsupported.bin", backupPath2);
336 backupStream2.close();
337 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"remove " + backupPath2, 0, remove(backupPath2.data()));
338 const auto backupDir(workingDir +
"/bak");
339 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"remove " + backupDir, 0, rmdir(backupDir.data()));
342 backupStream1.seekg(0, ios_base::end);
343 CPPUNIT_ASSERT_EQUAL(41_st,
static_cast<size_t>(backupStream1.tellg()));
350 file.
stream().seekg(0x1D);
351 CPPUNIT_ASSERT_EQUAL(0x34_st,
static_cast<size_t>(file.
stream().get()));
360 CPPUNIT_ASSERT_THROW(
362 CPPUNIT_ASSERT(diag.
level() < DiagLevel::Critical);
363 CPPUNIT_ASSERT(!diag.empty());
364 CPPUNIT_ASSERT_EQUAL(
"Rewriting the file to apply changed tag information has been aborted."s, diag.front().message());
365 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
375 CPPUNIT_ASSERT(diag.
level() >= DiagLevel::Critical);
376 CPPUNIT_ASSERT_EQUAL(
"Rewriting the file to apply changed tag information failed."s, diag.front().message());
377 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
383 throw std::ios_base::failure(
"simulated IO failure");
384 }
catch (
const std::ios_base::failure &) {
386 CPPUNIT_ASSERT_THROW_MESSAGE(
"IO failure re-thrown",
388 CPPUNIT_ASSERT(diag.
level() >= DiagLevel::Critical);
389 CPPUNIT_ASSERT_EQUAL(
"An IO error occurred when rewriting the file to apply changed tag information."s, diag.front().message());
390 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
393 CPPUNIT_ASSERT_EQUAL(0, remove(file.
path().data()));