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>
29using namespace CppUtilities::Literals;
31using namespace CPPUNIT_NS;
49 CPPUNIT_TEST_SUITE_END();
52 void setUp()
override;
81 static_assert(
Size().
isNull(),
"Size::isNull()");
82 static_assert(!
Size(3, 4).
isNull(),
"Size::isNull()");
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));
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());
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);
218 progressFeedback.updateOverallPercentage(25);
219 CPPUNIT_ASSERT_EQUAL(0u, steps);
220 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
221 progressFeedback.updateStep(
"foo", 45);
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);
226 progressFeedback.updateStepPercentage(60);
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);
231 progressFeedback.updateStepPercentageFromFraction(0.75);
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();
256 CPPUNIT_ASSERT(!progressFeedback.isAborted());
257 CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"stop does nothing if not aborted", progressFeedback.stopIfAborted());
258 CPPUNIT_ASSERT_EQUAL(0u, steps);
259 progressFeedback.updateOverallPercentage(25);
260 CPPUNIT_ASSERT_EQUAL(0u, steps);
261 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
262 progressFeedback.updateStep(
"foo", 45);
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", progressFeedback.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);
272 progressFeedback.tryToAbort();
273 CPPUNIT_ASSERT(progressFeedback.isAborted());
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 create backup file .* of .* 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()));
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()
TAG_PARSER_EXPORT void createBackupFile(const std::string &backupDir, const std::string &originalPath, std::string &backupPath, CppUtilities::NativeFileStream &originalStream, CppUtilities::NativeFileStream &backupStream)
TAG_PARSER_EXPORT void restoreOriginalFileFromBackupFile(const std::string &originalPath, const std::string &backupPath, CppUtilities::NativeFileStream &originalStream, CppUtilities::NativeFileStream &backupStream)
TAG_PARSER_EXPORT void handleFailureAfterFileModified(MediaFileInfo &fileInfo, const std::string &backupPath, CppUtilities::NativeFileStream &outputStream, CppUtilities::NativeFileStream &backupStream, Diagnostics &diag, const std::string &context="making file")
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)