10#include <c++utilities/io/misc.h>
19void OverallTests::checkOggTestfile1()
21 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Ogg, m_fileInfo.
containerFormat());
22 const auto tracks = m_fileInfo.
tracks();
23 CPPUNIT_ASSERT_EQUAL(2_st, tracks.size());
24 for (
const auto &track : tracks) {
25 switch (track->id()) {
27 CPPUNIT_ASSERT_EQUAL(MediaType::Video, track->mediaType());
28 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Theora, track->format().general);
31 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
32 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Vorbis, track->format().general);
33 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(2), track->channelCount());
34 CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
35 CPPUNIT_ASSERT_EQUAL(4, track->duration().minutes());
38 CPPUNIT_FAIL(
"unknown track ID");
41 const auto tags = m_fileInfo.
tags();
42 switch (m_tagStatus) {
45 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
46 CPPUNIT_ASSERT_EQUAL(
"ffmpeg2theora 0.13"s, tags.front()->value(KnownField::Encoder).toString());
47 CPPUNIT_ASSERT_EQUAL(std::vector<std::uint64_t>{ 0x68a1ea7f }, tags.front()->target().tracks());
52 checkOggTestMetaData();
55 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
58 CPPUNIT_ASSERT(m_diag.
level() <= DiagLevel::Information);
64void OverallTests::checkOggTestfile2()
66 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Ogg, m_fileInfo.
containerFormat());
67 const auto tracks = m_fileInfo.
tracks();
68 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
69 for (
const auto &track : tracks) {
70 switch (track->id()) {
72 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
73 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Opus, track->format().general);
74 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(2), track->channelCount());
75 CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
76 CPPUNIT_ASSERT_EQUAL(1, track->duration().minutes());
79 CPPUNIT_FAIL(
"unknown track ID");
82 const auto tags = m_fileInfo.
tags();
83 switch (m_tagStatus) {
86 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
87 CPPUNIT_ASSERT_EQUAL(
"opusenc from opus-tools 0.1.6"s, tags.front()->value(KnownField::Encoder).toString());
90 checkOggTestMetaData();
93 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
96 CPPUNIT_ASSERT(m_diag.
level() <= DiagLevel::Information);
102void OverallTests::checkOggTestfile3()
104 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Ogg, m_fileInfo.
containerFormat());
105 const auto tracks = m_fileInfo.
tracks();
106 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
107 for (
const auto &track : tracks) {
108 switch (track->id()) {
110 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
111 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Opus, track->format().general);
112 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(2), track->channelCount());
113 CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
114 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromSeconds(19.461), track->duration());
117 CPPUNIT_FAIL(
"unknown track ID");
120 const auto tags = m_fileInfo.
tags();
121 switch (m_tagStatus) {
124 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
125 CPPUNIT_ASSERT_EQUAL(
"Lavf58.76.100"s, tags.front()->value(KnownField::Encoder).toString());
126 CPPUNIT_ASSERT_EQUAL(
"eng"s, tags.front()->value(KnownField::Language).toString());
129 checkOggTestMetaDataCover();
132 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
136 CPPUNIT_ASSERT_MESSAGE(
"no warnings for non-broken file", m_diag.
level() <= DiagLevel::Information);
139 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"warning present", DiagLevel::Warning, m_diag.
level());
140 CPPUNIT_ASSERT(std::find_if(m_diag.begin(), m_diag.end(), [](
const auto &msg) {
141 return startsWith(msg.message(),
"3 bytes left in last segment");
143 CPPUNIT_ASSERT(std::find_if(m_diag.begin(), m_diag.end(), [](
const auto &msg) {
144 return startsWith(msg.message(),
"Tag spans over 6 pages but absolute granule position of unfinished page at");
146 CPPUNIT_ASSERT(std::find_if(m_diag.begin(), m_diag.end(), [](
const auto &msg) {
147 return startsWith(msg.message(),
"The tag is continued in Ogg page at");
154void OverallTests::checkOggTestMetaData()
157 const auto tags = m_fileInfo.
tags();
159 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
160 CPPUNIT_ASSERT(tag !=
nullptr);
163 CPPUNIT_ASSERT_EQUAL(m_testTitle, tag->value(KnownField::Title));
164 CPPUNIT_ASSERT_EQUAL(m_testComment.
toString(), tag->value(KnownField::Comment).toString());
165 CPPUNIT_ASSERT_EQUAL(m_testAlbum, tag->value(KnownField::Album));
166 CPPUNIT_ASSERT_EQUAL(m_preservedMetaData.front(), tag->value(KnownField::Artist));
167 CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->value(KnownField::TrackPosition));
168 CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->value(KnownField::DiskPosition));
170 m_preservedMetaData.pop();
173void OverallTests::checkOggTestMetaDataCover()
176 const auto tags = m_fileInfo.
tags();
178 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
179 CPPUNIT_ASSERT(tag !=
nullptr);
181 const auto expectedCoverData = readFile(testFilePath(
"ogg/example-cover.png"));
182 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"expected cover assigned", std::string_view(expectedCoverData), tag->value(KnownField::Cover).data());
185void OverallTests::setOggTestMetaData()
191 tag->
setValue(KnownField::Title, m_testTitle);
192 tag->setValue(KnownField::Comment, m_testComment);
193 tag->setValue(KnownField::Album, m_testAlbum);
194 m_preservedMetaData.push(tag->value(KnownField::Artist));
195 tag->setValue(KnownField::TrackPosition, m_testPosition);
196 tag->setValue(KnownField::DiskPosition, m_testPosition);
200void OverallTests::setOggTestMetaDataCover()
203 const auto cover = readFile(testFilePath(
"ogg/example-cover.png"));
204 tag->setValue(KnownField::Cover,
TagValue(
cover.data(),
cover.size(), TagDataType::Picture));
213 cerr << endl <<
"Ogg parser" << endl;
216 parseFile(testFilePath(
"mtx-test-data/ogg/qt4dance_medium.ogg"), &OverallTests::checkOggTestfile1);
217 parseFile(testFilePath(
"mtx-test-data/opus/v-opus.ogg"), &OverallTests::checkOggTestfile2);
218 parseFile(testFilePath(
"ogg/noise-broken-segment-termination.opus"), &OverallTests::checkOggTestfile3);
233 for (m_mode = 0; m_mode != 0x2; ++m_mode) {
240 list<string> testConditions;
241 if (m_mode & RemoveTag) {
242 testConditions.emplace_back(
"removing tag");
244 testConditions.emplace_back(
"modifying tag");
246 cerr << endl <<
"Ogg maker - testmode " << m_mode <<
": " << joinStrings(testConditions,
", ") << endl;
250 const auto modifyRoutine = (m_mode & RemoveTag) ? &OverallTests::removeAllTags : &OverallTests::setOggTestMetaData;
251 const auto modifyRoutineCover = (m_mode & RemoveTag) ? &OverallTests::removeAllTags : &OverallTests::setOggTestMetaDataCover;
252 makeFile(workingCopyPath(
"mtx-test-data/ogg/qt4dance_medium.ogg"), modifyRoutine, &OverallTests::checkOggTestfile1);
253 makeFile(workingCopyPath(
"mtx-test-data/opus/v-opus.ogg"), modifyRoutine, &OverallTests::checkOggTestfile2);
254 makeFile(workingCopyPath(
"ogg/noise-without-cover.opus"), modifyRoutineCover, &OverallTests::checkOggTestfile3);
263 const auto context = std::string();
273 auto &fields = vc.fields();
274 fields.insert(std::make_pair(trackNumberFieldId, std::move(trackNumber)));
275 fields.insert(std::make_pair(trackTotalFieldId, std::move(trackTotal)));
276 vc.convertTotalFields(context, diag);
278 const auto convertedValues = vc.values(trackNumberFieldId);
279 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"the two fileds have been combined into one", 1_st, fields.size());
280 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"there is exactly one track number value", 1_st, convertedValues.size());
281 const auto convertedTrackNumber = convertedValues.front()->toPositionInSet();
282 CPPUNIT_ASSERT_EQUAL(
PositionInSet(5, 20), convertedTrackNumber);
283 CPPUNIT_ASSERT_EQUAL(0_st, diag.size());
288 fields.insert(std::make_pair(diskNumberFieldId, std::move(diskNumber)));
289 fields.insert(std::make_pair(diskTotalFieldId, std::move(diskTotal)));
290 fields.insert(std::make_pair(diskTotalFieldId, std::move(diskTotal2)));
291 vc.convertTotalFields(context, diag);
293 const auto newDiskNumberValues = vc.values(diskNumberFieldId);
294 const auto newDiskTotalValues = vc.values(diskTotalFieldId);
295 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"invalid fields have not been combined", 4_st, fields.size());
296 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"invalid disk position has been preserved and valid disk total converted", 2_st, newDiskNumberValues.size());
297 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"invalid disk total has been preserved", 1_st, newDiskTotalValues.size());
298 const auto preservedDiskNumber = newDiskNumberValues[0]->toString();
299 const auto convertedDiskTotal = newDiskNumberValues[1]->toPositionInSet();
300 const auto preservedDiskTotal = newDiskTotalValues[0]->toString();
301 CPPUNIT_ASSERT_EQUAL(
"invalid pos"s, preservedDiskNumber);
302 CPPUNIT_ASSERT_EQUAL(
PositionInSet(0, 42), convertedDiskTotal);
303 CPPUNIT_ASSERT_EQUAL(
"invalid total"s, preservedDiskTotal);
304 CPPUNIT_ASSERT_EQUAL(3_st, diag.size());
void testOggParsing()
Tests the Ogg parser via MediaFileInfo.
void testVorbisCommentFieldHandling()
Tests the Vorbis Comment specifc handling of certain fields done in VorbisComment::convertTotalFields...
void testOggMaking()
Tests the Ogg maker via MediaFileInfo.
The Diagnostics class is a container for DiagMessage.
DiagLevel level() const
Returns the worst diag level present in the container.
The TagValue class wraps values of different types.
std::string toString(TagTextEncoding encoding=TagTextEncoding::Unspecified) const
Converts the value of the current TagValue object to its equivalent std::string representation.