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> 30 using namespace ConversionUtilities;
32 using namespace TestUtilities::Literals;
34 using namespace CPPUNIT_NS;
41 CPPUNIT_TEST(testSize);
42 CPPUNIT_TEST(testTagTarget);
43 CPPUNIT_TEST(testSignature);
44 CPPUNIT_TEST(testMargin);
45 CPPUNIT_TEST(testAspectRatio);
46 CPPUNIT_TEST(testMediaFormat);
47 CPPUNIT_TEST(testPositionInSet);
48 CPPUNIT_TEST(testProgressFeedback);
49 CPPUNIT_TEST(testAbortableProgressFeedback);
50 CPPUNIT_TEST(testDiagnostics);
51 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();
69 void testBackupFile();
84 static_assert(
Size().isNull(),
"Size::isNull()");
85 static_assert(!
Size(3, 4).isNull(),
"Size::isNull()");
86 static_assert(
Size(3, 4).resolution() == 12,
"Size::resolution");
88 Size size(1920, 1080);
89 CPPUNIT_ASSERT_EQUAL(
"width: 1920, height: 1080"s, size.
toString());
90 CPPUNIT_ASSERT_EQUAL(
"1080p"s,
string(size.
abbreviation()));
93 CPPUNIT_ASSERT_EQUAL(
"720p"s,
string(size.
abbreviation()));
99 CPPUNIT_ASSERT(target.
isEmpty());
100 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"default level is 50", static_cast<uint64>(50), target.
level());
101 CPPUNIT_ASSERT_EQUAL(
"level 50"s, target.
toString(TagTargetLevel::Unspecified));
102 target =
TagTarget(30, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 });
103 CPPUNIT_ASSERT(!target.isEmpty());
104 const auto mapping = [](uint64 level) {
return level == 30 ?
TagTargetLevel::Track : TagTargetLevel::Unspecified; };
105 CPPUNIT_ASSERT_EQUAL(
106 "level 30 'track, song, chapter', track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
107 target.toString(mapping));
109 CPPUNIT_ASSERT_EQUAL(
"level 40, track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
110 target.toString(mapping));
111 target.setLevelName(
"test");
112 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,
113 target.toString(mapping));
114 CPPUNIT_ASSERT(target ==
TagTarget(40, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 }));
116 CPPUNIT_ASSERT(target.isEmpty());
121 const unsigned char xzHead[12] = { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x04, 0xe6, 0xd6, 0xb4, 0x46 };
124 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(reinterpret_cast<const char *>(xzHead), 3));
125 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(reinterpret_cast<const char *>(xzHead), 2));
126 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(reinterpret_cast<const char *>(xzHead), 0));
128 const auto containerFormat =
parseSignature(reinterpret_cast<const char *>(xzHead),
sizeof(xzHead));
137 static_assert(
Margin().isNull(),
"empty margin");
138 static_assert(!
Margin(0, 2).isNull(),
"non-empty margin");
140 CPPUNIT_ASSERT_EQUAL(
"top: 1; left: 2; bottom: 3; right: 4"s,
Margin(1, 2, 3, 4).toString());
145 static_assert(!
AspectRatio().isValid(),
"invalid aspect ratio");
146 static_assert(
AspectRatio(16, 9).isValid(),
"valid aspect ratio");
147 static_assert(
AspectRatio(16, 9).isExtended(),
"extended aspect ratio");
150 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(16), ratio.
numerator);
151 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(11), ratio.
denominator);
153 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(0), ratio2.
numerator);
154 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(0), ratio2.
denominator);
161 CPPUNIT_ASSERT_EQUAL(
"Advanced Audio Coding"s,
string(aac.
name()));
162 CPPUNIT_ASSERT_EQUAL(
"AAC"s,
string(aac.
abbreviation()));
169 CPPUNIT_ASSERT_EQUAL(
"Advanced Audio Coding Low Complexity Profile"s,
string(aac.
name()));
170 CPPUNIT_ASSERT_EQUAL(
"MPEG-4 AAC-LC"s,
string(aac.
abbreviation()));
172 CPPUNIT_ASSERT_EQUAL(
"Spectral Band Replication / HE-AAC"s,
string(aac.
extensionName()));
178 CPPUNIT_ASSERT(empty.
isNull());
179 CPPUNIT_ASSERT_EQUAL(0, empty.
position());
180 CPPUNIT_ASSERT_EQUAL(0, empty.
total());
181 CPPUNIT_ASSERT_EQUAL(
""s, empty.
toString());
184 CPPUNIT_ASSERT(!oneOfThree.isNull());
185 CPPUNIT_ASSERT_EQUAL(1, oneOfThree.position());
186 CPPUNIT_ASSERT_EQUAL(3, oneOfThree.total());
187 CPPUNIT_ASSERT_EQUAL(
"1/3"s, oneOfThree.toString());
190 CPPUNIT_ASSERT(!posOnly.isNull());
191 CPPUNIT_ASSERT_EQUAL(5, posOnly.position());
192 CPPUNIT_ASSERT_EQUAL(0, posOnly.total());
193 CPPUNIT_ASSERT_EQUAL(
"5"s, posOnly.toString());
196 CPPUNIT_ASSERT(!totalOnly.isNull());
197 CPPUNIT_ASSERT_EQUAL(0, totalOnly.position());
198 CPPUNIT_ASSERT_EQUAL(5, totalOnly.total());
199 CPPUNIT_ASSERT_EQUAL(
"/5"s, totalOnly.toString());
204 unsigned int steps = 0;
206 unsigned int stepPercentage;
207 unsigned int overallPercentage = 0;
212 step = progress.
step();
220 CPPUNIT_ASSERT_EQUAL(0u, steps);
222 CPPUNIT_ASSERT_EQUAL(0u, steps);
223 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
225 CPPUNIT_ASSERT_EQUAL(1u, steps);
226 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
227 CPPUNIT_ASSERT_EQUAL(45u, stepPercentage);
228 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
230 CPPUNIT_ASSERT_EQUAL(1u, steps);
231 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
232 CPPUNIT_ASSERT_EQUAL(60u, stepPercentage);
233 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
235 CPPUNIT_ASSERT_EQUAL(1u, steps);
236 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
237 CPPUNIT_ASSERT_EQUAL(75u, stepPercentage);
238 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
243 unsigned int steps = 0;
245 unsigned int stepPercentage;
246 unsigned int overallPercentage = 0;
251 step = progress.
step();
260 CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"stop does nothing if not aborted", progress.
stopIfAborted());
261 CPPUNIT_ASSERT_EQUAL(0u, steps);
263 CPPUNIT_ASSERT_EQUAL(0u, steps);
264 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
266 CPPUNIT_ASSERT_EQUAL(1u, steps);
267 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
268 CPPUNIT_ASSERT_EQUAL(45u, stepPercentage);
269 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
270 CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"next step continues if not aborted", progress.
nextStepOrStop(
"bar", 33));
271 CPPUNIT_ASSERT_EQUAL(2u, steps);
272 CPPUNIT_ASSERT_EQUAL(
"bar"s, step);
273 CPPUNIT_ASSERT_EQUAL(33u, stepPercentage);
274 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
278 CPPUNIT_ASSERT_EQUAL(2u, steps);
279 CPPUNIT_ASSERT_EQUAL(
"bar"s, step);
280 CPPUNIT_ASSERT_EQUAL(33u, stepPercentage);
281 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
288 diag.emplace_back(DiagLevel::Warning,
"warning msg",
"context");
289 CPPUNIT_ASSERT_EQUAL(DiagLevel::Warning, diag.
level());
290 CPPUNIT_ASSERT(!diag.
has(DiagLevel::Critical));
291 diag.emplace_back(DiagLevel::Critical,
"critical msg",
"context");
292 CPPUNIT_ASSERT_EQUAL(DiagLevel::Critical, diag.
level());
293 CPPUNIT_ASSERT(diag.
has(DiagLevel::Critical));
298 using namespace BackupHelper;
307 string backupPath1, backupPath2;
308 NativeFileStream backupStream1, backupStream2;
310 CPPUNIT_ASSERT_EQUAL(workingDir +
"/unsupported.bin.bak", backupPath1);
313 file.
stream().open(file.
path(), ios_base::out);
314 file.
stream() <<
"test1" << endl;
318 CPPUNIT_ASSERT_EQUAL(workingDir +
"/unsupported.bin.1.bak", backupPath2);
321 backupStream2.close();
322 remove(backupPath2.data());
323 file.
stream().open(file.
path(), ios_base::out);
324 file.
stream() <<
"test2" << endl;
329 CPPUNIT_FAIL(
"renaming failed because backup dir does not exist");
331 const char *what = catchIoFailure();
332 CPPUNIT_ASSERT(strstr(what,
"Unable to rename original file before rewriting it."));
334 backupStream2.clear();
335 workingCopyPathMode(
"bak/unsupported.bin", WorkingCopyMode::NoCopy);
337 CPPUNIT_ASSERT_EQUAL(workingDir +
"/bak/unsupported.bin", backupPath2);
340 backupStream2.close();
341 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"remove " + backupPath2, 0, remove(backupPath2.data()));
342 const auto backupDir(workingDir +
"/bak");
343 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"remove " + backupDir, 0, rmdir(backupDir.data()));
346 backupStream1.seekg(0, ios_base::end);
347 CPPUNIT_ASSERT_EQUAL(41_st, static_cast<size_t>(backupStream1.tellg()));
354 file.
stream().seekg(0x1D);
355 CPPUNIT_ASSERT_EQUAL(0x34_st, static_cast<size_t>(file.
stream().get()));
364 CPPUNIT_ASSERT_THROW(
366 CPPUNIT_ASSERT(diag.level() < DiagLevel::Critical);
367 CPPUNIT_ASSERT(!diag.empty());
368 CPPUNIT_ASSERT_EQUAL(
"Rewriting the file to apply changed tag information has been aborted."s, diag.front().message());
369 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
379 CPPUNIT_ASSERT(diag.level() >= DiagLevel::Critical);
380 CPPUNIT_ASSERT_EQUAL(
"Rewriting the file to apply changed tag information failed."s, diag.front().message());
381 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
387 throwIoFailure(
"simulated IO failure");
392 CPPUNIT_FAIL(
"IO failure not rethrown");
396 CPPUNIT_ASSERT(diag.
level() >= DiagLevel::Critical);
397 CPPUNIT_ASSERT_EQUAL(
"An IO error occurred when rewriting the file to apply changed tag information."s, diag.front().message());
398 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
401 CPPUNIT_ASSERT_EQUAL(0, remove(file.
path().data()));
static std::string containingDirectory(const std::string &path)
Returns the path of the directory containing the given file.
void open(bool readOnly=false)
Opens a std::fstream for the current file.
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.
const std::string & path() const
Returns the path of the current file.
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.
void close()
A possibly opened std::fstream will be closed.
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.
IoUtilities::NativeFileStream & stream()
Returns the std::fstream for the current instance.
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.