1
/****************************************************************************************
2
* Copyright (c) 2010 Maximilian Kossick <maximilian.kossick@googlemail.com> *
4
* This program is free software; you can redistribute it and/or modify it under *
5
* the terms of the GNU General Public License as published by the Free Software *
6
* Foundation; either version 2 of the License, or (at your option) any later *
9
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
10
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
11
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
13
* You should have received a copy of the GNU General Public License along with *
14
* this program. If not, see <http://www.gnu.org/licenses/>. *
15
****************************************************************************************/
17
#include "TestSqlTrack.h"
19
#include "core/support/Debug.h"
20
#include "DefaultSqlQueryMakerFactory.h"
21
#include "core/meta/Meta.h"
22
#include "mysqlecollection/MySqlEmbeddedStorage.h"
24
#include "SqlCollection.h"
26
#include "SqlRegistry.h"
27
#include "SqlMountPointManagerMock.h"
29
#include "MetaNotificationSpy.h"
34
#include <qtest_kde.h>
36
QTEST_KDEMAIN_CORE( TestSqlTrack )
38
TestSqlTrack::TestSqlTrack()
47
TestSqlTrack::initTestCase()
49
m_tmpDir = new KTempDir();
50
m_storage = new MySqlEmbeddedStorage( m_tmpDir->name() );
51
m_collection = new Collections::SqlCollection( "testId", "testtrack", m_storage );
52
m_collection->setMountPointManager( new SqlMountPointManagerMock( this, m_storage ) );
54
// I just need the table and not the whole playlist manager
55
m_storage->query( QString( "CREATE TABLE playlist_tracks ("
56
" id " + m_storage->idType() +
57
", playlist_id INTEGER "
58
", track_num INTEGER "
59
", url " + m_storage->exactTextColumnType() +
60
", title " + m_storage->textColumnType() +
61
", album " + m_storage->textColumnType() +
62
", artist " + m_storage->textColumnType() +
64
", uniqueid " + m_storage->textColumnType(128) + ") ENGINE = MyISAM;" ) );
69
TestSqlTrack::cleanupTestCase()
72
//m_storage is deleted by SqlCollection
80
m_storage->query( "INSERT INTO artists(id, name) VALUES (1, 'artist1');" );
81
m_storage->query( "INSERT INTO artists(id, name) VALUES (2, 'artist2');" );
82
m_storage->query( "INSERT INTO artists(id, name) VALUES (3, 'artist3');" );
84
m_storage->query( "INSERT INTO albums(id,name,artist) VALUES(1,'album1',1);" );
85
m_storage->query( "INSERT INTO albums(id,name,artist) VALUES(2,'album2',1);" );
86
m_storage->query( "INSERT INTO albums(id,name,artist) VALUES(3,'album3',2);" );
87
m_storage->query( "INSERT INTO albums(id,name,artist) VALUES(4,'album-compilation',0);" );
89
m_storage->query( "INSERT INTO composers(id, name) VALUES (1, 'composer1');" );
90
m_storage->query( "INSERT INTO composers(id, name) VALUES (2, 'composer2');" );
91
m_storage->query( "INSERT INTO composers(id, name) VALUES (3, 'composer3');" );
93
m_storage->query( "INSERT INTO genres(id, name) VALUES (1, 'genre1');" );
94
m_storage->query( "INSERT INTO genres(id, name) VALUES (2, 'genre2');" );
95
m_storage->query( "INSERT INTO genres(id, name) VALUES (3, 'genre3');" );
97
m_storage->query( "INSERT INTO years(id, name) VALUES (1, '1');" );
98
m_storage->query( "INSERT INTO years(id, name) VALUES (2, '2');" );
99
m_storage->query( "INSERT INTO years(id, name) VALUES (3, '3');" );
101
m_storage->query( "INSERT INTO urls(id,deviceid,rpath,uniqueid) VALUES (1, -1, './IDoNotExist.mp3','1');" );
102
m_storage->query( "INSERT INTO urls(id,deviceid,rpath,uniqueid) VALUES (2, -1, './IDoNotExistAsWell.mp3','2');" );
103
m_storage->query( "INSERT INTO urls(id,deviceid,rpath,uniqueid) VALUES (3, -1, './MeNeither.mp3','3');" );
104
m_storage->query( "INSERT INTO urls(id,deviceid,rpath,uniqueid) VALUES (4, -1, './NothingHere.mp3','4');" );
106
m_storage->query( "INSERT INTO tracks(id,url,title,comment,artist,album,genre,year,composer) "
107
"VALUES(1,1,'track1','comment1',1,1,1,1,1);" );
108
m_storage->query( "INSERT INTO tracks(id,url,title,comment,artist,album,genre,year,composer) "
109
"VALUES(2,2,'track2','comment2',1,2,1,1,1);" );
111
m_collection->registry()->emptyCache();
115
TestSqlTrack::cleanup()
117
m_storage->query( "TRUNCATE TABLE years;" );
118
m_storage->query( "TRUNCATE TABLE genres;" );
119
m_storage->query( "TRUNCATE TABLE composers;" );
120
m_storage->query( "TRUNCATE TABLE albums;" );
121
m_storage->query( "TRUNCATE TABLE artists;" );
122
m_storage->query( "TRUNCATE TABLE tracks;" );
123
m_storage->query( "TRUNCATE TABLE urls;" );
124
m_storage->query( "TRUNCATE TABLE statistics;" );
125
m_storage->query( "TRUNCATE TABLE labels;" );
126
m_storage->query( "TRUNCATE TABLE urls_labels;" );
131
TestSqlTrack::setAllValues( Meta::SqlTrack *track )
133
track->setTitle( "New Title" );
134
track->setAlbum( "New Album" );
135
track->setArtist( "New Artist" );
136
track->setComposer( "New Composer" );
137
track->setYear( 1999 );
138
track->setGenre( "New Genre" );
140
track->setUrl( -1, "./new_url", 2 );
142
track->setBpm( 32.0 );
143
track->setComment( "New Comment" );
145
track->setScore( 64.0 );
146
track->setRating( 5 );
148
track->setLength( 5000 );
149
track->setSampleRate( 4400 );
150
track->setBitrate( 128 );
152
track->setTrackNumber( 4 );
153
track->setDiscNumber( 1 );
155
track->setFirstPlayed( QDateTime::fromTime_t(100) );
156
track->setLastPlayed( QDateTime::fromTime_t(200) );
157
track->setPlayCount( 20 );
159
Meta::ReplayGainTag modes[] = { Meta::ReplayGain_Track_Gain,
160
Meta::ReplayGain_Track_Peak,
161
Meta::ReplayGain_Album_Gain,
162
Meta::ReplayGain_Album_Peak };
164
for( int i=0; i<4; i++ )
165
track->setReplayGain( modes[i], qreal(i) );
167
track->addLabel( "New Label" );
171
TestSqlTrack::getAllValues( Meta::SqlTrack *track )
173
QCOMPARE( track->name(), QString( "New Title" ) );
174
QCOMPARE( track->album()->name(), QString( "New Album" ) );
175
QCOMPARE( track->artist()->name(), QString( "New Artist" ) );
176
QCOMPARE( track->composer()->name(), QString( "New Composer" ) );
177
QCOMPARE( track->year()->name(), QString( "1999" ) );
178
QCOMPARE( track->genre()->name(), QString( "New Genre" ) );
180
QCOMPARE( track->playableUrl().path(), QString( "/new_url" ) );
181
QCOMPARE( track->bpm(), 32.0 );
182
QCOMPARE( track->comment(), QString( "New Comment" ) );
184
QCOMPARE( track->score(), 64.0 );
185
QCOMPARE( track->rating(), 5 );
187
QCOMPARE( track->length(), qint64(5000) );
188
QCOMPARE( track->sampleRate(), 4400 );
189
QCOMPARE( track->bitrate(), 128 );
191
QCOMPARE( track->trackNumber(), 4 );
192
QCOMPARE( track->discNumber(), 1 );
194
QCOMPARE( track->firstPlayed(), QDateTime::fromTime_t(100) );
195
QCOMPARE( track->lastPlayed(), QDateTime::fromTime_t(200) );
196
QCOMPARE( track->playCount(), 20 );
198
Meta::ReplayGainTag modes[] = { Meta::ReplayGain_Track_Gain,
199
Meta::ReplayGain_Track_Peak,
200
Meta::ReplayGain_Album_Gain,
201
Meta::ReplayGain_Album_Peak };
203
for( int i=0; i<4; i++ )
204
QCOMPARE( track->replayGain( modes[i] ), qreal(i) );
206
QVERIFY( track->labels().count() > 0 );
207
QVERIFY( track->labels().contains( m_collection->registry()->getLabel("New Label") ) );
210
/** Check that the registry always returns the same track pointer */
212
TestSqlTrack::testGetTrack()
215
Meta::TrackPtr track1 = m_collection->registry()->getTrack( 1 );
216
Meta::TrackPtr track2 = m_collection->registry()->getTrack( "/IDoNotExist.mp3" );
217
Meta::TrackPtr track3 = m_collection->registry()->getTrackFromUid( "1" );
220
QVERIFY( track1 == track2 );
221
QVERIFY( track1 == track3 );
224
// and also after empty cache
225
m_collection->registry()->emptyCache();
229
Meta::TrackPtr track2 = m_collection->registry()->getTrack( "/IDoNotExist.mp3" );
230
Meta::TrackPtr track3 = m_collection->registry()->getTrackFromUid( "1" );
231
Meta::TrackPtr track1 = m_collection->registry()->getTrack( 1 );
234
QVERIFY( track1 == track2 );
235
QVERIFY( track1 == track3 );
238
// do again creating a new track
240
m_collection->registry()->emptyCache();
244
Meta::TrackPtr track1 = m_collection->registry()->getTrack( -1, "./newTrack.mp3", 2, "amarok-sqltrackuid://newuid" );
245
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
246
sqlTrack1->setBpm( 100 ); // have to commit the new track
249
QCOMPARE( track1->playableUrl().path(), QString("/newTrack.mp3" ));
250
QCOMPARE( track1->uidUrl(), QString("amarok-sqltrackuid://newuid" ));
253
m_collection->registry()->emptyCache();
257
Meta::TrackPtr track1 = m_collection->registry()->getTrackFromUid("amarok-sqltrackuid://newuid");
260
QCOMPARE( track1->playableUrl().path(), QString("/newTrack.mp3" ));
261
QCOMPARE( track1->uidUrl(), QString("amarok-sqltrackuid://newuid" ));
262
QCOMPARE( track1->bpm(), 100.0 );
267
TestSqlTrack::testSetAllValuesSingleNotExisting()
271
Meta::TrackPtr track1 = m_collection->registry()->getTrack( -1, "./IamANewTrack.mp3", 0, "mb-1e34fb213489" );
273
QSignalSpy spy( m_collection, SIGNAL(updated()));
274
MetaNotificationSpy metaSpy;
275
metaSpy.subscribeTo( track1 );
277
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
278
setAllValues( sqlTrack1 );
279
getAllValues( sqlTrack1 );
281
// new track should have an up-to-date create time (not more than 3 seconds old)
282
QVERIFY( track1->createDate().secsTo(QDateTime::currentDateTime()) < 3 );
284
QVERIFY( metaSpy.notificationsFromTracks().count() > 1 ); // we should be notified about the changes
287
// and also after empty cache
288
m_collection->registry()->emptyCache();
291
Meta::TrackPtr track1 = m_collection->registry()->getTrack( "/new_url" );
292
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
294
getAllValues( sqlTrack1 );
298
/** Set all track values but before that create them in the registry. */
300
TestSqlTrack::testSetAllValuesSingleExisting()
303
Meta::GenrePtr genre = m_collection->registry()->getGenre( "New Genre" );
304
Meta::ComposerPtr composer = m_collection->registry()->getComposer( "New Composer" );
305
Meta::YearPtr year = m_collection->registry()->getYear( 1999 );
306
Meta::AlbumPtr album = m_collection->registry()->getAlbum( "New Album", "New Artist" );
307
m_collection->registry()->getLabel( "New Label" );
309
Meta::TrackPtr track1 = m_collection->registry()->getTrack( "/IDoNotExist.mp3" );
311
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
312
setAllValues( sqlTrack1 );
313
getAllValues( sqlTrack1 );
315
// check that the existing object are really updated with the new tracklist
316
QCOMPARE( genre->tracks().count(), 1 );
317
QCOMPARE( genre->tracks().first().data(), track1.data() );
319
QCOMPARE( composer->tracks().count(), 1 );
320
QCOMPARE( composer->tracks().first().data(), track1.data() );
322
QCOMPARE( year->tracks().count(), 1 );
323
QCOMPARE( year->tracks().first().data(), track1.data() );
325
// the logic, how renaming the track artist influences its album is still
326
// unfinished. For sure the track must be in an album with the defined
328
QCOMPARE( sqlTrack1->album()->name(), QString("New Album") );
329
QCOMPARE( sqlTrack1->album()->tracks().count(), 1 );
330
QCOMPARE( sqlTrack1->album()->tracks().first().data(), track1.data() );
333
// and also after empty cache
334
m_collection->registry()->emptyCache();
337
Meta::TrackPtr track1 = m_collection->registry()->getTrack( "/new_url" );
338
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
340
getAllValues( sqlTrack1 );
342
Meta::GenrePtr genre = m_collection->registry()->getGenre( "New Genre" );
343
Meta::ComposerPtr composer = m_collection->registry()->getComposer( "New Composer" );
344
Meta::YearPtr year = m_collection->registry()->getYear( 1999 );
345
Meta::AlbumPtr album = m_collection->registry()->getAlbum( "New Album", "New Artist" );
347
// check that the existing object are really updated with the new tracklist
348
QCOMPARE( genre->tracks().count(), 1 );
349
QCOMPARE( genre->tracks().first().data(), track1.data() );
351
QCOMPARE( composer->tracks().count(), 1 );
352
QCOMPARE( composer->tracks().first().data(), track1.data() );
354
QCOMPARE( year->tracks().count(), 1 );
355
QCOMPARE( year->tracks().first().data(), track1.data() );
357
// the logic, how renaming the track artist influences its album is still
358
// unfinished. For sure the track must be in an album with the defined
360
QCOMPARE( sqlTrack1->album()->name(), QString("New Album") );
361
QCOMPARE( sqlTrack1->album()->tracks().count(), 1 );
362
QCOMPARE( sqlTrack1->album()->tracks().first().data(), track1.data() );
367
TestSqlTrack::testSetAllValuesBatch()
370
Meta::TrackPtr track1 = m_collection->registry()->getTrack( "/IDoNotExist.mp3" );
371
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
373
QSignalSpy spy( m_collection, SIGNAL(updated()));
374
MetaNotificationSpy metaSpy;
375
metaSpy.subscribeTo( track1 );
377
sqlTrack1->beginMetaDataUpdate();
379
setAllValues( sqlTrack1 );
380
QCOMPARE( metaSpy.notificationsFromTracks().count(), 1 ); // add label does one notify
382
sqlTrack1->endMetaDataUpdate();
383
QCOMPARE( metaSpy.notificationsFromTracks().count(), 2 ); // only one notificate for all the changes
385
getAllValues( sqlTrack1 );
388
// and also after empty cache
389
m_collection->registry()->emptyCache();
392
Meta::TrackPtr track1 = m_collection->registry()->getTrack( "/new_url" );
393
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
395
getAllValues( sqlTrack1 );
400
TestSqlTrack::testUnsetValues()
403
Meta::TrackPtr track1 = m_collection->registry()->getTrack( "/IDoNotExist.mp3" );
404
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
406
setAllValues( sqlTrack1 );
408
// now unset the values again
409
sqlTrack1->setAlbum( "" );
410
sqlTrack1->setArtist( "" );
411
sqlTrack1->setComposer( "" );
412
sqlTrack1->setYear( 0 ); // it is not clear what an empty year exacly is
413
sqlTrack1->setGenre( "" );
415
// note: Amarok is still not clear if an empty artist means track->artist() == 0
416
QVERIFY( !track1->album() || track1->album()->name().isEmpty() );
417
QVERIFY( !track1->artist() || track1->artist()->name().isEmpty() );
418
QVERIFY( !track1->composer() || track1->composer()->name().isEmpty() );
419
QVERIFY( !track1->year() || track1->year()->year() == 0 );
420
QVERIFY( !track1->genre() || track1->genre()->name().isEmpty() );
423
// and also after empty cache
424
m_collection->registry()->emptyCache();
427
Meta::TrackPtr track1 = m_collection->registry()->getTrack( "/new_url" );
429
QVERIFY( !track1->album() || track1->album()->name().isEmpty() );
430
QVERIFY( !track1->artist() || track1->artist()->name().isEmpty() );
431
QVERIFY( !track1->composer() || track1->composer()->name().isEmpty() );
432
QVERIFY( !track1->year() || track1->year()->year() == 0 );
433
QVERIFY( !track1->genre() || track1->genre()->name().isEmpty() );
438
TestSqlTrack::testFinishedPlaying()
440
Meta::TrackPtr track1 = m_collection->registry()->getTrack( "/IDoNotExist.mp3" );
441
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
443
sqlTrack1->setLength( 5000 );
445
QCOMPARE( sqlTrack1->score(), 0.0 );
446
QCOMPARE( sqlTrack1->playCount(), 0 );
447
QVERIFY( !sqlTrack1->firstPlayed().isValid() );
448
QVERIFY( !sqlTrack1->lastPlayed().isValid() );
450
// now play the track not really
451
sqlTrack1->finishedPlaying( 0.1 );
453
// can't do a statement about the score here
454
QCOMPARE( sqlTrack1->playCount(), 0 );
455
QVERIFY( !sqlTrack1->firstPlayed().isValid() );
456
QVERIFY( !sqlTrack1->lastPlayed().isValid() );
458
// and now really play it
459
sqlTrack1->finishedPlaying( 1.0 );
461
QVERIFY( sqlTrack1->score() > 0.0 );
462
QCOMPARE( sqlTrack1->playCount(), 1 );
463
QVERIFY( sqlTrack1->firstPlayed().secsTo( QDateTime::currentDateTime() ) < 2 );
464
QVERIFY( sqlTrack1->lastPlayed().secsTo( QDateTime::currentDateTime() ) < 2 );
469
TestSqlTrack::testAlbumRemaingsNonCompilationAfterChangingAlbumName()
471
m_storage->query( "INSERT INTO tracks(id,url,title,artist,album,genre,year,composer) "
472
"VALUES (3,3,'track1',1,1,1,1,1 );" );
473
m_storage->query( "INSERT INTO tracks(id,url,title,artist,album,genre,year,composer) "
474
"VALUES (4,4,'track2',1,1,1,1,1 );" );
476
Meta::TrackPtr track1 = m_collection->registry()->getTrack( 3 );
477
Meta::TrackPtr track2 = m_collection->registry()->getTrack( 4 );
479
QCOMPARE( track1->album()->name(), QString( "album1" ) );
480
QVERIFY( track1->album()->hasAlbumArtist() );
481
QCOMPARE( track1->album().data(), track2->album().data() );
483
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
484
sqlTrack1->setAlbum( "album2" );
485
Meta::SqlTrack *sqlTrack2 = static_cast<Meta::SqlTrack*>( track2.data() );
486
sqlTrack2->beginMetaDataUpdate();
487
sqlTrack2->setAlbum( "album2" );
488
sqlTrack2->endMetaDataUpdate();
490
QCOMPARE( track1->album()->name(), QString( "album2" ) );
491
QVERIFY( track1->album()->hasAlbumArtist() );
492
QVERIFY( track1->album() == track2->album() );
496
TestSqlTrack::testAlbumRemainsCompilationAfterChangingAlbumName()
498
m_storage->query( "INSERT INTO tracks(id,url,title,artist,album,genre,year,composer) "
499
"VALUES (3,3,'track1',1,4,1,1,1 );" );
500
m_storage->query( "INSERT INTO tracks(id,url,title,artist,album,genre,year,composer) "
501
"VALUES (4,4,'track2',1,4,1,1,1 );" );
503
Meta::TrackPtr track1 = m_collection->registry()->getTrack( 3 );
504
Meta::TrackPtr track2 = m_collection->registry()->getTrack( 4 );
507
QVERIFY( track1->album() );
509
QVERIFY( track2->album() );
510
QCOMPARE( track1->album()->name(), QString( "album-compilation" ) );
511
QVERIFY( track1->album()->isCompilation() );
512
QVERIFY( track1->album().data() == track2->album().data() );
514
Meta::SqlTrack *sqlTrack1 = static_cast<Meta::SqlTrack*>( track1.data() );
515
Meta::SqlTrack *sqlTrack2 = static_cast<Meta::SqlTrack*>( track2.data() );
516
sqlTrack1->setAlbum( "album2" );
517
sqlTrack2->beginMetaDataUpdate();
518
sqlTrack2->setAlbum( "album2" );
519
sqlTrack2->endMetaDataUpdate();
521
QCOMPARE( track1->album()->name(), QString( "album2" ) );
522
QVERIFY( track1->album()->isCompilation() );
523
QVERIFY( track1->album() == track2->album() );
527
TestSqlTrack::testRemoveLabelFromTrack()
529
Meta::TrackPtr track = m_collection->registry()->getTrack( "/IDoNotExist.mp3" );
530
Meta::LabelPtr label = m_collection->registry()->getLabel( "A" );
531
track->addLabel( label );
532
QCOMPARE( track->labels().count(), 1 );
534
track->removeLabel( label );
535
QCOMPARE( track->labels().count(), 0 );
537
QStringList urlsLabelsCount = m_storage->query( "SELECT COUNT(*) FROM urls_labels;" );
538
QCOMPARE( urlsLabelsCount.first().toInt(), 0 );
542
TestSqlTrack::testRemoveLabelFromTrackWhenNotInCache()
544
m_storage->query( "INSERT INTO labels(id,label) VALUES (1,'A');" );
545
m_storage->query( "INSERT INTO urls_labels(url,label) VALUES (1,1);" );
547
Meta::TrackPtr track = m_collection->registry()->getTrack( "/IDoNotExist.mp3" );
548
Meta::LabelPtr label = m_collection->registry()->getLabel( "A" );
550
track->removeLabel( label );
551
QCOMPARE( track->labels().count(), 0 );
553
QStringList urlsLabelsCount = m_storage->query( "SELECT COUNT(*) FROM urls_labels;" );
554
QCOMPARE( urlsLabelsCount.first().toInt(), 0 );
557
#include "TestSqlTrack.moc"