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>
28using namespace CppUtilities::Literals;
30using namespace CPPUNIT_NS;
48 CPPUNIT_TEST_SUITE_END();
51 void setUp()
override;
80 static_assert(
Size().
isNull(),
"Size::isNull()");
81 static_assert(!
Size(3, 4).
isNull(),
"Size::isNull()");
84 Size size(1920, 1080);
85 CPPUNIT_ASSERT_EQUAL(
"width: 1920, height: 1080"s, size.
toString());
86 CPPUNIT_ASSERT_EQUAL(
"1080p"s,
string(size.
abbreviation()));
89 CPPUNIT_ASSERT_EQUAL(
"720p"s,
string(size.
abbreviation()));
95 CPPUNIT_ASSERT(target.
isEmpty());
96 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"default level is 50",
static_cast<std::uint64_t
>(50), target.
level());
97 CPPUNIT_ASSERT_EQUAL(
"level 50"s, target.
toString(TagTargetLevel::Unspecified));
98 target =
TagTarget(30, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 });
99 CPPUNIT_ASSERT(!target.
isEmpty());
100 const auto mapping = [](std::uint64_t level) {
return level == 30 ? TagTargetLevel::Track : TagTargetLevel::Unspecified; };
101 CPPUNIT_ASSERT_EQUAL(
102 "level 30 'track, song, chapter', track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
105 CPPUNIT_ASSERT_EQUAL(
"level 40, track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
108 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,
110 CPPUNIT_ASSERT(target ==
TagTarget(40, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 }));
112 CPPUNIT_ASSERT(target.
isEmpty());
117 const unsigned char xzHead[12] = { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x04, 0xe6, 0xd6, 0xb4, 0x46 };
120 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(
reinterpret_cast<const char *
>(xzHead), 3));
121 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(
reinterpret_cast<const char *
>(xzHead), 2));
122 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown,
parseSignature(
reinterpret_cast<const char *
>(xzHead), 0));
124 const auto containerFormat =
parseSignature(
reinterpret_cast<const char *
>(xzHead),
sizeof(xzHead));
125 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Xz, containerFormat);
134 static_assert(!
Margin(0, 2).
isNull(),
"non-empty margin");
136 CPPUNIT_ASSERT_EQUAL(
"top: 1; left: 2; bottom: 3; right: 4"s,
Margin(1, 2, 3, 4).toString());
146 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(16), ratio.
numerator);
147 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(11), ratio.
denominator);
149 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(0), ratio2.
numerator);
150 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(0), ratio2.
denominator);
157 CPPUNIT_ASSERT_EQUAL(
"Advanced Audio Coding"s,
string(aac.
name()));
158 CPPUNIT_ASSERT_EQUAL(
"AAC"s,
string(aac.
abbreviation()));
163 CPPUNIT_ASSERT(aac == GeneralMediaFormat::Aac);
164 CPPUNIT_ASSERT(aac != GeneralMediaFormat::Mpeg1Audio);
165 CPPUNIT_ASSERT_EQUAL(
"Advanced Audio Coding Low Complexity Profile"s,
string(aac.
name()));
166 CPPUNIT_ASSERT_EQUAL(
"MPEG-4 AAC-LC"s,
string(aac.
abbreviation()));
168 CPPUNIT_ASSERT_EQUAL(
"Spectral Band Replication / HE-AAC"s,
string(aac.
extensionName()));
174 CPPUNIT_ASSERT(empty.
isNull());
175 CPPUNIT_ASSERT_EQUAL(0, empty.
position());
176 CPPUNIT_ASSERT_EQUAL(0, empty.
total());
177 CPPUNIT_ASSERT_EQUAL(
""s, empty.
toString());
180 CPPUNIT_ASSERT(!oneOfThree.
isNull());
181 CPPUNIT_ASSERT_EQUAL(1, oneOfThree.
position());
182 CPPUNIT_ASSERT_EQUAL(3, oneOfThree.
total());
183 CPPUNIT_ASSERT_EQUAL(
"1/3"s, oneOfThree.
toString());
186 CPPUNIT_ASSERT(!posOnly.
isNull());
187 CPPUNIT_ASSERT_EQUAL(5, posOnly.
position());
188 CPPUNIT_ASSERT_EQUAL(0, posOnly.
total());
189 CPPUNIT_ASSERT_EQUAL(
"5"s, posOnly.
toString());
192 CPPUNIT_ASSERT(!totalOnly.
isNull());
193 CPPUNIT_ASSERT_EQUAL(0, totalOnly.
position());
194 CPPUNIT_ASSERT_EQUAL(5, totalOnly.
total());
195 CPPUNIT_ASSERT_EQUAL(
"/5"s, totalOnly.
toString());
200 unsigned int steps = 0;
202 unsigned int stepPercentage;
203 unsigned int overallPercentage = 0;
208 step = progress.
step();
216 CPPUNIT_ASSERT_EQUAL(0u, steps);
217 progressFeedback.updateOverallPercentage(25);
218 CPPUNIT_ASSERT_EQUAL(0u, steps);
219 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
220 progressFeedback.updateStep(
"foo", 45);
221 CPPUNIT_ASSERT_EQUAL(1u, steps);
222 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
223 CPPUNIT_ASSERT_EQUAL(45u, stepPercentage);
224 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
225 progressFeedback.updateStepPercentage(60);
226 CPPUNIT_ASSERT_EQUAL(1u, steps);
227 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
228 CPPUNIT_ASSERT_EQUAL(60u, stepPercentage);
229 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
230 progressFeedback.updateStepPercentageFromFraction(0.75);
231 CPPUNIT_ASSERT_EQUAL(1u, steps);
232 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
233 CPPUNIT_ASSERT_EQUAL(75u, stepPercentage);
234 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
239 unsigned int steps = 0;
241 unsigned int stepPercentage;
242 unsigned int overallPercentage = 0;
247 step = progress.
step();
255 CPPUNIT_ASSERT(!progressFeedback.isAborted());
256 CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"stop does nothing if not aborted", progressFeedback.stopIfAborted());
257 CPPUNIT_ASSERT_EQUAL(0u, steps);
258 progressFeedback.updateOverallPercentage(25);
259 CPPUNIT_ASSERT_EQUAL(0u, steps);
260 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
261 progressFeedback.updateStep(
"foo", 45);
262 CPPUNIT_ASSERT_EQUAL(1u, steps);
263 CPPUNIT_ASSERT_EQUAL(
"foo"s, step);
264 CPPUNIT_ASSERT_EQUAL(45u, stepPercentage);
265 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
266 CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"next step continues if not aborted", progressFeedback.nextStepOrStop(
"bar", 33));
267 CPPUNIT_ASSERT_EQUAL(2u, steps);
268 CPPUNIT_ASSERT_EQUAL(
"bar"s, step);
269 CPPUNIT_ASSERT_EQUAL(33u, stepPercentage);
270 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
271 progressFeedback.tryToAbort();
272 CPPUNIT_ASSERT(progressFeedback.isAborted());
274 CPPUNIT_ASSERT_EQUAL(2u, steps);
275 CPPUNIT_ASSERT_EQUAL(
"bar"s, step);
276 CPPUNIT_ASSERT_EQUAL(33u, stepPercentage);
277 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
283 CPPUNIT_ASSERT_EQUAL(DiagLevel::None, diag.
level());
284 diag.emplace_back(DiagLevel::Warning,
"warning msg",
"context");
285 CPPUNIT_ASSERT_EQUAL(DiagLevel::Warning, diag.
level());
286 CPPUNIT_ASSERT(!diag.
has(DiagLevel::Critical));
287 diag.emplace_back(DiagLevel::Critical,
"critical msg",
"context");
288 CPPUNIT_ASSERT_EQUAL(DiagLevel::Critical, diag.
level());
289 CPPUNIT_ASSERT(diag.
has(DiagLevel::Critical));
294 using namespace BackupHelper;
303 string backupPath1, backupPath2;
304 NativeFileStream backupStream1, backupStream2;
305 createBackupFile(
string(), file.
path(), backupPath1, file.
stream(), backupStream1);
306 CPPUNIT_ASSERT_EQUAL(workingDir +
"/unsupported.bin.bak", backupPath1);
309 file.
stream().open(file.
path(), ios_base::out);
310 file.
stream() <<
"test1" << endl;
313 createBackupFile(
string(), file.
path(), backupPath2, file.
stream(), backupStream2);
314 CPPUNIT_ASSERT_EQUAL(workingDir +
"/unsupported.bin.1.bak", backupPath2);
317 backupStream2.close();
318 remove(backupPath2.data());
319 file.
stream().open(file.
path(), ios_base::out);
320 file.
stream() <<
"test2" << endl;
324 createBackupFile(
"bak", file.
path(), backupPath2, file.
stream(), backupStream2);
325 CPPUNIT_FAIL(
"renaming failed because backup dir does not exist");
326 }
catch (
const std::ios_base::failure &failure) {
327 TESTUTILS_ASSERT_LIKE(
"renaming error",
"Unable to create backup file .* of .* before rewriting it: .*"s,
string(failure.what()));
329 backupStream2.clear();
330 workingCopyPath(
"bak/unsupported.bin", WorkingCopyMode::NoCopy);
331 createBackupFile(
"bak", file.
path(), backupPath2, file.
stream(), backupStream2);
332 CPPUNIT_ASSERT_EQUAL(workingDir +
"/bak/unsupported.bin", backupPath2);
335 backupStream2.close();
336 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"remove " + backupPath2, 0, remove(backupPath2.data()));
337 std::filesystem::remove_all(workingDir +
"/bak");
340 backupStream1.seekg(0, ios_base::end);
341 CPPUNIT_ASSERT_EQUAL(41_st,
static_cast<size_t>(backupStream1.tellg()));
344 restoreOriginalFileFromBackupFile(file.
path(), backupPath1, file.
stream(), backupStream1);
348 file.
stream().seekg(0x1D);
349 CPPUNIT_ASSERT_EQUAL(0x34_st,
static_cast<size_t>(file.
stream().get()));
353 createBackupFile(
string(), file.
path(), backupPath1, file.
stream(), backupStream1);
358 CPPUNIT_ASSERT_THROW(
360 CPPUNIT_ASSERT(diag.
level() < DiagLevel::Critical);
361 CPPUNIT_ASSERT(!diag.empty());
362 CPPUNIT_ASSERT_EQUAL(
"Rewriting the file to apply changed tag information has been aborted."s, diag.front().message());
363 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
367 createBackupFile(
string(), file.
path(), backupPath1, file.
stream(), backupStream1);
372 CPPUNIT_ASSERT_THROW(handleFailureAfterFileModified(file, backupPath1, file.
stream(), backupStream1, diag,
"test"),
Failure);
373 CPPUNIT_ASSERT(diag.
level() >= DiagLevel::Critical);
374 CPPUNIT_ASSERT_EQUAL(
"Rewriting the file to apply changed tag information failed."s, diag.front().message());
375 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
379 createBackupFile(
string(), file.
path(), backupPath1, file.
stream(), backupStream1);
381 throw std::ios_base::failure(
"simulated IO failure");
382 }
catch (
const std::ios_base::failure &) {
384 CPPUNIT_ASSERT_THROW_MESSAGE(
"IO failure re-thrown",
385 handleFailureAfterFileModified(file, backupPath1, file.
stream(), backupStream1, diag,
"test"), std::ios_base::failure);
386 CPPUNIT_ASSERT(diag.
level() >= DiagLevel::Critical);
387 CPPUNIT_ASSERT_EQUAL(
"An IO error occurred when rewriting the file to apply changed tag information."s, diag.front().message());
388 CPPUNIT_ASSERT_EQUAL(
"The original file has been restored."s, diag.back().message());
391 CPPUNIT_ASSERT_EQUAL(0, remove(file.
path().data()));
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
const std::string & path() const
Returns the path of the current file.
static std::string containingDirectory(std::string_view path)
Returns the path of the directory containing the given file.
CppUtilities::NativeFileStream & stream()
Returns the std::fstream for the current instance.
void open(bool readOnly=false)
Opens a std::fstream for the current file.
void close()
A possibly opened std::fstream will be closed.
std::uint8_t stepPercentage() const
Returns the percentage of the current step (initially 0, supposed to be a value from 0 to 100).
const std::string & step() const
Returns the name of the current step (initially empty).
std::uint8_t overallPercentage() const
Returns the overall percentage (initially 0, supposed to be a value from 0 to 100).
The Diagnostics class is a container for DiagMessage.
bool has(DiagLevel level) const
Returns whether there's at least one DiagMessage which is at least as worse as level.
DiagLevel level() const
Returns the worst diag level present in the container.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
The Margin class defines the four margins of a rectangle.
constexpr bool isNull() const
Returns true if all margins are is 0; otherwise returns false;.
The exception that is thrown when an operation has been stopped and thus not successfully completed b...
The PositionInSet class describes the position of an element in a set which consists of a certain num...
constexpr std::int32_t position() const
Returns the element position of the current instance.
constexpr std::int32_t total() const
Returns the total element count of the current instance.
StringType toString() const
Returns the string representation of the current PositionInSet.
constexpr bool isNull() const
Returns an indication whether both the element position and total element count is 0.
The ProgressFeedback class provides feedback about an ongoing operation via callbacks.
The Size class defines the size of a two-dimensional object using integer point precision.
void setWidth(std::uint32_t value)
Sets the width.
bool constexpr isNull() const
Returns an indication whether both the width and height is 0.
std::string toString() const
Returns the string representation of the current size.
constexpr std::uint32_t resolution() const
Returns the resolution of the current instance (product of with and height).
void setHeight(std::uint32_t value)
Sets the height.
std::string_view abbreviation() const
Returns an abbreviation for the current instance, eg.
The TagTarget class specifies the target of a tag.
std::uint64_t level() const
Returns the level.
std::string toString(const std::function< TagTargetLevel(std::uint64_t)> &tagTargetMapping) const
Returns the string representation of the current instance.
bool isEmpty() const
Returns an indication whether the target is empty.
void clear()
Clears the TagTarget.
void setLevel(std::uint64_t level)
Sets the level.
void setLevelName(const std::string &levelName)
Sets the level name.
The UtilitiesTests class tests various utility classes and functions of the tagparser library.
void testProgressFeedback()
void testStatusProvider()
void testAbortableProgressFeedback()
Contains all classes and functions of the TagInfo library.
TAG_PARSER_EXPORT std::string_view containerFormatSubversion(ContainerFormat containerFormat)
Returns the subversion of the container format as C-style string.
TAG_PARSER_EXPORT std::string_view 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...
TAG_PARSER_EXPORT std::string_view containerFormatName(ContainerFormat containerFormat)
Returns the name of the specified container format as C-style string.
TAG_PARSER_EXPORT ContainerFormat parseSignature(const char *buffer, std::size_t bufferSize)
The AspectRatio struct defines an aspect ratio.
std::uint16_t denominator
constexpr bool isExtended() const
Returns whether numerator and denominator must be read from extended SAR header.
constexpr bool isValid() const
Returns an indication whether the aspect ratio is present and valid.
CPPUNIT_TEST_SUITE_REGISTRATION(UtilitiesTests)