1 /****************************************************************************************
2 * Copyright (c) 2009 Maximilian Kossick <maximilian.kossick@googlemail.com> *
3 * Copyright (c) 2010-2013 Ralf Engels <ralf-engels@gmx.de> *
4 * *
5 * This program is free software; you can redistribute it and/or modify it under *
6 * the terms of the GNU General Public License as published by the Free Software *
7 * Foundation; either version 2 of the License, or (at your option) any later *
8 * version. *
9 * *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY *
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
12 * PARTICULAR PURPOSE. See the GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License along with *
15 * this program. If not, see <http://www.gnu.org/licenses/>. *
16 ****************************************************************************************/
17
18 #include "TestGenericScanManager.h"
19
20 #include "amarokconfig.h"
21 #include "MetaTagLib.h"
22 #include "scanner/GenericScanManager.h"
23
24 #include "config-amarok-test.h"
25
26 #include <QImage>
27 #include <QScopedPointer>
28 #include <QTest>
29
30 #include <unistd.h>
31
QTEST_MAIN(TestGenericScanManager)32 QTEST_MAIN( TestGenericScanManager )
33
34 TestGenericScanManager::TestGenericScanManager()
35 : QObject()
36 {
37 // QString help = i18n("Amarok"); // prevent a bug when the scanner is the first thread creating a translator
38 }
39
40 void
initTestCase()41 TestGenericScanManager::initTestCase()
42 {
43 AmarokConfig::instance("amarokrc");
44
45 // setenv( "LC_ALL", "", 1 ); // this breaks the test
46 // Amarok does not force LC_ALL=C but obviously the test does it which
47 // will prevent scanning of files with umlauts.
48
49 // that is the original mp3 file that we use to generate the "real" tracks
50 m_sourcePath = QDir::toNativeSeparators( QString( AMAROK_TEST_DIR ) + "/data/audio/Platz 01.mp3" );
51 QVERIFY( QFile::exists( m_sourcePath ) );
52
53 m_scanManager = new GenericScanManager( this );
54
55 connect( m_scanManager, &GenericScanManager::started,
56 this, &TestGenericScanManager::slotStarted );
57 connect( m_scanManager, &GenericScanManager::directoryCount, this, &TestGenericScanManager::slotDirectoryCount );
58 connect( m_scanManager, &GenericScanManager::directoryScanned,
59 this, &TestGenericScanManager::slotDirectoryScanned );
60 connect( m_scanManager, &GenericScanManager::succeeded, this, &TestGenericScanManager::slotSucceeded );
61 connect( m_scanManager, &GenericScanManager::failed, this, &TestGenericScanManager::slotFailed );
62
63 AmarokConfig::setScanRecursively( true );
64 AmarokConfig::setMonitorChanges( false );
65
66 // switch on writing back so that we can create the test files with all the information
67 AmarokConfig::setWriteBack( true );
68 AmarokConfig::setWriteBackStatistics( true );
69 AmarokConfig::setWriteBackCover( true );
70 }
71
72 void
cleanupTestCase()73 TestGenericScanManager::cleanupTestCase()
74 { }
75
76 void
init()77 TestGenericScanManager::init()
78 {
79 m_tmpCollectionDir = new QTemporaryDir;
80
81 QStringList collectionFolders;
82 collectionFolders << m_tmpCollectionDir->path();
83
84 m_started = false;
85 m_finished = false;
86
87 m_scannedDirsCount = 0;
88 m_scannedTracksCount = 0;
89 m_scannedCoversCount = 0;
90 }
91
92 void
cleanup()93 TestGenericScanManager::cleanup()
94 {
95 m_scanManager->abort();
96 delete m_tmpCollectionDir;
97 }
98
99 void
testScanSingle()100 TestGenericScanManager::testScanSingle()
101 {
102 createSingleTrack();
103 fullScanAndWait();
104
105 QCOMPARE( m_scannedDirsCount, 3 );
106 QCOMPARE( m_scannedTracksCount, 1 );
107 QCOMPARE( m_scannedCoversCount, 0 );
108 }
109
110 void
testScanDirectory()111 TestGenericScanManager::testScanDirectory()
112 {
113 createAlbum();
114 fullScanAndWait();
115
116 // -- check the commit
117 QCOMPARE( m_scannedDirsCount, 3 );
118 QCOMPARE( m_scannedTracksCount, 9 );
119 QCOMPARE( m_scannedCoversCount, 0 );
120 }
121
122 void
testRestartScanner()123 TestGenericScanManager::testRestartScanner()
124 {
125 #ifndef QT_NO_DEBUG
126 createAlbum();
127
128 // the scanner crashes at a special file:
129 Meta::FieldHash values;
130 values.clear();
131 values.insert( Meta::valUniqueId, QVariant("c6c29f50279ab9523a0f44928bc1e96b") );
132 values.insert( Meta::valUrl, QVariant("Thriller/crash_amarok_here.ogg") );
133 createTrack( values );
134
135 fullScanAndWait();
136
137 // -- check the commit
138 QCOMPARE( m_scannedDirsCount, 4 );
139 QCOMPARE( m_scannedTracksCount, 9 );
140 QCOMPARE( m_scannedCoversCount, 0 );
141
142 #else
143 QSKIP( "Collection scanner only crashes in debug build.", SkipAll );
144 #endif
145 }
146
147 void
testAlbumImage()148 TestGenericScanManager::testAlbumImage()
149 {
150 createSingleTrack();
151 createAlbum();
152
153 // put an image into the album directory
154 QString imageSourcePath = QDir::toNativeSeparators( QString( AMAROK_TEST_DIR ) + "/data/playlists/no-playlist.png" );
155 QVERIFY( QFile::exists( imageSourcePath ) );
156 QString targetPath;
157 targetPath = m_tmpCollectionDir->path() + '/' + "Pop/Thriller/cover.png";
158 QVERIFY( QFile::copy( m_sourcePath, targetPath ) );
159
160 // set an embedded image
161 targetPath = m_tmpCollectionDir->path() + '/' + "Various Artists/Big Screen Adventures/28 - Theme From Armageddon.mp3";
162 Meta::Tag::setEmbeddedCover( targetPath, QImage( 200, 200, QImage::Format_RGB32 ) );
163
164 fullScanAndWait();
165
166 // -- check the commit
167 QCOMPARE( m_scannedDirsCount, 5 );
168 QCOMPARE( m_scannedTracksCount, 10 );
169 QCOMPARE( m_scannedCoversCount, 1 );
170 }
171
172 void
slotStarted(GenericScanManager::ScanType type)173 TestGenericScanManager::slotStarted( GenericScanManager::ScanType type )
174 {
175 Q_UNUSED( type );
176
177 QVERIFY( !m_started );
178 QVERIFY( !m_finished );
179
180 m_started = true;
181 }
182
183 void
slotDirectoryCount(int count)184 TestGenericScanManager::slotDirectoryCount( int count )
185 {
186 Q_UNUSED( count );
187
188 QVERIFY( m_started );
189 QVERIFY( !m_finished );
190 }
191
192 void
slotDirectoryScanned(QSharedPointer<CollectionScanner::Directory> dir)193 TestGenericScanManager::slotDirectoryScanned( QSharedPointer<CollectionScanner::Directory> dir )
194 {
195 QVERIFY( m_started );
196 QVERIFY( !m_finished );
197
198 m_scannedDirsCount += 1;
199 m_scannedTracksCount += dir->tracks().count();
200 m_scannedCoversCount += dir->covers().count();
201 }
202
203 void
slotSucceeded()204 TestGenericScanManager::slotSucceeded()
205 {
206 QVERIFY( m_started );
207 QVERIFY( !m_finished );
208
209 m_finished = true;
210 }
211
212 void
slotFailed(const QString & message)213 TestGenericScanManager::slotFailed( const QString& message )
214 {
215 Q_UNUSED( message );
216
217 QVERIFY( m_started );
218 QVERIFY( !m_finished );
219
220 m_finished = true;
221 }
222
223 void
fullScanAndWait()224 TestGenericScanManager::fullScanAndWait()
225 {
226 QList<QUrl> urls;
227 urls << QUrl::fromLocalFile( m_tmpCollectionDir->path() );
228
229 QSignalSpy spy( m_scanManager, &GenericScanManager::succeeded );
230 m_scanManager->requestScan( urls );
231 waitScannerFinished( spy );
232
233 QVERIFY( m_started );
234 QVERIFY( m_finished );
235 }
236
237 void
waitScannerFinished(QSignalSpy & spy)238 TestGenericScanManager::waitScannerFinished( QSignalSpy &spy )
239 {
240 QVERIFY( m_scanManager->isRunning() );
241 QVERIFY2( spy.wait( 5000 ), "ScanManager didn't finish scan within timeout" );
242 // m_scanManager needs a little time to delete its worker job after it emits succeeded.
243 int wait = 0;
244 while( wait < 50 && m_scanManager->isRunning() )
245 {
246 wait++;
247 usleep( 100 );
248 }
249 QVERIFY( !m_scanManager->isRunning() );
250 }
251
252 void
createTrack(const Meta::FieldHash & values)253 TestGenericScanManager::createTrack( const Meta::FieldHash &values )
254 {
255 // -- copy the file from our original
256 QVERIFY( values.contains( Meta::valUrl ) );
257 const QString targetPath = m_tmpCollectionDir->path() + '/' + values.value( Meta::valUrl ).toString();
258 QVERIFY( QDir( m_tmpCollectionDir->path() ).mkpath( QFileInfo( values.value( Meta::valUrl ).toString() ).path() ) );
259
260 QVERIFY( QFile::copy( m_sourcePath, targetPath ) );
261
262 // -- set all the values that we need
263 Meta::Tag::writeTags( targetPath, values, true );
264 }
265
266 void
createSingleTrack()267 TestGenericScanManager::createSingleTrack()
268 {
269 Meta::FieldHash values;
270
271 values.insert( Meta::valUniqueId, QVariant("794b1bd040d5dd9b5b45c1494d84cc82") );
272 values.insert( Meta::valUrl, QVariant("Various Artists/Big Screen Adventures/28 - Theme From Armageddon.mp3") );
273 values.insert( Meta::valFormat, QVariant("1") );
274 values.insert( Meta::valTitle, QVariant("Theme From Armageddon") );
275 values.insert( Meta::valArtist, QVariant("Soundtrack & Theme Orchestra") );
276 values.insert( Meta::valAlbumArtist, QVariant("Theme Orchestra") );
277 values.insert( Meta::valAlbum, QVariant("Big Screen Adventures") );
278 values.insert( Meta::valComposer, QVariant("Unknown Composer") );
279 values.insert( Meta::valComment, QVariant("Amazon.com Song ID: 210541237") );
280 values.insert( Meta::valGenre, QVariant("Broadway & Vocalists") );
281 values.insert( Meta::valYear, QVariant(2009) );
282 values.insert( Meta::valTrackNr, QVariant(28) );
283 // values.insert( Meta::valBitrate, QVariant(216) ); // the bitrate can not be set. it's computed
284 // values.insert( Meta::valLength, QVariant(184000) ); // also can't be set
285 // values.insert( Meta::valSamplerate, QVariant(44100) ); // again
286 // values.insert( Meta::valFilesize, QVariant(5094892) ); // again
287 values.insert( Meta::valScore, QVariant(0.875) );
288 values.insert( Meta::valPlaycount, QVariant(5) );
289 // TODO: set an embedded cover
290
291 createTrack( values );
292 }
293
294 void
createAlbum()295 TestGenericScanManager::createAlbum()
296 {
297 Meta::FieldHash values;
298
299 values.insert( Meta::valUniqueId, QVariant("1dc7022c52a3e4c51b46577da9b3c8ff") );
300 values.insert( Meta::valUrl, QVariant("Pop/Thriller/Thriller - 01 - Michael Jackson - Track01.mp3") );
301 values.insert( Meta::valTitle, QVariant("Wanna Be Startin' Somethin'") );
302 values.insert( Meta::valArtist, QVariant("Michael Jackson") );
303 values.insert( Meta::valAlbum, QVariant("Thriller") );
304 values.insert( Meta::valYear, QVariant(1982) );
305 values.insert( Meta::valTrackNr, QVariant(1) );
306 createTrack( values );
307
308 values.clear();
309 values.insert( Meta::valUniqueId, QVariant("1dc708934a3e4c51b46577da9b3ab11") );
310 values.insert( Meta::valUrl, QVariant("Pop/Thriller/Thriller - 02 - Michael Jackson - Track02.mp3") );
311 values.insert( Meta::valTitle, QVariant("Baby Be Mine") );
312 values.insert( Meta::valArtist, QVariant("Michael Jackson") );
313 values.insert( Meta::valAlbum, QVariant("Thriller") );
314 values.insert( Meta::valYear, QVariant(1982) );
315 values.insert( Meta::valTrackNr, QVariant(2) );
316 createTrack( values );
317
318 values.clear();
319 values.insert( Meta::valUniqueId, QVariant("15a6b1bf79747fdc8e9c6b6f06203017") );
320 values.insert( Meta::valUrl, QVariant("Pop/Thriller/Thriller - 03 - Michael Jackson - Track03.mp3") );
321 values.insert( Meta::valTitle, QVariant("The Girl Is Mine") );
322 values.insert( Meta::valArtist, QVariant("Michael Jackson") );
323 values.insert( Meta::valAlbum, QVariant("Thriller") );
324 values.insert( Meta::valYear, QVariant(1982) );
325 values.insert( Meta::valTrackNr, QVariant(3) );
326 createTrack( values );
327
328 values.clear();
329 values.insert( Meta::valUniqueId, QVariant("4aba4c8b1d1893c03c112cc3c01221e9") );
330 values.insert( Meta::valUrl, QVariant("Pop/Thriller/Thriller - 04 - Michael Jackson - Track04.mp3") );
331 values.insert( Meta::valTitle, QVariant("Thriller") );
332 values.insert( Meta::valArtist, QVariant("Michael Jackson") );
333 values.insert( Meta::valAlbum, QVariant("Thriller") );
334 values.insert( Meta::valYear, QVariant(1982) );
335 values.insert( Meta::valTrackNr, QVariant(4) );
336 createTrack( values );
337
338 values.clear();
339 values.insert( Meta::valUniqueId, QVariant("cb44d2a3d8053829b04672723bf0bd6e") );
340 values.insert( Meta::valUrl, QVariant("Pop/Thriller/Thriller - 05 - Michael Jackson - Track05.mp3") );
341 values.insert( Meta::valTitle, QVariant("Beat It") );
342 values.insert( Meta::valArtist, QVariant("Michael Jackson") );
343 values.insert( Meta::valAlbum, QVariant("Thriller") );
344 values.insert( Meta::valYear, QVariant(1982) );
345 values.insert( Meta::valTrackNr, QVariant(5) );
346 createTrack( values );
347
348 values.clear();
349 values.insert( Meta::valUniqueId, QVariant("eba1858eeeb3c6d97fe3385200114d86") );
350 values.insert( Meta::valUrl, QVariant("Pop/Thriller/Thriller - 06 - Michael Jackson - Track06.mp3") );
351 values.insert( Meta::valTitle, QVariant("Billy Jean") );
352 values.insert( Meta::valArtist, QVariant("Michael Jackson") );
353 values.insert( Meta::valAlbum, QVariant("Thriller") );
354 values.insert( Meta::valYear, QVariant(1982) );
355 values.insert( Meta::valTrackNr, QVariant(6) );
356 createTrack( values );
357
358 values.clear();
359 values.insert( Meta::valUniqueId, QVariant("4623850290998486b0f7b39a2719904e") );
360 values.insert( Meta::valUrl, QVariant("Pop/Thriller/Thriller - 07 - Michael Jackson - Track07.mp3") );
361 values.insert( Meta::valTitle, QVariant("Human Nature") );
362 values.insert( Meta::valArtist, QVariant("Michael Jackson") );
363 values.insert( Meta::valAlbum, QVariant("Thriller") );
364 values.insert( Meta::valYear, QVariant(1982) );
365 values.insert( Meta::valTrackNr, QVariant(7) );
366 createTrack( values );
367
368 values.clear();
369 values.insert( Meta::valUniqueId, QVariant("6d9a7de13af1e16bb13a6208e44b046d") );
370 values.insert( Meta::valUrl, QVariant("Pop/Thriller/Thriller - 08 - Michael Jackson - Track08.mp3") );
371 values.insert( Meta::valTitle, QVariant("P.Y.T. (Pretty Young Thing)") );
372 values.insert( Meta::valArtist, QVariant("Michael Jackson") );
373 values.insert( Meta::valAlbum, QVariant("Thriller") );
374 values.insert( Meta::valYear, QVariant(1982) );
375 values.insert( Meta::valTrackNr, QVariant(8) );
376 createTrack( values );
377
378 values.clear();
379 values.insert( Meta::valUniqueId, QVariant("91cf9a7c0d255399f9f6babfacae432b") );
380 values.insert( Meta::valUrl, QVariant("Pop/Thriller/Thriller - 09 - Michael Jackson - Track09.mp3") );
381 values.insert( Meta::valTitle, QVariant("The Lady In My Life") );
382 values.insert( Meta::valArtist, QVariant("Michael Jackson") );
383 values.insert( Meta::valAlbum, QVariant("Thriller") );
384 values.insert( Meta::valYear, QVariant(1982) );
385 values.insert( Meta::valTrackNr, QVariant(9) );
386 createTrack( values );
387 }
388
389