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/io/catchiofailure.h> 18 #include <c++utilities/tests/testutils.h> 21 #include <cppunit/TestFixture.h> 22 #include <cppunit/extensions/HelperMacros.h> 39 CPPUNIT_TEST(testSize);
40 CPPUNIT_TEST(testTagTarget);
41 CPPUNIT_TEST(testSignature);
42 CPPUNIT_TEST(testMargin);
43 CPPUNIT_TEST(testAspectRatio);
44 CPPUNIT_TEST(testMediaFormat);
45 CPPUNIT_TEST(testPositionInSet);
46 CPPUNIT_TEST(testProgressFeedback);
47 CPPUNIT_TEST(testAbortableProgressFeedback);
48 CPPUNIT_TEST(testDiagnostics);
50 CPPUNIT_TEST(testBackupFile);
52 CPPUNIT_TEST_SUITE_END();
59 void testStatusProvider();
63 void testAspectRatio();
64 void testMediaFormat();
65 void testPositionInSet();
66 void testProgressFeedback();
67 void testAbortableProgressFeedback();
68 void testDiagnostics();
70 void testBackupFile();
86 static_assert(
Size().isNull(),
"Size::isNull()");
87 static_assert(!
Size(3, 4).isNull(),
"Size::isNull()");
88 static_assert(
Size(3, 4).resolution() == 12,
"Size::resolution");
90 Size size(1920, 1080);
91 CPPUNIT_ASSERT_EQUAL(
"width: 1920, height: 1080"s, size.
toString());
92 CPPUNIT_ASSERT_EQUAL(
"1080p"s,
string(size.
abbreviation()));
95 CPPUNIT_ASSERT_EQUAL(
"720p"s,
string(size.
abbreviation()));
101 CPPUNIT_ASSERT(target.
isEmpty());
102 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"default level is 50", 50ul, target.
level());
103 CPPUNIT_ASSERT_EQUAL(
"level 50"s, target.
toString(TagTargetLevel::Unspecified));
104 target =
TagTarget(30, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 });
105 CPPUNIT_ASSERT(!target.isEmpty());
106 const auto mapping = [](uint64 level) {
return level == 30 ?
TagTargetLevel::Track : TagTargetLevel::Unspecified; };
107 CPPUNIT_ASSERT_EQUAL(
108 "level 30 'track, song, chapter', track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
109 target.toString(mapping));
111 CPPUNIT_ASSERT_EQUAL(
"level 40, track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
112 target.toString(mapping));
113 target.setLevelName(
"test");
114 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,
115 target.toString(mapping));
116 CPPUNIT_ASSERT(target ==
TagTarget(40, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 }));
118 CPPUNIT_ASSERT(target.isEmpty());
123 const unsigned char xzHead[12] = { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x04, 0xe6, 0xd6, 0xb4, 0x46 };
126 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(reinterpret_cast<const char *>(xzHead), 3));
127 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(reinterpret_cast<const char *>(xzHead), 2));
128 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(reinterpret_cast<const char *>(xzHead), 0));
130 const auto containerFormat =
parseSignature(reinterpret_cast<const char *>(xzHead),
sizeof(xzHead));
139 static_assert(
Margin().isNull(),
"empty margin");
140 static_assert(!
Margin(0, 2).isNull(),
"non-empty margin");
142 CPPUNIT_ASSERT_EQUAL(
"top: 1; left: 2; bottom: 3; right: 4"s,
Margin(1, 2, 3, 4).toString());
147 static_assert(!
AspectRatio().isValid(),
"invalid aspect ratio");
148 static_assert(
AspectRatio(16, 9).isValid(),
"valid aspect ratio");
149 static_assert(
AspectRatio(16, 9).isExtended(),
"extended aspect ratio");
152 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(16), ratio.
numerator);
153 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(11), ratio.
denominator);
155 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(0), ratio2.
numerator);
156 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(0), ratio2.
denominator);
163 CPPUNIT_ASSERT_EQUAL(
"Advanced Audio Coding"s,
string(aac.
name()));
164 CPPUNIT_ASSERT_EQUAL(
"AAC"s,
string(aac.
abbreviation()));
171 CPPUNIT_ASSERT_EQUAL(
"Advanced Audio Coding Low Complexity Profile"s,
string(aac.
name()));
172 CPPUNIT_ASSERT_EQUAL(
"MPEG-4 AAC-LC"s,
string(aac.
abbreviation()));
174 CPPUNIT_ASSERT_EQUAL(
"Spectral Band Replication / HE-AAC"s,
string(aac.
extensionName()));
180 CPPUNIT_ASSERT(empty.
isNull());
181 CPPUNIT_ASSERT_EQUAL(0, empty.
position());
182 CPPUNIT_ASSERT_EQUAL(0, empty.
total());
183 CPPUNIT_ASSERT_EQUAL(
""s, empty.
toString());
186 CPPUNIT_ASSERT(!oneOfThree.isNull());
187 CPPUNIT_ASSERT_EQUAL(1, oneOfThree.position());
188 CPPUNIT_ASSERT_EQUAL(3, oneOfThree.total());
189 CPPUNIT_ASSERT_EQUAL(
"1/3"s, oneOfThree.toString());
192 CPPUNIT_ASSERT(!posOnly.isNull());
193 CPPUNIT_ASSERT_EQUAL(5, posOnly.position());
194 CPPUNIT_ASSERT_EQUAL(0, posOnly.total());
195 CPPUNIT_ASSERT_EQUAL(
"5"s, posOnly.toString());
198 CPPUNIT_ASSERT(!totalOnly.isNull());
199 CPPUNIT_ASSERT_EQUAL(0, totalOnly.position());
200 CPPUNIT_ASSERT_EQUAL(5, totalOnly.total());
201 CPPUNIT_ASSERT_EQUAL(
"/5"s, totalOnly.toString());
206 unsigned int steps = 0;
208 unsigned int stepPercentage;
209 unsigned int overallPercentage = 0;
214 step = progress.
step();
222 CPPUNIT_ASSERT_EQUAL(0u, steps);
224 CPPUNIT_ASSERT_EQUAL(0u, steps);
225 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
227 CPPUNIT_ASSERT_EQUAL(1u, steps);
228 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
229 CPPUNIT_ASSERT_EQUAL(45u, stepPercentage);
230 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
232 CPPUNIT_ASSERT_EQUAL(1u, steps);
233 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
234 CPPUNIT_ASSERT_EQUAL(60u, stepPercentage);
235 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
237 CPPUNIT_ASSERT_EQUAL(1u, steps);
238 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
239 CPPUNIT_ASSERT_EQUAL(75u, stepPercentage);
240 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
245 unsigned int steps = 0;
247 unsigned int stepPercentage;
248 unsigned int overallPercentage = 0;
253 step = progress.
step();
262 CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"stop does nothing if not aborted", progress.
stopIfAborted());
263 CPPUNIT_ASSERT_EQUAL(0u, steps);
265 CPPUNIT_ASSERT_EQUAL(0u, steps);
266 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
268 CPPUNIT_ASSERT_EQUAL(1u, steps);
269 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
270 CPPUNIT_ASSERT_EQUAL(45u, stepPercentage);
271 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
272 CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"next step continues if not aborted", progress.
nextStepOrStop(
"bar", 33));
273 CPPUNIT_ASSERT_EQUAL(2u, steps);
274 CPPUNIT_ASSERT_EQUAL(
"bar"s, step);
275 CPPUNIT_ASSERT_EQUAL(33u, stepPercentage);
276 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
280 CPPUNIT_ASSERT_EQUAL(2u, steps);
281 CPPUNIT_ASSERT_EQUAL(
"bar"s, step);
282 CPPUNIT_ASSERT_EQUAL(33u, stepPercentage);
283 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
290 diag.emplace_back(DiagLevel::Warning,
"warning msg",
"context");
291 CPPUNIT_ASSERT_EQUAL(DiagLevel::Warning, diag.
level());
292 CPPUNIT_ASSERT(!diag.
has(DiagLevel::Critical));
293 diag.emplace_back(DiagLevel::Critical,
"critical msg",
"context");
294 CPPUNIT_ASSERT_EQUAL(DiagLevel::Critical, diag.
level());
295 CPPUNIT_ASSERT(diag.
has(DiagLevel::Critical));
299 void UtilitiesTests::testBackupFile()
301 using namespace BackupHelper;
305 file.setBackupDirectory(
string());
306 const auto workingDir(file.containingDirectory());
310 string backupPath1, backupPath2;
311 NativeFileStream backupStream1, backupStream2;
312 createBackupFile(
string(), file.path(), backupPath1, file.stream(), backupStream1);
313 CPPUNIT_ASSERT_EQUAL(workingDir +
"/unsupported.bin.bak", backupPath1);
316 file.stream().open(file.path(), ios_base::out);
317 file.stream() <<
"test1" << endl;
320 createBackupFile(
string(), file.path(), backupPath2, file.stream(), backupStream2);
321 CPPUNIT_ASSERT_EQUAL(workingDir +
"/unsupported.bin.1.bak", backupPath2);
324 backupStream2.close();
325 remove(backupPath2.data());
326 file.stream().open(file.path(), ios_base::out);
327 file.stream() <<
"test2" << endl;
331 createBackupFile(
"bak", file.path(), backupPath2, file.stream(), backupStream2);
332 CPPUNIT_FAIL(
"renaming failed because backup dir does not exist");
334 const char *what = catchIoFailure();
335 CPPUNIT_ASSERT(strstr(what,
"Unable to rename original file before rewriting it."));
337 backupStream2.clear();
338 workingCopyPathMode(
"bak/unsupported.bin", WorkingCopyMode::NoCopy);
339 createBackupFile(
"bak", file.path(), backupPath2, file.stream(), backupStream2);
340 CPPUNIT_ASSERT_EQUAL(workingDir +
"/bak/unsupported.bin", backupPath2);
343 backupStream2.close();
344 CPPUNIT_ASSERT_EQUAL(0,
remove(backupPath2.data()));
345 CPPUNIT_ASSERT_EQUAL(0,
remove((workingDir +
"/bak").data()));
348 backupStream1.seekg(0, ios_base::end);
349 CPPUNIT_ASSERT_EQUAL(41_st, static_cast<size_t>(backupStream1.tellg()));
356 file.stream().seekg(0x1D);
357 CPPUNIT_ASSERT_EQUAL(0x34_st, static_cast<size_t>(file.stream().get()));
361 createBackupFile(
string(), file.path(), backupPath1, file.stream(), backupStream1);
366 CPPUNIT_ASSERT_THROW(
368 CPPUNIT_ASSERT(diag.
level() < DiagLevel::Critical);
369 CPPUNIT_ASSERT(!diag.empty());
370 CPPUNIT_ASSERT_EQUAL(
"Rewriting the file to apply changed tag information has been aborted."s, diag.front().message());
371 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
375 createBackupFile(
string(), file.path(), backupPath1, file.stream(), backupStream1);
381 CPPUNIT_ASSERT(diag.
level() >= DiagLevel::Critical);
382 CPPUNIT_ASSERT_EQUAL(
"Rewriting the file to apply changed tag information failed."s, diag.front().message());
383 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
387 createBackupFile(
string(), file.path(), backupPath1, file.stream(), backupStream1);
389 throwIoFailure(
"simulated IO failure");
394 CPPUNIT_FAIL(
"IO failure not rethrown");
398 CPPUNIT_ASSERT(diag.
level() >= DiagLevel::Critical);
399 CPPUNIT_ASSERT_EQUAL(
"An IO error occurred when rewriting the file to apply changed tag information."s, diag.front().message());
400 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
403 CPPUNIT_ASSERT_EQUAL(0,
remove(file.path().data()));
The Margin class defines the four margins of a rectangle.
StringType toString() const
Returns the string representation of the current PositionInSet.
std::string toString(const std::function< TagTargetLevel(uint64)> &tagTargetMapping) const
Returns the string representation of the current instance.
const char * abbreviation() const
Returns an abbreviation for the current instance, eg.
void updateStepPercentage(byte stepPercentage)
Updates the current step percentage and invokes the second callback specified on construction (or the...
void setWidth(uint32 value)
Sets the width.
The ProgressFeedback class provides feedback about an ongoing operation via callbacks.
void stopIfAborted() const
Throws an OperationAbortedException if aborted.
constexpr int32 position() const
Returns the element position of the current instance.
uint64 level() const
Returns the level.
The PositionInSet class describes the position of an element in a set which consists of a certain num...
The UtilitiesTests class tests various utility classes and functions of the tagparser library...
void updateStepPercentageFromFraction(double stepPercentage)
Updates the current step percentage and invokes the second callback specified on construction (or the...
TAG_PARSER_EXPORT void createBackupFile(const std::string &backupDir, const std::string &originalPath, std::string &backupPath, IoUtilities::NativeFileStream &originalStream, IoUtilities::NativeFileStream &backupStream)
bool isAborted() const
Returns whether the operation has been aborted via tryToAbort().
constexpr int32 total() const
Returns the total element count of the current instance.
void setHeight(uint32 value)
Sets the height.
The Size class defines the size of a two-dimensional object using integer point precision.
byte stepPercentage() const
Returns the percentage of the current step (initially 0, supposed to be a value from 0 to 100)...
byte overallPercentage() const
Returns the overall percentage (initially 0, supposed to be a value from 0 to 100).
Contains utility classes helping to read and write streams.
DiagLevel level() const
Returns the worst diag level present in the container.
TAG_PARSER_EXPORT const char * containerFormatName(ContainerFormat containerFormat)
Returns the name of the specified container format as C-style string.
void testAbortableProgressFeedback()
bool isEmpty() const
Returns an indication whether the target is empty.
void tryToAbort()
Aborts the operation.
The TagTarget class specifies the target of a tag.
TAG_PARSER_EXPORT void restoreOriginalFileFromBackupFile(const std::string &originalPath, const std::string &backupPath, IoUtilities::NativeFileStream &originalStream, IoUtilities::NativeFileStream &backupStream)
TAG_PARSER_EXPORT const char * containerFormatAbbreviation(ContainerFormat containerFormat, MediaType mediaType=MediaType::Unknown, unsigned int version=0)
Returns the abbreviation of the container format as C-style string considering the specified media ty...
void updateOverallPercentage(byte overallPercentage)
Updates the overall percentage and invokes the second callback specified on construction (or the firs...
void testProgressFeedback()
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks...
CPPUNIT_TEST_SUITE_REGISTRATION(UtilitiesTests)
constexpr bool isNull() const
Returns an indication whether both the element position and total element count is 0...
void updateStep(const std::string &step, byte stepPercentage=0)
Updates the current step and invokes the first callback specified on construction.
TAG_PARSER_EXPORT void handleFailureAfterFileModified(MediaFileInfo &mediaFileInfo, const std::string &backupPath, IoUtilities::NativeFileStream &outputStream, IoUtilities::NativeFileStream &backupStream, Diagnostics &diag, const std::string &context="making file")
std::string toString() const
Returns the string representation of the current size.
bool has(DiagLevel level) const
Returns whether there's at least one DiagMessage which is at least as worse as level.
TAG_PARSER_EXPORT ContainerFormat parseSignature(const char *buffer, int bufferSize)
Parses the signature read from the specified buffer.
const std::string & step() const
Returns the name of the current step (initially empty).
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
The exception that is thrown when an operation has been stopped and thus not successfully completed b...
TAG_PARSER_EXPORT const char * containerFormatSubversion(ContainerFormat containerFormat)
Returns the subversion of the container format as C-style string.
Contains all classes and functions of the TagInfo library.
void nextStepOrStop(const std::string &step, byte stepPercentage=0)
Throws an OperationAbortedException if aborted; otherwise the data for the next step is set...
The AspectRatio struct defines an aspect ratio.
The Diagnostics class is a container for DiagMessage.