File indexing completed on 2024-04-28 04:48:06

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 "TestSingleCollectionTreeItemModel.h"
0018 
0019 #include "amarokconfig.h"
0020 #include "core/meta/Meta.h"
0021 #include "browsers/CollectionTreeItemModelBase.h"
0022 #include "browsers/SingleCollectionTreeItemModel.h"
0023 
0024 #include "CollectionTestImpl.h"
0025 #include "mocks/MockTrack.h"
0026 #include "mocks/MockAlbum.h"
0027 #include "mocks/MockArtist.h"
0028 
0029 #include <QApplication>
0030 #include <QModelIndex>
0031 #include <QSet>
0032 #include <QSignalSpy>
0033 #include <QStringList>
0034 
0035 #include <gmock/gmock.h>
0036 
0037 using ::testing::Return;
0038 using ::testing::AnyNumber;
0039 using ::testing::_;
0040 
0041 QTEST_MAIN( TestSingleCollectionTreeItemModel )
0042 
0043 void addMockTrack( Collections::CollectionTestImpl *coll, const QString &trackName, const QString &artistName, const QString &albumName )
0044 {
0045     Meta::MockTrack *track = new Meta::MockTrack();
0046     ::testing::Mock::AllowLeak( track );
0047     Meta::TrackPtr trackPtr( track );
0048     EXPECT_CALL( *track, name() ).Times( AnyNumber() ).WillRepeatedly( Return( trackName ) );
0049     EXPECT_CALL( *track, prettyName() ).Times( AnyNumber() ).WillRepeatedly( Return( trackName ) );
0050     EXPECT_CALL( *track, uidUrl() ).Times( AnyNumber() ).WillRepeatedly( Return( trackName + '_' + artistName + '_' + albumName ) );
0051     EXPECT_CALL( *track, playableUrl() ).Times( AnyNumber() ).WillRepeatedly( Return( QUrl( '/' + track->uidUrl() ) ) );
0052     EXPECT_CALL( *track, composer() ).Times( AnyNumber() ).WillRepeatedly( Return( Meta::ComposerPtr() ) );
0053     EXPECT_CALL( *track, genre() ).Times( AnyNumber() ).WillRepeatedly( Return( Meta::GenrePtr() ) );
0054     EXPECT_CALL( *track, year() ).Times( AnyNumber() ).WillRepeatedly( Return( Meta::YearPtr() ) );
0055     coll->mc->addTrack( trackPtr );
0056 
0057     Meta::AlbumPtr albumPtr = coll->mc->albumMap().value( albumName, QString() /* no album artist */ );
0058     Meta::MockAlbum *album;
0059     Meta::TrackList albumTracks;
0060     if( albumPtr )
0061     {
0062         album = dynamic_cast<Meta::MockAlbum*>( albumPtr.data() );
0063         if( !album )
0064         {
0065             QFAIL( "expected a Meta::MockAlbum" );
0066             return;
0067         }
0068         albumTracks = albumPtr->tracks();
0069     }
0070     else
0071     {
0072         album = new Meta::MockAlbum();
0073         ::testing::Mock::AllowLeak( album );
0074         albumPtr = Meta::AlbumPtr( album );
0075         EXPECT_CALL( *album, name() ).Times( AnyNumber() ).WillRepeatedly( Return( albumName ) );
0076         EXPECT_CALL( *album, prettyName() ).Times( AnyNumber() ).WillRepeatedly( Return( albumName ) );
0077         EXPECT_CALL( *album, hasAlbumArtist() ).Times( AnyNumber() ).WillRepeatedly( Return( false ) );
0078         EXPECT_CALL( *album, isCompilation() ).Times( AnyNumber() ).WillRepeatedly( Return( false ) ); //inconsistent
0079         coll->mc->addAlbum( albumPtr );
0080     }
0081     albumTracks << trackPtr;
0082     EXPECT_CALL( *album, tracks() ).Times( AnyNumber() ).WillRepeatedly( Return( albumTracks ) );
0083 
0084     EXPECT_CALL( *track, album() ).Times( AnyNumber() ).WillRepeatedly( Return( albumPtr ) );
0085 
0086     Meta::ArtistPtr artistPtr = coll->mc->artistMap().value( artistName );
0087     Meta::MockArtist *artist;
0088     Meta::TrackList artistTracks;
0089     if( artistPtr )
0090     {
0091         artist = dynamic_cast<Meta::MockArtist*>( artistPtr.data() );
0092         if( !artist )
0093         {
0094             QFAIL( "expected a Meta::MockArtist" );
0095             return;
0096         }
0097         artistTracks = artistPtr->tracks();
0098     }
0099     else
0100     {
0101         artist = new Meta::MockArtist();
0102         ::testing::Mock::AllowLeak( artist );
0103         artistPtr = Meta::ArtistPtr( artist );
0104         EXPECT_CALL( *artist, name() ).Times( AnyNumber() ).WillRepeatedly( Return( artistName ) );
0105         EXPECT_CALL( *artist, prettyName() ).Times( AnyNumber() ).WillRepeatedly( Return( artistName ) );
0106         coll->mc->addArtist( artistPtr );
0107     }
0108     artistTracks << trackPtr;
0109     EXPECT_CALL( *artist, tracks() ).Times( AnyNumber() ).WillRepeatedly( Return( artistTracks ) );
0110     EXPECT_CALL( *track, artist() ).Times( AnyNumber() ).WillRepeatedly( Return( artistPtr ) );
0111     EXPECT_CALL( *album, albumArtist() ).Times( AnyNumber() ).WillRepeatedly( Return( artistPtr ) );
0112 }
0113 
0114 void
0115 TestSingleCollectionTreeItemModel::initTestCase()
0116 {
0117     qRegisterMetaType<Meta::TrackList>();
0118     qRegisterMetaType<Meta::AlbumList>();
0119     qRegisterMetaType<Meta::ArtistList>();
0120     qRegisterMetaType<Meta::DataList>();
0121     qRegisterMetaType<Meta::GenreList>();
0122     qRegisterMetaType<Meta::ComposerList>();
0123     qRegisterMetaType<Meta::YearList>();
0124     qRegisterMetaType<Meta::LabelList>();
0125 
0126     AmarokConfig::instance("amarokrc");
0127 }
0128 
0129 #define loadChildren( itemModel, idx ) \
0130 { \
0131     if( itemModel->canFetchMore( idx ) ) { \
0132         QSignalSpy spy( itemModel, &SingleCollectionTreeItemModel::allQueriesFinished ); \
0133         itemModel->fetchMore( idx ); \
0134         QVERIFY( spy.wait( 5000 ) ); \
0135     } \
0136 }
0137 
0138 void
0139 TestSingleCollectionTreeItemModel::testAddNewArtist()
0140 {
0141     Collections::CollectionTestImpl *coll = new Collections::CollectionTestImpl( "test" );
0142     addMockTrack( coll, "track1", "artist1", "album1" );
0143 
0144     QList<CategoryId::CatMenuId> levels;
0145     levels<< CategoryId::Artist << CategoryId::Album;
0146 
0147     SingleCollectionTreeItemModel *model = new SingleCollectionTreeItemModel( coll, levels );
0148 
0149     loadChildren( model, QModelIndex() );
0150 
0151     QCOMPARE( model->rowCount( QModelIndex() ), 1 );
0152 
0153     {
0154         QModelIndex artist1Index = model->index( 0, 0, QModelIndex() );
0155         QCOMPARE( model->data( artist1Index, Qt::DisplayRole ).toString(), QString( "artist1" ) );
0156     }
0157 
0158     addMockTrack( coll, "track2", "artist2", "album2" );
0159 
0160     model->slotFilter();
0161 
0162     loadChildren( model, QModelIndex() );
0163 
0164     QCOMPARE( model->rowCount( QModelIndex() ), 2 );
0165 
0166     QSet<QString> artists;
0167 
0168     QModelIndex idx1 = model->index( 0, 0, QModelIndex() );
0169     artists << model->data( idx1, Qt::DisplayRole ).toString();
0170 
0171     QModelIndex idx2 = model->index( 1, 0, QModelIndex() );
0172     artists << model->data( idx2, Qt::DisplayRole ).toString();
0173 
0174     {
0175         QSet<QString> expected;
0176         expected << "artist1" << "artist2";
0177         QCOMPARE( artists, expected );
0178     }
0179 
0180     delete model;
0181     delete coll;
0182 }
0183 
0184 void
0185 TestSingleCollectionTreeItemModel::testRemoveArtist()
0186 {
0187     Collections::CollectionTestImpl *coll = new Collections::CollectionTestImpl( "test" );
0188     addMockTrack( coll, "track1", "artist1", "album1" );
0189     addMockTrack( coll, "track2", "artist2", "album2" );
0190 
0191     QList<CategoryId::CatMenuId> levels;
0192     levels<< CategoryId::Artist << CategoryId::Album;
0193 
0194     SingleCollectionTreeItemModel *model = new SingleCollectionTreeItemModel( coll, levels );
0195 
0196     loadChildren( model, QModelIndex() );
0197 
0198     QCOMPARE( model->rowCount( QModelIndex() ), 2 );
0199 
0200     {
0201         QSet<QString> artists;
0202 
0203         QModelIndex idx1 = model->index( 0, 0, QModelIndex() );
0204         artists << model->data( idx1, Qt::DisplayRole ).toString();
0205 
0206         QModelIndex idx2 = model->index( 1, 0, QModelIndex() );
0207         artists << model->data( idx2, Qt::DisplayRole ).toString();
0208 
0209         QSet<QString> expected;
0210         expected << "artist1" << "artist2";
0211         QCOMPARE( artists, expected );
0212     }
0213 
0214     ArtistMap map = coll->mc->artistMap();
0215     map.remove( "artist2" );  //album and track are still part of the collection
0216     coll->mc->setArtistMap( map );
0217 
0218     model->slotFilter();
0219 
0220     loadChildren( model, QModelIndex() );
0221 
0222     QCOMPARE( model->rowCount( QModelIndex() ), 1 );
0223 
0224     {
0225         QModelIndex artist1Index = model->index( 0, 0, QModelIndex() );
0226         QCOMPARE( model->data( artist1Index, Qt::DisplayRole ).toString(), QString( "artist1" ) );
0227     }
0228 
0229     delete model;
0230     delete coll;
0231 }
0232 
0233 void
0234 TestSingleCollectionTreeItemModel::testAddTrack()
0235 {
0236     Collections::CollectionTestImpl *coll = new Collections::CollectionTestImpl( "test" );
0237     addMockTrack( coll, "track1", "artist1", "album1" );
0238     addMockTrack( coll, "track2", "artist2", "album2" );
0239 
0240     QList<CategoryId::CatMenuId> levels;
0241     levels<< CategoryId::Artist << CategoryId::Album;
0242 
0243     SingleCollectionTreeItemModel *model = new SingleCollectionTreeItemModel( coll, levels );
0244 
0245     loadChildren( model, QModelIndex() );
0246 
0247     QCOMPARE( model->rowCount( QModelIndex() ), 2 );
0248 
0249     {
0250         QSet<QString> artists;
0251 
0252         QModelIndex idx1 = model->index( 0, 0, QModelIndex() );
0253         artists << model->data( idx1, Qt::DisplayRole ).toString();
0254 
0255         QModelIndex idx2 = model->index( 1, 0, QModelIndex() );
0256         artists << model->data( idx2, Qt::DisplayRole ).toString();
0257 
0258         QSet<QString> expected;
0259         expected << "artist1" << "artist2";
0260         QCOMPARE( artists, expected );
0261     }
0262 
0263     for( int i = 0; i < 2; i++ )
0264     {
0265         QModelIndex parent = model->index( i, 0, QModelIndex() );
0266         loadChildren( model, parent );
0267         QCOMPARE( model->rowCount( parent ), 1 );
0268 
0269         QModelIndex subParent = model->index( 0, 0, parent );
0270         loadChildren( model, subParent );
0271         QCOMPARE( model->rowCount( subParent ), 1 );
0272     }
0273 
0274     addMockTrack( coll, "track3", "artist1", "album1" );
0275 
0276     model->slotFilter();
0277 
0278     QTest::qWait( 30 );
0279 
0280     loadChildren( model, QModelIndex() );
0281 
0282     QCOMPARE( model->rowCount( QModelIndex() ), 2 );
0283 
0284     for( int i = 0; i < 2; i++ )
0285     {
0286         QModelIndex parent = model->index( i, 0, QModelIndex() );
0287         loadChildren( model, parent );
0288         QCOMPARE( model->rowCount( parent ), 1 );
0289 
0290         QString name = model->data( parent, Qt::DisplayRole ).toString();
0291         int count = (name == "artist1" ? 2 : 1 );
0292 
0293         QModelIndex subParent = model->index( 0, 0, parent );
0294         loadChildren( model, subParent );
0295         QCOMPARE( model->rowCount( subParent ), count );
0296     }
0297 
0298     delete model;
0299     delete coll;
0300 }
0301 
0302 void
0303 TestSingleCollectionTreeItemModel::testRemoveTrack()
0304 {
0305 
0306 }
0307 
0308 void
0309 TestSingleCollectionTreeItemModel::testAddTrackWithFilter()
0310 {
0311     Collections::CollectionTestImpl *coll = new Collections::CollectionTestImpl( "test" );
0312     addMockTrack( coll, "track1", "artist1", "album1" );
0313 
0314     QList<CategoryId::CatMenuId> levels;
0315     levels << CategoryId::Artist << CategoryId::Album;
0316 
0317     SingleCollectionTreeItemModel *model = new SingleCollectionTreeItemModel( coll, levels );
0318 
0319     loadChildren( model, QModelIndex() );
0320     QCOMPARE( model->rowCount( QModelIndex() ), 1 );
0321 
0322     {
0323         QModelIndex artist1Index = model->index( 0, 0, QModelIndex() );
0324         QCOMPARE( model->data( artist1Index, Qt::DisplayRole ).toString(), QString( "artist1" ) );
0325     }
0326 
0327     addMockTrack( coll, "track2", "artist2", "album2" );
0328     model->setCurrentFilter( "track2" );
0329     model->slotFilter();
0330     loadChildren( model, QModelIndex() );
0331     QCOMPARE( model->rowCount( QModelIndex() ), 1 );
0332 
0333     model->setCurrentFilter( QString() );
0334     model->slotFilter();
0335     loadChildren( model, QModelIndex() );
0336     QCOMPARE( model->rowCount( QModelIndex() ), 2 );
0337 
0338     QModelIndex idx1 = model->index( 0, 0, QModelIndex() );
0339     QCOMPARE( model->data( idx1, Qt::DisplayRole ).toString(), QString( "artist2" ) );
0340 
0341     delete model;
0342     delete coll;
0343 }