Tag Parser 12.3.1
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
Loading...
Searching...
No Matches
utils.cpp
Go to the documentation of this file.
1#include "./helper.h"
2
3#include "../aspectratio.h"
4#include "../backuphelper.h"
5#include "../diagnostics.h"
6#include "../exceptions.h"
7#include "../margin.h"
8#include "../mediafileinfo.h"
9#include "../mediaformat.h"
10#include "../positioninset.h"
11#include "../progressfeedback.h"
12#include "../signature.h"
13#include "../size.h"
14#include "../tagtarget.h"
15
16#include <c++utilities/conversion/stringbuilder.h>
17#include <c++utilities/tests/testutils.h>
18using namespace CppUtilities;
19
20#include <cppunit/TestFixture.h>
21#include <cppunit/extensions/HelperMacros.h>
22
23#include <cstdio>
24#include <filesystem>
25#include <regex>
26
27using namespace std;
28using namespace CppUtilities::Literals;
29using namespace TagParser;
30using namespace CPPUNIT_NS;
31
35class UtilitiesTests : public TestFixture {
36 CPPUNIT_TEST_SUITE(UtilitiesTests);
37 CPPUNIT_TEST(testSize);
38 CPPUNIT_TEST(testTagTarget);
39 CPPUNIT_TEST(testSignature);
40 CPPUNIT_TEST(testMargin);
41 CPPUNIT_TEST(testAspectRatio);
42 CPPUNIT_TEST(testMediaFormat);
43 CPPUNIT_TEST(testPositionInSet);
44 CPPUNIT_TEST(testProgressFeedback);
46 CPPUNIT_TEST(testDiagnostics);
47 CPPUNIT_TEST(testBackupFile);
48 CPPUNIT_TEST_SUITE_END();
49
50public:
51 void setUp() override;
52 void tearDown() override;
53
54 void testSize();
56 void testTagTarget();
57 void testSignature();
58 void testMargin();
59 void testAspectRatio();
60 void testMediaFormat();
61 void testPositionInSet();
64 void testDiagnostics();
65 void testBackupFile();
66};
67
69
71{
72}
73
77
79{
80 static_assert(Size().isNull(), "Size::isNull()");
81 static_assert(!Size(3, 4).isNull(), "Size::isNull()");
82 static_assert(Size(3, 4).resolution() == 12, "Size::resolution");
83
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()));
87 size.setWidth(1280);
88 size.setHeight(720);
89 CPPUNIT_ASSERT_EQUAL("720p"s, string(size.abbreviation()));
90}
91
93{
94 TagTarget target;
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,
103 target.toString(mapping));
104 target.setLevel(40);
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,
106 target.toString(mapping));
107 target.setLevelName("test");
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,
109 target.toString(mapping));
110 CPPUNIT_ASSERT(target == TagTarget(40, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 }));
111 target.clear();
112 CPPUNIT_ASSERT(target.isEmpty());
113}
114
116{
117 const unsigned char xzHead[12] = { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x04, 0xe6, 0xd6, 0xb4, 0x46 };
118
119 // truncated buffer
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));
123
124 const auto containerFormat = parseSignature(reinterpret_cast<const char *>(xzHead), sizeof(xzHead));
125 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Xz, containerFormat);
126 CPPUNIT_ASSERT_EQUAL("xz compressed file"s, string(containerFormatName(containerFormat)));
127 CPPUNIT_ASSERT_EQUAL("xz"s, string(containerFormatAbbreviation(containerFormat)));
128 CPPUNIT_ASSERT_EQUAL(string(), string(containerFormatSubversion(containerFormat)));
129}
130
132{
133 static_assert(Margin().isNull(), "empty margin");
134 static_assert(!Margin(0, 2).isNull(), "non-empty margin");
135
136 CPPUNIT_ASSERT_EQUAL("top: 1; left: 2; bottom: 3; right: 4"s, Margin(1, 2, 3, 4).toString());
137}
138
140{
141 static_assert(!AspectRatio().isValid(), "invalid aspect ratio");
142 static_assert(AspectRatio(16, 9).isValid(), "valid aspect ratio");
143 static_assert(AspectRatio(16, 9).isExtended(), "extended aspect ratio");
144
145 const AspectRatio ratio(4);
146 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(16), ratio.numerator);
147 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(11), ratio.denominator);
148 const AspectRatio ratio2(77);
149 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(0), ratio2.numerator);
150 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(0), ratio2.denominator);
151}
152
154{
155 // unspecific format
156 MediaFormat aac(GeneralMediaFormat::Aac);
157 CPPUNIT_ASSERT_EQUAL("Advanced Audio Coding"s, string(aac.name()));
158 CPPUNIT_ASSERT_EQUAL("AAC"s, string(aac.abbreviation()));
159 CPPUNIT_ASSERT_EQUAL("AAC"s, string(aac.shortAbbreviation()));
160
161 // specific format
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()));
167 CPPUNIT_ASSERT_EQUAL("HE-AAC"s, string(aac.shortAbbreviation()));
168 CPPUNIT_ASSERT_EQUAL("Spectral Band Replication / HE-AAC"s, string(aac.extensionName()));
169}
170
172{
173 const PositionInSet empty;
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());
178
179 const PositionInSet oneOfThree(1, 3);
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());
184
185 const PositionInSet posOnly(5, 0);
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());
190
191 const PositionInSet totalOnly(0, 5);
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());
196}
197
199{
200 unsigned int steps = 0;
201 string step;
202 unsigned int stepPercentage;
203 unsigned int overallPercentage = 0;
204
205 ProgressFeedback progressFeedback(
206 [&](const ProgressFeedback &progress) {
207 ++steps;
208 step = progress.step();
209 stepPercentage = progress.stepPercentage();
210 overallPercentage = progress.overallPercentage();
211 },
212 [&](const ProgressFeedback &progress) {
213 stepPercentage = progress.stepPercentage();
214 overallPercentage = progress.overallPercentage();
215 });
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);
235}
236
238{
239 unsigned int steps = 0;
240 string step;
241 unsigned int stepPercentage;
242 unsigned int overallPercentage = 0;
243
244 AbortableProgressFeedback progressFeedback(
245 [&](const AbortableProgressFeedback &progress) {
246 ++steps;
247 step = progress.step();
248 stepPercentage = progress.stepPercentage();
249 overallPercentage = progress.overallPercentage();
250 },
251 [&](const AbortableProgressFeedback &progress) {
252 stepPercentage = progress.stepPercentage();
253 overallPercentage = progress.overallPercentage();
254 });
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());
273 CPPUNIT_ASSERT_THROW(progressFeedback.nextStepOrStop("not going to happen", 33), OperationAbortedException);
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);
278}
279
281{
282 Diagnostics diag;
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));
290}
291
293{
294 using namespace BackupHelper;
295
296 // setup testfile
297 MediaFileInfo file(workingCopyPath("unsupported.bin"));
298 file.setBackupDirectory(string()); // ensure backup directory is empty, so backups will be created in the same directory as the original file
299 const auto workingDir(file.containingDirectory());
300 file.open();
301
302 // create backup file
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);
307
308 // recreate original file (like the 'make' methods would do to apply changes)
309 file.stream().open(file.path(), ios_base::out);
310 file.stream() << "test1" << endl;
311
312 // create a 2nd backup which should not override the first one
313 createBackupFile(string(), file.path(), backupPath2, file.stream(), backupStream2);
314 CPPUNIT_ASSERT_EQUAL(workingDir + "/unsupported.bin.1.bak", backupPath2);
315
316 // get rid of 2nd backup, recreate original file
317 backupStream2.close();
318 remove(backupPath2.data());
319 file.stream().open(file.path(), ios_base::out);
320 file.stream() << "test2" << endl;
321
322 // create backup under another location
323 try {
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()));
328 }
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);
333
334 // get rid of 2nd backup (again)
335 backupStream2.close();
336 CPPUNIT_ASSERT_EQUAL_MESSAGE("remove " + backupPath2, 0, remove(backupPath2.data()));
337 std::filesystem::remove_all(workingDir + "/bak");
338
339 // should be able to use backup stream, eg. seek to the end
340 backupStream1.seekg(0, ios_base::end);
341 CPPUNIT_ASSERT_EQUAL(41_st, static_cast<size_t>(backupStream1.tellg()));
342
343 // restore backup
344 restoreOriginalFileFromBackupFile(file.path(), backupPath1, file.stream(), backupStream1);
345
346 // check restored backup
347 file.open(true);
348 file.stream().seekg(0x1D);
349 CPPUNIT_ASSERT_EQUAL(0x34_st, static_cast<size_t>(file.stream().get()));
350 file.close();
351
352 // restore after user aborted
353 createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1);
354 try {
356 } catch (...) {
357 Diagnostics diag;
358 CPPUNIT_ASSERT_THROW(
359 handleFailureAfterFileModified(file, backupPath1, file.stream(), backupStream1, diag, "test"), OperationAbortedException);
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());
364 }
365
366 // restore after error
367 createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1);
368 try {
369 throw Failure();
370 } catch (...) {
371 Diagnostics diag;
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());
376 }
377
378 // restore after io failure
379 createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1);
380 try {
381 throw std::ios_base::failure("simulated IO failure");
382 } catch (const std::ios_base::failure &) {
383 Diagnostics diag;
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());
389 }
390
391 CPPUNIT_ASSERT_EQUAL(0, remove(file.path().data()));
392}
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.
Definition margin.h:16
constexpr bool isNull() const
Returns true if all margins are is 0; otherwise returns false;.
Definition margin.h:115
The MediaFileInfo class allows to read and write tag information providing a container/tag format ind...
void setBackupDirectory(std::string_view backupDirectory)
Sets the directory used to store backup files.
The MediaFormat class specifies the format of media data.
std::string_view abbreviation() const
Returns the abbreviation of the media format as C-style string.
std::string_view shortAbbreviation() const
Returns a short abbreviation of the media format as C-style string.
std::string_view name() const
Returns the name of the media format as C-style string.
std::string_view extensionName() const
Returns the abbreviation of the media format as C-style string.
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.
Definition size.h:17
void setWidth(std::uint32_t value)
Sets the width.
Definition size.h:76
bool constexpr isNull() const
Returns an indication whether both the width and height is 0.
Definition size.h:100
std::string toString() const
Returns the string representation of the current size.
Definition size.h:125
constexpr std::uint32_t resolution() const
Returns the resolution of the current instance (product of with and height).
Definition size.h:92
void setHeight(std::uint32_t value)
Sets the height.
Definition size.h:84
std::string_view abbreviation() const
Returns an abbreviation for the current instance, eg.
Definition size.cpp:17
The TagTarget class specifies the target of a tag.
std::uint64_t level() const
Returns the level.
Definition tagtarget.h:73
std::string toString(const std::function< TagTargetLevel(std::uint64_t)> &tagTargetMapping) const
Returns the string representation of the current instance.
Definition tagtarget.h:217
bool isEmpty() const
Returns an indication whether the target is empty.
Definition tagtarget.h:169
void clear()
Clears the TagTarget.
Definition tagtarget.h:177
void setLevel(std::uint64_t level)
Sets the level.
Definition tagtarget.h:81
void setLevelName(const std::string &levelName)
Sets the level name.
Definition tagtarget.h:97
The UtilitiesTests class tests various utility classes and functions of the tagparser library.
Definition utils.cpp:35
void testPositionInSet()
Definition utils.cpp:171
void testSize()
Definition utils.cpp:78
void testTagTarget()
Definition utils.cpp:92
void testProgressFeedback()
Definition utils.cpp:198
void tearDown() override
Definition utils.cpp:74
void testStatusProvider()
void testAbortableProgressFeedback()
Definition utils.cpp:237
void testAspectRatio()
Definition utils.cpp:139
void testMargin()
Definition utils.cpp:131
void testSignature()
Definition utils.cpp:115
void testDiagnostics()
Definition utils.cpp:280
void setUp() override
Definition utils.cpp:70
void testBackupFile()
Definition utils.cpp:292
void testMediaFormat()
Definition utils.cpp:153
Contains all classes and functions of the TagInfo library.
Definition aaccodebook.h:10
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)
Definition signature.h:83
The AspectRatio struct defines an aspect ratio.
std::uint16_t numerator
Definition aspectratio.h:22
std::uint16_t denominator
Definition aspectratio.h:23
constexpr bool isExtended() const
Returns whether numerator and denominator must be read from extended SAR header.
Definition aspectratio.h:58
constexpr bool isValid() const
Returns an indication whether the aspect ratio is present and valid.
Definition aspectratio.h:50
CPPUNIT_TEST_SUITE_REGISTRATION(UtilitiesTests)