1/*
2 * Copyright (C) 2016 Varun Joshi <varunj.1011@gmail.com>
3 * Copyright (C) 2018 Alexander Stippich <a.stippich@gmx.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21#include "taglibwritertest.h"
22#include "indexerextractortestsconfig.h"
23#include "writers/taglibwriter.h"
24#include "writedata.h"
25#include <kfilemetadata/ExtractorCollection>
26#include <kfilemetadata/Extractor>
27#include <kfilemetadata/ExtractionResult>
28#include <kfilemetadata/SimpleExtractionResult>
29#include "taglib.h"
30#include "fileref.h"
31
32#include <QTest>
33#include <QFile>
34#include <QMap>
35
36using namespace KFileMetaData;
37
38QString TagLibWriterTest::testFilePath(const QString& fileName) const
39{
40 return QLatin1String(INDEXER_TESTS_SAMPLE_FILES_PATH) + QLatin1Char('/') + fileName;
41}
42
43void TagLibWriterTest::extractResult(const QString &mimeType, KFileMetaData::ExtractionResult &result)
44{
45 KFileMetaData::ExtractorCollection extractors;
46 QList<KFileMetaData::Extractor*> extractorList = extractors.fetchExtractors(mimeType);
47 if (extractorList.isEmpty()) {
48 QFAIL("This mime type is not supported by the extractor. Likely a newer KDE Frameworks version is required.");
49 }
50 if (extractorList.size() > 1) {
51 QWARN("Multiple extractors are available.");
52 }
53 KFileMetaData::Extractor* ex = extractorList.first();
54 ex->extract(&result);
55}
56
57void TagLibWriterTest::testCommonData()
58{
59 QFETCH(QString, fileType);
60 QFETCH(QString, mimeType);
61 QFETCH(QString, stringSuffix);
62
63 QString temporaryFileName = testFilePath(QStringLiteral("writertest.") + fileType);
64
65 QFile::copy(testFilePath("test." + fileType), temporaryFileName);
66 TagLibWriter writerPlugin{this};
67 QCOMPARE(writerPlugin.writeMimetypes().contains(mimeType),true);
68
69 WriteData data(temporaryFileName, mimeType);
70
71 data.add(Property::Title, QString(QStringLiteral("Title1") + stringSuffix));
72 data.add(Property::Artist, QString(QStringLiteral("Artist1") + stringSuffix));
73 data.add(Property::Album, QString(QStringLiteral("Album1") + stringSuffix));
74 data.add(Property::AlbumArtist, QString(QStringLiteral("AlbumArtist1") + stringSuffix));
75 data.add(Property::Composer, QString(QStringLiteral("Composer1") + stringSuffix));
76 data.add(Property::TrackNumber, 10);
77 data.add(Property::DiscNumber, 2);
78 data.add(Property::ReleaseYear, 1999);
79 data.add(Property::Genre, QString(QStringLiteral("Genre1") + stringSuffix));
80 data.add(Property::Comment, QString(QStringLiteral("Comment1") + stringSuffix));
81 data.add(Property::Copyright, QString(QStringLiteral("Copyright1") + stringSuffix));
82
83 writerPlugin.write(data);
84
85 KFileMetaData::SimpleExtractionResult result(temporaryFileName, mimeType, KFileMetaData::ExtractionResult::ExtractMetaData);
86 extractResult(mimeType, result);
87
88 QCOMPARE(result.properties().value(Property::Title), QVariant(QStringLiteral("Title1") + stringSuffix));
89 QCOMPARE(result.properties().value(Property::Artist), QVariant(QStringLiteral("Artist1") + stringSuffix));
90 QCOMPARE(result.properties().value(Property::Album), QVariant(QStringLiteral("Album1") + stringSuffix));
91 QCOMPARE(result.properties().value(Property::AlbumArtist), QVariant(QStringLiteral("AlbumArtist1") + stringSuffix));
92 QCOMPARE(result.properties().value(Property::Composer), QVariant(QStringLiteral("Composer1") + stringSuffix));
93 QCOMPARE(result.properties().value(Property::TrackNumber).toInt(), 10);
94 QCOMPARE(result.properties().value(Property::DiscNumber).toInt(), 2);
95 QCOMPARE(result.properties().value(Property::ReleaseYear).toInt(), 1999);
96 QCOMPARE(result.properties().value(Property::Genre), QVariant(QStringLiteral("Genre1") + stringSuffix));
97 QCOMPARE(result.properties().value(Property::Comment), QVariant(QStringLiteral("Comment1") + stringSuffix));
98 QCOMPARE(result.properties().value(Property::Copyright), QVariant(QStringLiteral("Copyright1") + stringSuffix));
99
100 QFile::remove(temporaryFileName);
101}
102
103void TagLibWriterTest::testCommonData_data()
104{
105 // Add some unicode characters, use codepoints to avoid any issues with
106 // source encoding: "€µ"
107 static const QChar data[2] = { 0x20ac, 0xb5 };
108 QString unicodeTestStringSuffix(data, 2);
109
110 QTest::addColumn<QString>("fileType");
111 QTest::addColumn<QString>("mimeType");
112 QTest::addColumn<QString>("stringSuffix");
113
114
115 QTest::addRow("aiff")
116 << QStringLiteral("aif")
117 << QStringLiteral("audio/x-aiff")
118 << QString()
119 ;
120
121 QTest::addRow("aiff_unicode")
122 << QStringLiteral("aif")
123 << QStringLiteral("audio/x-aiff")
124 << unicodeTestStringSuffix
125 ;
126
127 QTest::addRow("ape")
128 << QStringLiteral("ape")
129 << QStringLiteral("audio/x-ape")
130 << QString()
131 ;
132
133 QTest::addRow("ape_unicode")
134 << QStringLiteral("ape")
135 << QStringLiteral("audio/x-ape")
136 << unicodeTestStringSuffix
137 ;
138
139 QTest::addRow("flac")
140 << QStringLiteral("flac")
141 << QStringLiteral("audio/flac")
142 << QString()
143 ;
144
145 QTest::addRow("flac_unicode")
146 << QStringLiteral("flac")
147 << QStringLiteral("audio/flac")
148 << unicodeTestStringSuffix
149 ;
150
151 QTest::addRow("m4a")
152 << QStringLiteral("m4a")
153 << QStringLiteral("audio/mp4")
154 << QString()
155 ;
156
157 QTest::addRow("m4a_unicode")
158 << QStringLiteral("m4a")
159 << QStringLiteral("audio/mp4")
160 << unicodeTestStringSuffix
161 ;
162
163 QTest::addRow("mp3")
164 << QStringLiteral("mp3")
165 << QStringLiteral("audio/mpeg3")
166 << QString()
167 ;
168
169 QTest::addRow("mp3_unicode")
170 << QStringLiteral("mp3")
171 << QStringLiteral("audio/mpeg3")
172 << unicodeTestStringSuffix
173 ;
174
175 QTest::addRow("mpc")
176 << QStringLiteral("mpc")
177 << QStringLiteral("audio/x-musepack")
178 << QString()
179 ;
180
181 QTest::addRow("mpc_unicode")
182 << QStringLiteral("mpc")
183 << QStringLiteral("audio/x-musepack")
184 << unicodeTestStringSuffix
185 ;
186
187 QTest::addRow("ogg")
188 << QStringLiteral("ogg")
189 << QStringLiteral("audio/ogg")
190 << QString()
191 ;
192
193 QTest::addRow("ogg_unicode")
194 << QStringLiteral("ogg")
195 << QStringLiteral("audio/ogg")
196 << unicodeTestStringSuffix
197 ;
198
199 QTest::addRow("opus")
200 << QStringLiteral("opus")
201 << QStringLiteral("audio/opus")
202 << QString()
203 ;
204
205 QTest::addRow("opus_unicode")
206 << QStringLiteral("opus")
207 << QStringLiteral("audio/opus")
208 << unicodeTestStringSuffix
209 ;
210
211 QTest::addRow("speex")
212 << QStringLiteral("spx")
213 << QStringLiteral("audio/speex")
214 << QString()
215 ;
216
217 QTest::addRow("speex_unicode")
218 << QStringLiteral("spx")
219 << QStringLiteral("audio/speex")
220 << unicodeTestStringSuffix
221 ;
222
223 QTest::addRow("wav")
224 << QStringLiteral("wav")
225 << QStringLiteral("audio/wav")
226 << QString()
227 ;
228
229 QTest::addRow("wav_unicode")
230 << QStringLiteral("wav")
231 << QStringLiteral("audio/wav")
232 << unicodeTestStringSuffix
233 ;
234
235 QTest::addRow("wavpack")
236 << QStringLiteral("wv")
237 << QStringLiteral("audio/x-wavpack")
238 << QString()
239 ;
240
241 QTest::addRow("wavpack_unicode")
242 << QStringLiteral("wv")
243 << QStringLiteral("audio/x-wavpack")
244 << unicodeTestStringSuffix
245 ;
246
247 QTest::addRow("wma")
248 << QStringLiteral("wma")
249 << QStringLiteral("audio/x-ms-wma")
250 << QString()
251 ;
252
253 QTest::addRow("wma_unicode")
254 << QStringLiteral("wma")
255 << QStringLiteral("audio/x-ms-wma")
256 << unicodeTestStringSuffix
257 ;
258}
259
260void TagLibWriterTest::testExtendedData()
261{
262 QFETCH(QString, fileType);
263 QFETCH(QString, mimeType);
264
265 QString temporaryFileName = testFilePath(QStringLiteral("writertest.") + fileType);
266
267 QFile::copy(testFilePath("test." + fileType), temporaryFileName);
268 TagLibWriter writerPlugin{this};
269
270 WriteData data(temporaryFileName, mimeType);
271
272 data.add(Property::Composer, QStringLiteral("Composer1"));
273 data.add(Property::Lyricist, QStringLiteral("Lyricist1"));
274 data.add(Property::Conductor, QStringLiteral("Conductor1"));
275 data.add(Property::Lyrics, QStringLiteral("Lyrics1"));
276 data.add(Property::Language, QStringLiteral("Language1"));
277
278 writerPlugin.write(data);
279
280 KFileMetaData::SimpleExtractionResult result(temporaryFileName, mimeType, KFileMetaData::ExtractionResult::ExtractMetaData);
281 extractResult(mimeType, result);
282
283 QCOMPARE(result.properties().value(Property::Composer), QVariant(QStringLiteral("Composer1")));
284 QCOMPARE(result.properties().value(Property::Lyricist), QVariant(QStringLiteral("Lyricist1")));
285 QCOMPARE(result.properties().value(Property::Conductor), QVariant(QStringLiteral("Conductor1")));
286 QCOMPARE(result.properties().value(Property::Lyrics), QVariant(QStringLiteral("Lyrics1")));
287 QCOMPARE(result.properties().value(Property::Language), QVariant(QStringLiteral("Language1")));
288
289 QFile::remove(temporaryFileName);
290}
291
292void TagLibWriterTest::testExtendedData_data()
293{
294 QTest::addColumn<QString>("fileType");
295 QTest::addColumn<QString>("mimeType");
296
297 QTest::addRow("aiff")
298 << QStringLiteral("aif")
299 << QStringLiteral("audio/x-aiff")
300 ;
301
302 QTest::addRow("ape")
303 << QStringLiteral("ape")
304 << QStringLiteral("audio/x-ape")
305 ;
306
307 QTest::addRow("flac")
308 << QStringLiteral("flac")
309 << QStringLiteral("audio/flac")
310 ;
311
312 QTest::addRow("mp3")
313 << QStringLiteral("mp3")
314 << QStringLiteral("audio/mpeg3")
315 ;
316
317 QTest::addRow("mpc")
318 << QStringLiteral("mpc")
319 << QStringLiteral("audio/x-musepack")
320 ;
321
322 QTest::addRow("ogg")
323 << QStringLiteral("ogg")
324 << QStringLiteral("audio/ogg")
325 ;
326
327 QTest::addRow("opus")
328 << QStringLiteral("opus")
329 << QStringLiteral("audio/opus")
330 ;
331
332 QTest::addRow("speex")
333 << QStringLiteral("spx")
334 << QStringLiteral("audio/speex")
335 ;
336
337 QTest::addRow("wav")
338 << QStringLiteral("wav")
339 << QStringLiteral("audio/wav")
340 ;
341
342 QTest::addRow("wavpack")
343 << QStringLiteral("wv")
344 << QStringLiteral("audio/x-wavpack")
345 ;
346}
347
348void TagLibWriterTest::testRating()
349{
350 QFETCH(QString, fileType);
351 QFETCH(QString, mimeType);
352 QFETCH(int, rating);
353
354 QString temporaryFileName = testFilePath(QStringLiteral("writertest.") + fileType);
355
356 QFile::copy(testFilePath("test.") + fileType, temporaryFileName);
357 TagLibWriter writerPlugin{this};
358 QCOMPARE(writerPlugin.writeMimetypes().contains(mimeType),true);
359
360 WriteData data(temporaryFileName, mimeType);
361
362 data.add(Property::Rating, rating);
363 writerPlugin.write(data);
364
365 KFileMetaData::SimpleExtractionResult result(temporaryFileName, mimeType, KFileMetaData::ExtractionResult::ExtractMetaData);
366 extractResult(mimeType, result);
367
368 QCOMPARE(result.properties().value(Property::Rating).toInt(), rating);
369
370 QFile::remove(temporaryFileName);
371}
372
373void TagLibWriterTest::testRating_data()
374{
375
376 QTest::addColumn<QString>("fileType");
377 QTest::addColumn<QString>("mimeType");
378 QTest::addColumn<int>("rating");
379
380 QTest::addRow("aiff")
381 << QStringLiteral("aif")
382 << QStringLiteral("audio/x-aiff")
383 << 3
384 ;
385
386 QTest::addRow("ape")
387 << QStringLiteral("ape")
388 << QStringLiteral("audio/x-ape")
389 << 1
390 ;
391
392 QTest::addRow("flac")
393 << QStringLiteral("flac")
394 << QStringLiteral("audio/flac")
395 << 3
396 ;
397
398 QTest::addRow("m4a")
399 << QStringLiteral("m4a")
400 << QStringLiteral("audio/mp4")
401 << 5
402 ;
403
404 QTest::addRow("mp3_0")
405 << QStringLiteral("mp3")
406 << QStringLiteral("audio/mpeg3")
407 << 0
408 ;
409
410 QTest::addRow("mp3_1")
411 << QStringLiteral("mp3")
412 << QStringLiteral("audio/mpeg3")
413 << 1
414 ;
415
416 QTest::addRow("mp3_2")
417 << QStringLiteral("mp3")
418 << QStringLiteral("audio/mpeg3")
419 << 2
420 ;
421
422 QTest::addRow("mp3_3")
423 << QStringLiteral("mp3")
424 << QStringLiteral("audio/mpeg3")
425 << 3
426 ;
427
428 QTest::addRow("mp3_4")
429 << QStringLiteral("mp3")
430 << QStringLiteral("audio/mpeg3")
431 << 4
432 ;
433
434 QTest::addRow("mp3_5")
435 << QStringLiteral("mp3")
436 << QStringLiteral("audio/mpeg3")
437 << 5
438 ;
439
440 QTest::addRow("mp3_6")
441 << QStringLiteral("mp3")
442 << QStringLiteral("audio/mpeg3")
443 << 6
444 ;
445
446 QTest::addRow("mp3_7")
447 << QStringLiteral("mp3")
448 << QStringLiteral("audio/mpeg3")
449 << 7
450 ;
451
452 QTest::addRow("mp3_8")
453 << QStringLiteral("mp3")
454 << QStringLiteral("audio/mpeg3")
455 << 8
456 ;
457
458 QTest::addRow("mp3_9")
459 << QStringLiteral("mp3")
460 << QStringLiteral("audio/mpeg3")
461 << 9
462 ;
463
464 QTest::addRow("mp3_10")
465 << QStringLiteral("mp3")
466 << QStringLiteral("audio/mpeg3")
467 << 10
468 ;
469
470 QTest::addRow("mpc")
471 << QStringLiteral("mpc")
472 << QStringLiteral("audio/x-musepack")
473 << 7
474 ;
475
476 QTest::addRow("opus")
477 << QStringLiteral("opus")
478 << QStringLiteral("audio/opus")
479 << 6
480 ;
481
482 QTest::addRow("speex")
483 << QStringLiteral("spx")
484 << QStringLiteral("audio/speex")
485 << 8
486 ;
487
488 QTest::addRow("wav")
489 << QStringLiteral("wav")
490 << QStringLiteral("audio/wav")
491 << 4
492 ;
493
494 QTest::addRow("wavpack")
495 << QStringLiteral("wv")
496 << QStringLiteral("audio/x-wavpack")
497 << 9
498 ;
499
500 QTest::addRow("wma_0")
501 << QStringLiteral("wma")
502 << QStringLiteral("audio/x-ms-wma")
503 << 0
504 ;
505
506 QTest::addRow("wma_2")
507 << QStringLiteral("wma")
508 << QStringLiteral("audio/x-ms-wma")
509 << 2
510 ;
511
512 QTest::addRow("wma_4")
513 << QStringLiteral("wma")
514 << QStringLiteral("audio/x-ms-wma")
515 << 4
516 ;
517
518 QTest::addRow("wma_5")
519 << QStringLiteral("wma")
520 << QStringLiteral("audio/x-ms-wma")
521 << 5
522 ;
523
524 QTest::addRow("wma_6")
525 << QStringLiteral("wma")
526 << QStringLiteral("audio/x-ms-wma")
527 << 6
528 ;
529
530 QTest::addRow("wma_8")
531 << QStringLiteral("wma")
532 << QStringLiteral("audio/x-ms-wma")
533 << 8
534 ;
535
536 QTest::addRow("wma_10")
537 << QStringLiteral("wma")
538 << QStringLiteral("audio/x-ms-wma")
539 << 10
540 ;
541}
542
543void TagLibWriterTest::testComplexContactData()
544{
545 QFETCH(QString, fileExtension);
546 QFETCH(QString, mimeType);
547
548 QString temporaryFileName = testFilePath(QStringLiteral("writertest.") + fileExtension);
549
550 QFile::copy(testFilePath("test." + fileExtension), temporaryFileName);
551 TagLibWriter writerPlugin{this};
552
553 WriteData data(temporaryFileName, mimeType);
554
555 const QMap<Property::Property, QString> properties = {
556 { Property::Artist, QStringLiteral("Artist1 feat Artist2") },
557 { Property::AlbumArtist, QStringLiteral("Artist1 feat. Artist2") },
558 { Property::Composer, QStringLiteral("Composer1; Composer2") },
559 { Property::Lyricist, QStringLiteral("Lyricist1 ft Lyricist2") },
560 { Property::Genre, QStringLiteral("Genre1; Genre2") },
561 };
562
563 QMap<Property::Property, QString>::const_iterator it;
564 for (it = properties.begin(); it != properties.end(); ++it) {
565 data.add(it.key(), it.value());
566 }
567
568 writerPlugin.write(data);
569
570 KFileMetaData::SimpleExtractionResult result(temporaryFileName, mimeType, KFileMetaData::ExtractionResult::ExtractMetaData);
571 extractResult(mimeType, result);
572
573 for (it = properties.begin(); it != properties.end(); ++it) {
574 QCOMPARE(result.properties().value(it.key()), it.value());
575 }
576
577 QFile::remove(temporaryFileName);
578}
579
580void TagLibWriterTest::testComplexContactData_data()
581{
582 QTest::addColumn<QString>("fileExtension");
583 QTest::addColumn<QString>("mimeType");
584
585 QTest::addRow("aiff")
586 << QStringLiteral("aif")
587 << QStringLiteral("audio/x-aiff")
588 ;
589
590 QTest::addRow("ape")
591 << QStringLiteral("ape")
592 << QStringLiteral("audio/x-ape")
593 ;
594
595 QTest::addRow("flac")
596 << QStringLiteral("flac")
597 << QStringLiteral("audio/flac")
598 ;
599
600 QTest::addRow("mp3")
601 << QStringLiteral("mp3")
602 << QStringLiteral("audio/mpeg3")
603 ;
604
605 QTest::addRow("mpc")
606 << QStringLiteral("mpc")
607 << QStringLiteral("audio/x-musepack")
608 ;
609
610 QTest::addRow("ogg")
611 << QStringLiteral("ogg")
612 << QStringLiteral("audio/ogg")
613 ;
614
615 QTest::addRow("opus")
616 << QStringLiteral("opus")
617 << QStringLiteral("audio/opus")
618 ;
619
620 QTest::addRow("speex")
621 << QStringLiteral("spx")
622 << QStringLiteral("audio/speex")
623 ;
624
625 QTest::addRow("wav")
626 << QStringLiteral("wav")
627 << QStringLiteral("audio/wav")
628 ;
629
630 QTest::addRow("wavpack")
631 << QStringLiteral("wv")
632 << QStringLiteral("audio/x-wavpack")
633 ;
634}
635
636QTEST_GUILESS_MAIN(TagLibWriterTest)
637