File indexing completed on 2024-04-21 04:48:05

0001 /****************************************************************************************
0002  * Copyright (c) 2010 Maximilian Kossick <maximilian.kossick@googlemail.com>       *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #include "TestMasterSlaveSynchronizationJob.h"
0018 
0019 #include "core/support/Debug.h"
0020 #include "core/collections/CollectionLocation.h"
0021 #include "core/collections/CollectionLocationDelegate.h"
0022 #include "core/support/Components.h"
0023 #include "synchronization/MasterSlaveSynchronizationJob.h"
0024 
0025 #include "CollectionTestImpl.h"
0026 #include "core/collections/MockCollectionLocationDelegate.h"
0027 #include "mocks/MockTrack.h"
0028 #include "mocks/MockAlbum.h"
0029 #include "mocks/MockArtist.h"
0030 
0031 #include <gmock/gmock.h>
0032 
0033 #include <QSignalSpy>
0034 
0035 
0036 QTEST_GUILESS_MAIN( TestMasterSlaveSynchronizationJob )
0037 
0038 using ::testing::Return;
0039 using ::testing::AnyNumber;
0040 using ::testing::_;
0041 
0042 static int trackCopyCount;
0043 static int trackRemoveCount;
0044 
0045 namespace Collections {
0046 
0047 class MyCollectionLocation : public CollectionLocation
0048 {
0049 public:
0050     Collections::CollectionTestImpl *coll;
0051 
0052     QString prettyLocation() const override { return "foo"; }
0053     bool isWritable() const override { return true; }
0054 
0055     void removeUrlsFromCollection( const Meta::TrackList &sources ) override
0056     {
0057         trackRemoveCount += sources.count();
0058         coll->mc->acquireWriteLock();
0059         TrackMap map = coll->mc->trackMap();
0060         foreach( const Meta::TrackPtr &track, sources )
0061             map.remove( track->uidUrl() );
0062         coll->mc->setTrackMap( map );
0063         coll->mc->releaseLock();
0064         slotRemoveOperationFinished();
0065     }
0066 
0067     void copyUrlsToCollection(const QMap<Meta::TrackPtr, QUrl> &sources, const Transcoding::Configuration& conf) override
0068     {
0069         Q_UNUSED( conf )
0070         trackCopyCount = sources.count();
0071         foreach( const Meta::TrackPtr &track, sources.keys() )
0072         {
0073             coll->mc->addTrack( track );
0074         }
0075     }
0076 };
0077 
0078 class MyCollectionTestImpl : public CollectionTestImpl
0079 {
0080 public:
0081     MyCollectionTestImpl( const QString &id ) : CollectionTestImpl( id ) {}
0082 
0083     CollectionLocation* location() override
0084     {
0085         MyCollectionLocation *r = new MyCollectionLocation();
0086         r->coll = this;
0087         return r;
0088     }
0089 };
0090 
0091 } //namespace Collections
0092 
0093 void addMockTrack( Collections::CollectionTestImpl *coll, const QString &trackName, const QString &artistName, const QString &albumName )
0094 {
0095     Meta::MockTrack *track = new Meta::MockTrack();
0096     ::testing::Mock::AllowLeak( track );
0097     Meta::TrackPtr trackPtr( track );
0098     EXPECT_CALL( *track, name() ).Times( AnyNumber() ).WillRepeatedly( Return( trackName ) );
0099     EXPECT_CALL( *track, uidUrl() ).Times( AnyNumber() ).WillRepeatedly( Return( trackName + '_' + artistName + '_' + albumName ) );
0100     EXPECT_CALL( *track, playableUrl() ).Times( AnyNumber() ).WillRepeatedly( Return( QUrl( '/' + track->uidUrl() ) ) );
0101     coll->mc->addTrack( trackPtr );
0102 
0103     Meta::AlbumPtr albumPtr = coll->mc->albumMap().value( albumName, QString() /* no album artist */ );
0104     Meta::MockAlbum *album;
0105     Meta::TrackList albumTracks;
0106     if( albumPtr )
0107     {
0108         album = dynamic_cast<Meta::MockAlbum*>( albumPtr.data() );
0109         if( !album )
0110         {
0111             QFAIL( "expected a Meta::MockAlbum" );
0112             return;
0113         }
0114         albumTracks = albumPtr->tracks();
0115     }
0116     else
0117     {
0118         album = new Meta::MockAlbum();
0119         ::testing::Mock::AllowLeak( album );
0120         albumPtr = Meta::AlbumPtr( album );
0121         EXPECT_CALL( *album, name() ).Times( AnyNumber() ).WillRepeatedly( Return( albumName ) );
0122         EXPECT_CALL( *album, hasAlbumArtist() ).Times( AnyNumber() ).WillRepeatedly( Return( false ) );
0123         EXPECT_CALL( *album, albumArtist() ).Times( AnyNumber() ).WillRepeatedly( Return( Meta::ArtistPtr() ) );
0124         coll->mc->addAlbum( albumPtr );
0125     }
0126     albumTracks << trackPtr;
0127     EXPECT_CALL( *album, tracks() ).Times( AnyNumber() ).WillRepeatedly( Return( albumTracks ) );
0128 
0129     EXPECT_CALL( *track, album() ).Times( AnyNumber() ).WillRepeatedly( Return( albumPtr ) );
0130 
0131     Meta::ArtistPtr artistPtr = coll->mc->artistMap().value( artistName );
0132     Meta::MockArtist *artist;
0133     Meta::TrackList artistTracks;
0134     if( artistPtr )
0135     {
0136         artist = dynamic_cast<Meta::MockArtist*>( artistPtr.data() );
0137         if( !artist )
0138         {
0139             QFAIL( "expected a Meta::MockArtist" );
0140             return;
0141         }
0142         artistTracks = artistPtr->tracks();
0143     }
0144     else
0145     {
0146         artist = new Meta::MockArtist();
0147         ::testing::Mock::AllowLeak( artist );
0148         artistPtr = Meta::ArtistPtr( artist );
0149         EXPECT_CALL( *artist, name() ).Times( AnyNumber() ).WillRepeatedly( Return( artistName ) );
0150         coll->mc->addArtist( artistPtr );
0151     }
0152     artistTracks << trackPtr;
0153     EXPECT_CALL( *artist, tracks() ).Times( AnyNumber() ).WillRepeatedly( Return( artistTracks ) );
0154     EXPECT_CALL( *track, artist() ).Times( AnyNumber() ).WillRepeatedly( Return( artistPtr ) );
0155 }
0156 
0157 TestMasterSlaveSynchronizationJob::TestMasterSlaveSynchronizationJob()
0158 {
0159     int argc = 1;
0160     char **argv = (char **) malloc(sizeof(char *));
0161     argv[0] = strdup( QCoreApplication::applicationName().toLocal8Bit().data() );
0162     ::testing::InitGoogleMock( &argc, argv );
0163     qRegisterMetaType<Meta::TrackList>();
0164     qRegisterMetaType<Meta::AlbumList>();
0165     qRegisterMetaType<Meta::ArtistList>();
0166 }
0167 
0168 void
0169 TestMasterSlaveSynchronizationJob::init()
0170 {
0171     trackCopyCount = 0;
0172     trackRemoveCount = 0;
0173 }
0174 
0175 void
0176 TestMasterSlaveSynchronizationJob::testAddTracksToEmptySlave()
0177 {
0178     Collections::CollectionTestImpl *master = new Collections::MyCollectionTestImpl( "master" );
0179     Collections::CollectionTestImpl *slave = new Collections::MyCollectionTestImpl( "slave" );
0180 
0181     //setup master
0182     addMockTrack( master, "track1", "artist1", "album1" );
0183     QCOMPARE( master->mc->trackMap().count(), 1 );
0184     QCOMPARE( slave->mc->trackMap().count(), 0 );
0185     QCOMPARE( trackCopyCount, 0 );
0186     QCOMPARE( trackRemoveCount, 0 );
0187 
0188     MasterSlaveSynchronizationJob *job = new MasterSlaveSynchronizationJob();
0189     QSignalSpy spy( job, &MasterSlaveSynchronizationJob::destroyed );
0190     job->setMaster( master );
0191     job->setSlave( slave );
0192     job->synchronize();
0193     spy.wait( 1000 );
0194 
0195     QCOMPARE( trackCopyCount, 1 );
0196     QCOMPARE( trackRemoveCount, 0 );
0197     QCOMPARE( master->mc->trackMap().count(), 1 );
0198     QCOMPARE( slave->mc->trackMap().count(), 1 );
0199     delete master;
0200     delete slave;
0201 }
0202 
0203 void
0204 TestMasterSlaveSynchronizationJob::testAddSingleTrack()
0205 {
0206     Collections::CollectionTestImpl *master = new Collections::MyCollectionTestImpl( "master" );
0207     Collections::CollectionTestImpl *slave = new Collections::MyCollectionTestImpl( "slave" );
0208 
0209     //setup
0210     addMockTrack( master, "track1", "artist1", "album1" );
0211     addMockTrack( slave, "track1", "artist1", "album1" );
0212     addMockTrack( master, "track2", "artist1", "album1" );
0213 
0214     QCOMPARE( master->mc->trackMap().count(), 2 );
0215     QCOMPARE( slave->mc->trackMap().count(), 1 );
0216     QCOMPARE( trackCopyCount, 0 );
0217     QCOMPARE( trackRemoveCount, 0 );
0218 
0219     //test
0220     MasterSlaveSynchronizationJob *job = new MasterSlaveSynchronizationJob();
0221     QSignalSpy spy( job, &MasterSlaveSynchronizationJob::destroyed );
0222     job->setMaster( master );
0223     job->setSlave( slave );
0224     job->synchronize();
0225     spy.wait( 1000 );
0226 
0227     //verify
0228     QCOMPARE( trackCopyCount, 1 );
0229     QCOMPARE( trackRemoveCount, 0 );
0230     QCOMPARE( master->mc->trackMap().count(), 2 );
0231     QCOMPARE( slave->mc->trackMap().count(), 2 );
0232 
0233     delete master;
0234     delete slave;
0235 }
0236 
0237 void
0238 TestMasterSlaveSynchronizationJob::testAddAlbum()
0239 {
0240     Collections::CollectionTestImpl *master = new Collections::MyCollectionTestImpl( "master" );
0241     Collections::CollectionTestImpl *slave = new Collections::MyCollectionTestImpl( "slave" );
0242 
0243     //setup
0244     addMockTrack( master, "track1", "artist1", "album1" );
0245     addMockTrack( slave, "track1", "artist1", "album1" );
0246     addMockTrack( master, "track1", "artist1", "album2" );
0247 
0248     QCOMPARE( master->mc->trackMap().count(), 2 );
0249     QCOMPARE( slave->mc->trackMap().count(), 1 );
0250     QCOMPARE( trackCopyCount, 0 );
0251     QCOMPARE( trackRemoveCount, 0 );
0252 
0253     //test
0254     MasterSlaveSynchronizationJob *job = new MasterSlaveSynchronizationJob();
0255     QSignalSpy spy( job, &MasterSlaveSynchronizationJob::destroyed );
0256     job->setMaster( master );
0257     job->setSlave( slave );
0258     job->synchronize();
0259     spy.wait( 1000 );
0260 
0261     //verify
0262     QCOMPARE( trackCopyCount, 1 );
0263     QCOMPARE( trackRemoveCount, 0 );
0264     QCOMPARE( master->mc->trackMap().count(), 2 );
0265     QCOMPARE( slave->mc->trackMap().count(), 2 );
0266 
0267     delete master;
0268     delete slave;
0269 }
0270 
0271 void
0272 TestMasterSlaveSynchronizationJob::testAddArtist()
0273 {
0274     Collections::CollectionTestImpl *master = new Collections::MyCollectionTestImpl( "master" );
0275     Collections::CollectionTestImpl *slave = new Collections::MyCollectionTestImpl( "slave" );
0276 
0277     //setup
0278     addMockTrack( master, "track1", "artist1", "album1" );
0279     addMockTrack( slave, "track1", "artist1", "album1" );
0280     addMockTrack( master, "track1", "artist2", "album1" );
0281 
0282     QCOMPARE( master->mc->trackMap().count(), 2 );
0283     QCOMPARE( slave->mc->trackMap().count(), 1 );
0284     QCOMPARE( trackCopyCount, 0 );
0285     QCOMPARE( trackRemoveCount, 0 );
0286 
0287     //test
0288     MasterSlaveSynchronizationJob *job = new MasterSlaveSynchronizationJob();
0289     QSignalSpy spy( job, &MasterSlaveSynchronizationJob::destroyed );
0290     job->setMaster( master );
0291     job->setSlave( slave );
0292     job->synchronize();
0293     spy.wait( 1000 );
0294 
0295     //verify
0296     QCOMPARE( trackCopyCount, 1 );
0297     QCOMPARE( trackRemoveCount, 0 );
0298     QCOMPARE( master->mc->trackMap().count(), 2 );
0299     QCOMPARE( slave->mc->trackMap().count(), 2 );
0300 
0301     delete master;
0302     delete slave;
0303 }
0304 
0305 void
0306 TestMasterSlaveSynchronizationJob::testRemoveSingleTrack()
0307 {
0308     Collections::CollectionTestImpl *master = new Collections::MyCollectionTestImpl( "master" );
0309     Collections::CollectionTestImpl *slave = new Collections::MyCollectionTestImpl( "slave" );
0310 
0311     Collections::MockCollectionLocationDelegate *delegate = new Collections::MockCollectionLocationDelegate();
0312     EXPECT_CALL( *delegate, reallyDelete( _, _) ).Times( AnyNumber() ).WillRepeatedly( Return( true ) );
0313     Amarok::Components::setCollectionLocationDelegate( delegate );
0314 
0315     //setup
0316     addMockTrack( master, "track1", "artist1", "album1" );
0317     addMockTrack( slave, "track1", "artist1", "album1" );
0318     addMockTrack( slave, "track2", "artist1", "album1" );
0319 
0320     QCOMPARE( master->mc->trackMap().count(), 1 );
0321     QCOMPARE( slave->mc->trackMap().count(), 2 );
0322     QCOMPARE( trackCopyCount, 0 );
0323     QCOMPARE( trackRemoveCount, 0 );
0324 
0325     //test
0326     MasterSlaveSynchronizationJob *job = new MasterSlaveSynchronizationJob();
0327     QSignalSpy spy( job, &MasterSlaveSynchronizationJob::destroyed );
0328     job->setMaster( master );
0329     job->setSlave( slave );
0330     job->synchronize();
0331     spy.wait( 1000 );
0332 
0333     //verify
0334     QCOMPARE( trackCopyCount, 0 );
0335     QCOMPARE( trackRemoveCount, 1 );
0336     QCOMPARE( master->mc->trackMap().count(), 1 );
0337     QCOMPARE( slave->mc->trackMap().count(), 1 );
0338 
0339     delete master;
0340     delete slave;
0341     delete Amarok::Components::setCollectionLocationDelegate( nullptr );
0342 }
0343 
0344 void
0345 TestMasterSlaveSynchronizationJob::testRemoveAlbum()
0346 {
0347     Collections::CollectionTestImpl *master = new Collections::MyCollectionTestImpl( "master" );
0348     Collections::CollectionTestImpl *slave = new Collections::MyCollectionTestImpl( "slave" );
0349 
0350     Collections::MockCollectionLocationDelegate *delegate = new Collections::MockCollectionLocationDelegate();
0351     EXPECT_CALL( *delegate, reallyDelete( _, _) ).Times( AnyNumber() ).WillRepeatedly( Return( true ) );
0352     Amarok::Components::setCollectionLocationDelegate( delegate );
0353 
0354     //setup
0355     addMockTrack( master, "track1", "artist1", "album1" );
0356     addMockTrack( slave, "track1", "artist1", "album1" );
0357     addMockTrack( slave, "track1", "artist1", "album2" );
0358 
0359     QCOMPARE( master->mc->trackMap().count(), 1 );
0360     QCOMPARE( slave->mc->trackMap().count(), 2 );
0361     QCOMPARE( trackCopyCount, 0 );
0362     QCOMPARE( trackRemoveCount, 0 );
0363 
0364     //test
0365     MasterSlaveSynchronizationJob *job = new MasterSlaveSynchronizationJob();
0366     QSignalSpy spy( job, &MasterSlaveSynchronizationJob::destroyed );
0367     job->setMaster( master );
0368     job->setSlave( slave );
0369     job->synchronize();
0370     spy.wait( 1000 );
0371 
0372     //verify
0373     QCOMPARE( trackCopyCount, 0 );
0374     QCOMPARE( trackRemoveCount, 1 );
0375     QCOMPARE( master->mc->trackMap().count(), 1 );
0376     QCOMPARE( slave->mc->trackMap().count(), 1 );
0377 
0378     delete master;
0379     delete slave;
0380     delete Amarok::Components::setCollectionLocationDelegate( nullptr );
0381 }
0382 
0383 void
0384 TestMasterSlaveSynchronizationJob::testRemoveArtist()
0385 {
0386     Collections::CollectionTestImpl *master = new Collections::MyCollectionTestImpl( "master" );
0387     Collections::CollectionTestImpl *slave = new Collections::MyCollectionTestImpl( "slave" );
0388 
0389     Collections::MockCollectionLocationDelegate *delegate = new Collections::MockCollectionLocationDelegate();
0390     EXPECT_CALL( *delegate, reallyDelete( _, _) ).Times( AnyNumber() ).WillRepeatedly( Return( true ) );
0391     Amarok::Components::setCollectionLocationDelegate( delegate );
0392 
0393     //setup
0394     addMockTrack( master, "track1", "artist1", "album1" );
0395     addMockTrack( slave, "track1", "artist1", "album1" );
0396     addMockTrack( slave, "track1", "artist2", "album1" );
0397 
0398     QCOMPARE( master->mc->trackMap().count(), 1 );
0399     QCOMPARE( slave->mc->trackMap().count(), 2 );
0400     QCOMPARE( trackCopyCount, 0 );
0401     QCOMPARE( trackRemoveCount, 0 );
0402 
0403     //test
0404     MasterSlaveSynchronizationJob *job = new MasterSlaveSynchronizationJob();
0405     QSignalSpy spy( job, &MasterSlaveSynchronizationJob::destroyed );
0406     job->setMaster( master );
0407     job->setSlave( slave );
0408     job->synchronize();
0409     spy.wait( 1000 );
0410 
0411     //verify
0412     QCOMPARE( trackCopyCount, 0 );
0413     QCOMPARE( trackRemoveCount, 1 );
0414     QCOMPARE( master->mc->trackMap().count(), 1 );
0415     QCOMPARE( slave->mc->trackMap().count(), 1 );
0416 
0417     delete master;
0418     delete slave;
0419     delete Amarok::Components::setCollectionLocationDelegate( nullptr );
0420 }
0421 
0422 void
0423 TestMasterSlaveSynchronizationJob::testEmptyMaster()
0424 {
0425     Collections::CollectionTestImpl *master = new Collections::MyCollectionTestImpl( "master" );
0426     Collections::CollectionTestImpl *slave = new Collections::MyCollectionTestImpl( "slave" );
0427 
0428     Collections::MockCollectionLocationDelegate *delegate = new Collections::MockCollectionLocationDelegate();
0429     EXPECT_CALL( *delegate, reallyDelete( _, _) ).Times( AnyNumber() ).WillRepeatedly( Return( true ) );
0430     Amarok::Components::setCollectionLocationDelegate( delegate );
0431 
0432     //setup master
0433     addMockTrack( slave, "track1", "artist1", "album1" );
0434     QCOMPARE( master->mc->trackMap().count(), 0 );
0435     QCOMPARE( slave->mc->trackMap().count(), 1 );
0436     QCOMPARE( trackCopyCount, 0 );
0437     QCOMPARE( trackRemoveCount, 0 );
0438 
0439     MasterSlaveSynchronizationJob *job = new MasterSlaveSynchronizationJob();
0440     QSignalSpy spy( job, &MasterSlaveSynchronizationJob::destroyed );
0441     job->setMaster( master );
0442     job->setSlave( slave );
0443     job->synchronize();
0444     spy.wait( 1000 );
0445 
0446     QCOMPARE( trackCopyCount, 0 );
0447     QCOMPARE( trackRemoveCount, 1 );
0448     QCOMPARE( master->mc->trackMap().count(), 0 );
0449     QCOMPARE( slave->mc->trackMap().count(), 0 );
0450     delete master;
0451     delete slave;
0452     delete Amarok::Components::setCollectionLocationDelegate( nullptr );
0453 }