From kde-commits Tue Oct 31 22:12:28 2017 From: Matthieu Gallien Date: Tue, 31 Oct 2017 22:12:28 +0000 To: kde-commits Subject: [elisa] /: increase test coverage of DatabaseInterface and fix bugs during tracks removal Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=150948796328939 Git commit ec5a51caa9f53b391e230165b557286e54acc377 by Matthieu Gallien. Committed on 31/10/2017 at 22:04. Pushed by mgallien into branch 'master'. increase test coverage of DatabaseInterface and fix bugs during tracks remo= val M +306 -22 autotests/databaseinterfacetest.cpp M +143 -43 src/databaseinterface.cpp M +4 -0 src/databaseinterface.h https://commits.kde.org/elisa/ec5a51caa9f53b391e230165b557286e54acc377 diff --git a/autotests/databaseinterfacetest.cpp b/autotests/databaseinterf= acetest.cpp index 870bee6..205d166 100644 --- a/autotests/databaseinterfacetest.cpp +++ b/autotests/databaseinterfacetest.cpp @@ -1467,9 +1467,14 @@ private Q_SLOTS: = void removeOneTrack() { + QTemporaryFile databaseFile; + databaseFile.open(); + + qDebug() << "removeOneTrack" << databaseFile.fileName(); + DatabaseInterface musicDb; = - musicDb.init(QStringLiteral("testDb")); + musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); = QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::art= istAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albu= mAdded); @@ -1636,30 +1641,35 @@ private Q_SLOTS: QCOMPARE(firstAlbumTracksCount, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum, false); = - auto firstTrackId =3D musicDb.trackIdFromTitleAlbumArtist(QStringL= iteral("track1"), QStringLiteral("album1"), QStringLiteral("artist1")); + auto firstTrackId =3D musicDb.trackIdFromTitleAlbumArtist(QStringL= iteral("track1"), QStringLiteral("album2"), QStringLiteral("artist1")); auto firstTrack =3D musicDb.trackFromDatabaseId(firstTrackId); - auto secondTrackId =3D musicDb.trackIdFromTitleAlbumArtist(QString= Literal("track2"), QStringLiteral("album1"), QStringLiteral("artist2")); + auto secondTrackId =3D musicDb.trackIdFromTitleAlbumArtist(QString= Literal("track2"), QStringLiteral("album2"), QStringLiteral("artist1")); auto secondTrack =3D musicDb.trackFromDatabaseId(secondTrackId); - auto thirdTrackId =3D musicDb.trackIdFromTitleAlbumArtist(QStringL= iteral("track3"), QStringLiteral("album1"), QStringLiteral("artist3")); + auto thirdTrackId =3D musicDb.trackIdFromTitleAlbumArtist(QStringL= iteral("track3"), QStringLiteral("album2"), QStringLiteral("artist1")); auto thirdTrack =3D musicDb.trackFromDatabaseId(thirdTrackId); - auto fourthTrackId =3D musicDb.trackIdFromTitleAlbumArtist(QString= Literal("track4"), QStringLiteral("album1"), QStringLiteral("artist4")); + auto fourthTrackId =3D musicDb.trackIdFromTitleAlbumArtist(QString= Literal("track4"), QStringLiteral("album2"), QStringLiteral("artist1")); auto fourthTrack =3D musicDb.trackFromDatabaseId(fourthTrackId); + auto fithTrackId =3D musicDb.trackIdFromTitleAlbumArtist(QStringLi= teral("track5"), QStringLiteral("album2"), QStringLiteral("artist1")); + auto fithTrack =3D musicDb.trackFromDatabaseId(fithTrackId); + auto sixthTrackId =3D musicDb.trackIdFromTitleAlbumArtist(QStringL= iteral("track6"), QStringLiteral("album2"), QStringLiteral("artist1 and art= ist2")); + auto sixthTrack =3D musicDb.trackFromDatabaseId(sixthTrackId); = - musicDb.removeTracksList({firstTrack.resourceURI(), secondTrack.re= sourceURI(), thirdTrack.resourceURI(), fourthTrack.resourceURI()}); + musicDb.removeTracksList({firstTrack.resourceURI(), secondTrack.re= sourceURI(), thirdTrack.resourceURI(), + fourthTrack.resourceURI(), fithTrack.res= ourceURI(), sixthTrack.resourceURI()}); = QCOMPARE(musicDb.allAlbums().count(), 2); - QCOMPARE(musicDb.allArtists().count(), 3); + QCOMPARE(musicDb.allArtists().count(), 5); QCOMPARE(musicDbArtistAddedSpy.count(), 6); QCOMPARE(musicDbAlbumAddedSpy.count(), 3); QCOMPARE(musicDbTrackAddedSpy.count(), 13); - QCOMPARE(musicDbArtistRemovedSpy.count(), 3); + QCOMPARE(musicDbArtistRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumRemovedSpy.count(), 1); - QCOMPARE(musicDbTrackRemovedSpy.count(), 4); + QCOMPARE(musicDbTrackRemovedSpy.count(), 6); QCOMPARE(musicDbArtistModifiedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 3); QCOMPARE(musicDbTrackModifiedSpy.count(), 1); = - auto removedAlbum =3D musicDb.albumFromTitle(QStringLiteral("album= 1")); + auto removedAlbum =3D musicDb.albumFromTitle(QStringLiteral("album= 2")); = QCOMPARE(removedAlbum.isValid(), false); } @@ -1729,7 +1739,7 @@ private Q_SLOTS: QCOMPARE(firstAlbumTracksCount, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum, false); = - auto trackId =3D musicDb.trackIdFromTitleAlbumArtist(QStringLitera= l("track4"), QStringLiteral("album1"), QStringLiteral("artist4")); + auto trackId =3D musicDb.trackIdFromTitleAlbumArtist(QStringLitera= l("track3"), QStringLiteral("album1"), QStringLiteral("artist3")); auto track =3D musicDb.trackFromDatabaseId(trackId); = musicDb.removeTracksList({track.resourceURI()}); @@ -2163,17 +2173,17 @@ private Q_SLOTS: = void reloadDatabase() { - QTemporaryFile mDatabaseFile; - mDatabaseFile.open(); + QTemporaryFile databaseFile; + databaseFile.open(); = - qDebug() << "reloadDatabase" << mDatabaseFile.fileName(); + qDebug() << "reloadDatabase" << databaseFile.fileName(); = { DatabaseInterface musicDb; = QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::= trackAdded); = - musicDb.init(QStringLiteral("testDb"), mDatabaseFile.fileName(= )); + musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()= ); = musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLitera= l("autoTest")); = @@ -2205,7 +2215,7 @@ private Q_SLOTS: QCOMPARE(musicDbAlbumModifiedSpy2.count(), 0); QCOMPARE(musicDbTrackModifiedSpy2.count(), 0); = - musicDb2.init(QStringLiteral("testDb2"), mDatabaseFile.fileName()); + musicDb2.init(QStringLiteral("testDb2"), databaseFile.fileName()); = musicDbTrackAddedSpy2.wait(300); = @@ -2250,7 +2260,7 @@ private Q_SLOTS: = auto invalidTracks =3D musicDb2.allInvalidTracksFromSource(QString= Literal("autoTest")); = - QCOMPARE(invalidTracks.size(), 13); + QCOMPARE(invalidTracks.size(), 14); = auto tracksUrlsToRemove =3D QList(); = @@ -2276,17 +2286,17 @@ private Q_SLOTS: = void reloadDatabaseWithAllTracks() { - QTemporaryFile mDatabaseFile; - mDatabaseFile.open(); + QTemporaryFile databaseFile; + databaseFile.open(); = - qDebug() << "reloadDatabase" << mDatabaseFile.fileName(); + qDebug() << "reloadDatabaseWithAllTracks" << databaseFile.fileName= (); = { DatabaseInterface musicDb; = QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::= trackAdded); = - musicDb.init(QStringLiteral("testDb"), mDatabaseFile.fileName(= )); + musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()= ); = musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLitera= l("autoTest")); = @@ -2318,7 +2328,7 @@ private Q_SLOTS: QCOMPARE(musicDbAlbumModifiedSpy2.count(), 0); QCOMPARE(musicDbTrackModifiedSpy2.count(), 0); = - musicDb2.init(QStringLiteral("testDb2"), mDatabaseFile.fileName()); + musicDb2.init(QStringLiteral("testDb2"), databaseFile.fileName()); = musicDbTrackAddedSpy2.wait(300); = @@ -2375,6 +2385,280 @@ private Q_SLOTS: QCOMPARE(musicDbAlbumModifiedSpy2.count(), 1); QCOMPARE(musicDbTrackModifiedSpy2.count(), 1); } + + void reloadDatabaseAndCleanInvalidTracks() + { + QTemporaryFile databaseFile; + databaseFile.open(); + + qDebug() << "reloadDatabaseAndCleanInvalidTracks" << databaseFile.= fileName(); + + { + DatabaseInterface musicDb; + + QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::= trackAdded); + + musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()= ); + + musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLitera= l("autoTest")); + + musicDbTrackAddedSpy.wait(300); + } + + DatabaseInterface musicDb2; + + QSignalSpy musicDbArtistAddedSpy2(&musicDb2, &DatabaseInterface::a= rtistAdded); + QSignalSpy musicDbAlbumAddedSpy2(&musicDb2, &DatabaseInterface::al= bumAdded); + QSignalSpy musicDbTrackAddedSpy2(&musicDb2, &DatabaseInterface::tr= ackAdded); + QSignalSpy musicDbArtistRemovedSpy2(&musicDb2, &DatabaseInterface:= :artistRemoved); + QSignalSpy musicDbAlbumRemovedSpy2(&musicDb2, &DatabaseInterface::= albumRemoved); + QSignalSpy musicDbTrackRemovedSpy2(&musicDb2, &DatabaseInterface::= trackRemoved); + QSignalSpy musicDbArtistModifiedSpy2(&musicDb2, &DatabaseInterface= ::artistModified); + QSignalSpy musicDbAlbumModifiedSpy2(&musicDb2, &DatabaseInterface:= :albumModified); + QSignalSpy musicDbTrackModifiedSpy2(&musicDb2, &DatabaseInterface:= :trackModified); + + QCOMPARE(musicDb2.allAlbums().count(), 0); + QCOMPARE(musicDb2.allArtists().count(), 0); + QCOMPARE(musicDb2.allTracks().count(), 0); + QCOMPARE(musicDbArtistAddedSpy2.count(), 0); + QCOMPARE(musicDbAlbumAddedSpy2.count(), 0); + QCOMPARE(musicDbTrackAddedSpy2.count(), 0); + QCOMPARE(musicDbArtistRemovedSpy2.count(), 0); + QCOMPARE(musicDbAlbumRemovedSpy2.count(), 0); + QCOMPARE(musicDbTrackRemovedSpy2.count(), 0); + QCOMPARE(musicDbArtistModifiedSpy2.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy2.count(), 0); + QCOMPARE(musicDbTrackModifiedSpy2.count(), 0); + + musicDb2.init(QStringLiteral("testDb2"), databaseFile.fileName()); + + musicDbTrackAddedSpy2.wait(300); + + QCOMPARE(musicDb2.allAlbums().count(), 3); + QCOMPARE(musicDb2.allArtists().count(), 6); + QCOMPARE(musicDb2.allTracks().count(), 13); + QCOMPARE(musicDbArtistAddedSpy2.count(), 6); + QCOMPARE(musicDbAlbumAddedSpy2.count(), 3); + QCOMPARE(musicDbTrackAddedSpy2.count(), 13); + QCOMPARE(musicDbArtistRemovedSpy2.count(), 0); + QCOMPARE(musicDbAlbumRemovedSpy2.count(), 0); + QCOMPARE(musicDbTrackRemovedSpy2.count(), 0); + QCOMPARE(musicDbArtistModifiedSpy2.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy2.count(), 0); + QCOMPARE(musicDbTrackModifiedSpy2.count(), 0); + + musicDb2.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("= autoTest")); + + QCOMPARE(musicDb2.allAlbums().count(), 3); + QCOMPARE(musicDb2.allArtists().count(), 6); + QCOMPARE(musicDb2.allTracks().count(), 13); + QCOMPARE(musicDbArtistAddedSpy2.count(), 6); + QCOMPARE(musicDbAlbumAddedSpy2.count(), 3); + QCOMPARE(musicDbTrackAddedSpy2.count(), 13); + QCOMPARE(musicDbArtistRemovedSpy2.count(), 0); + QCOMPARE(musicDbAlbumRemovedSpy2.count(), 0); + QCOMPARE(musicDbTrackRemovedSpy2.count(), 0); + QCOMPARE(musicDbArtistModifiedSpy2.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy2.count(), 1); + QCOMPARE(musicDbTrackModifiedSpy2.count(), 1); + + musicDb2.cleanInvalidTracks(); + + QCOMPARE(musicDb2.allAlbums().count(), 3); + QCOMPARE(musicDb2.allArtists().count(), 6); + QCOMPARE(musicDb2.allTracks().count(), 13); + QCOMPARE(musicDbArtistAddedSpy2.count(), 6); + QCOMPARE(musicDbAlbumAddedSpy2.count(), 3); + QCOMPARE(musicDbTrackAddedSpy2.count(), 13); + QCOMPARE(musicDbArtistRemovedSpy2.count(), 0); + QCOMPARE(musicDbAlbumRemovedSpy2.count(), 0); + QCOMPARE(musicDbTrackRemovedSpy2.count(), 0); + QCOMPARE(musicDbArtistModifiedSpy2.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy2.count(), 1); + QCOMPARE(musicDbTrackModifiedSpy2.count(), 1); + } + + void testRemovalOfTracksFromInvalidSource() + { + DatabaseInterface musicDb; + + musicDb.init(QStringLiteral("testDb")); + + QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::art= istAdded); + QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albu= mAdded); + QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::trac= kAdded); + QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::a= rtistRemoved); + QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::al= bumRemoved); + QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::tr= ackRemoved); + QSignalSpy musicDbArtistModifiedSpy(&musicDb, &DatabaseInterface::= artistModified); + QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::a= lbumModified); + QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::t= rackModified); + + QCOMPARE(musicDb.allAlbums().count(), 0); + QCOMPARE(musicDb.allArtists().count(), 0); + QCOMPARE(musicDbArtistAddedSpy.count(), 0); + QCOMPARE(musicDbAlbumAddedSpy.count(), 0); + QCOMPARE(musicDbTrackAddedSpy.count(), 0); + QCOMPARE(musicDbArtistRemovedSpy.count(), 0); + QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); + QCOMPARE(musicDbTrackRemovedSpy.count(), 0); + QCOMPARE(musicDbArtistModifiedSpy.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); + QCOMPARE(musicDbTrackModifiedSpy.count(), 0); + + auto newFiles =3D QList(); + const auto &constNewTracks =3D mNewTracks; + for (const auto &oneTrack : constNewTracks) { + newFiles.push_back(oneTrack.resourceURI()); + } + + musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("a= utoTest")); + + musicDbTrackAddedSpy.wait(300); + + QCOMPARE(musicDb.allAlbums().count(), 3); + QCOMPARE(musicDb.allArtists().count(), 6); + QCOMPARE(musicDbArtistAddedSpy.count(), 6); + QCOMPARE(musicDbAlbumAddedSpy.count(), 3); + QCOMPARE(musicDbTrackAddedSpy.count(), 13); + QCOMPARE(musicDbArtistRemovedSpy.count(), 0); + QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); + QCOMPARE(musicDbTrackRemovedSpy.count(), 0); + QCOMPARE(musicDbArtistModifiedSpy.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy.count(), 3); + QCOMPARE(musicDbTrackModifiedSpy.count(), 1); + + musicDb.removeAllTracksFromSource(QStringLiteral("autoTestNotValid= ")); + + QCOMPARE(musicDb.allAlbums().count(), 3); + QCOMPARE(musicDb.allArtists().count(), 6); + QCOMPARE(musicDbArtistAddedSpy.count(), 6); + QCOMPARE(musicDbAlbumAddedSpy.count(), 3); + QCOMPARE(musicDbTrackAddedSpy.count(), 13); + QCOMPARE(musicDbArtistRemovedSpy.count(), 0); + QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); + QCOMPARE(musicDbTrackRemovedSpy.count(), 0); + QCOMPARE(musicDbArtistModifiedSpy.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy.count(), 3); + QCOMPARE(musicDbTrackModifiedSpy.count(), 1); + } + + void testRemovalOfTracksFromValidSource() + { + QTemporaryFile databaseFile; + databaseFile.open(); + + qDebug() << "testRemovalOfTracksFromValidSource" << databaseFile.f= ileName(); + + DatabaseInterface musicDb; + + musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); + + QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::art= istAdded); + QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albu= mAdded); + QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::trac= kAdded); + QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::a= rtistRemoved); + QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::al= bumRemoved); + QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::tr= ackRemoved); + QSignalSpy musicDbArtistModifiedSpy(&musicDb, &DatabaseInterface::= artistModified); + QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::a= lbumModified); + QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::t= rackModified); + + QCOMPARE(musicDb.allAlbums().count(), 0); + QCOMPARE(musicDb.allArtists().count(), 0); + QCOMPARE(musicDbArtistAddedSpy.count(), 0); + QCOMPARE(musicDbAlbumAddedSpy.count(), 0); + QCOMPARE(musicDbTrackAddedSpy.count(), 0); + QCOMPARE(musicDbArtistRemovedSpy.count(), 0); + QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); + QCOMPARE(musicDbTrackRemovedSpy.count(), 0); + QCOMPARE(musicDbArtistModifiedSpy.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); + QCOMPARE(musicDbTrackModifiedSpy.count(), 0); + + auto newFiles =3D QList(); + const auto &constNewTracks =3D mNewTracks; + for (const auto &oneTrack : constNewTracks) { + newFiles.push_back(oneTrack.resourceURI()); + } + + musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("a= utoTest")); + + musicDbTrackAddedSpy.wait(300); + + QCOMPARE(musicDb.allAlbums().count(), 3); + QCOMPARE(musicDb.allArtists().count(), 6); + QCOMPARE(musicDbArtistAddedSpy.count(), 6); + QCOMPARE(musicDbAlbumAddedSpy.count(), 3); + QCOMPARE(musicDbTrackAddedSpy.count(), 13); + QCOMPARE(musicDbArtistRemovedSpy.count(), 0); + QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); + QCOMPARE(musicDbTrackRemovedSpy.count(), 0); + QCOMPARE(musicDbArtistModifiedSpy.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy.count(), 3); + QCOMPARE(musicDbTrackModifiedSpy.count(), 1); + + QList secondNewTracks =3D { + {true, QStringLiteral("$20"), QStringLiteral("0"), QStringLite= ral("track1"), + QStringLiteral("artist6"), QStringLiteral("album6"), QStringL= iteral("artist6"), + 1, 1, QTime::fromMSecsSinceStartOfDay(1), {QUrl::fromLocalFil= e(QStringLiteral("/$20"))}, + {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 1, f= alse}, + {true, QStringLiteral("$21"), QStringLiteral("0"), QStringLite= ral("track2"), + QStringLiteral("artist6"), QStringLiteral("album6"), QStringL= iteral("artist6"), + 2, 1, QTime::fromMSecsSinceStartOfDay(2), {QUrl::fromLocalFil= e(QStringLiteral("/$21"))}, + {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 2, f= alse}, + {true, QStringLiteral("$22"), QStringLiteral("0"), QStringLite= ral("track3"), + QStringLiteral("artist6"), QStringLiteral("album6"), QStringL= iteral("artist6"), + 3, 1, QTime::fromMSecsSinceStartOfDay(3), {QUrl::fromLocalFil= e(QStringLiteral("/$22"))}, + {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 3, f= alse}, + {true, QStringLiteral("$23"), QStringLiteral("0"), QStringLite= ral("track4"), + QStringLiteral("artist6"), QStringLiteral("album6"), QStringL= iteral("artist6"), + 4, 1, QTime::fromMSecsSinceStartOfDay(4), {QUrl::fromLocalFil= e(QStringLiteral("/$23"))}, + {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 4, f= alse}, + {true, QStringLiteral("$24"), QStringLiteral("0"), QStringLite= ral("track5"), + QStringLiteral("artist6"), QStringLiteral("album6"), QStringL= iteral("artist6"), + 5, 1, QTime::fromMSecsSinceStartOfDay(4), {QUrl::fromLocalFil= e(QStringLiteral("/$24"))}, + {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 5, f= alse}, + {true, QStringLiteral("$25"), QStringLiteral("0"), QStringLite= ral("track6"), + QStringLiteral("artist6"), QStringLiteral("album6"), QStringL= iteral("artist6"), + 6, 1, QTime::fromMSecsSinceStartOfDay(5), {QUrl::fromLocalFil= e(QStringLiteral("/$25"))}, + {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 6, t= rue}, + {true, QStringLiteral("$2"), QStringLiteral("0"), QStringLiter= al("track2"), + QStringLiteral("artist2"), QStringLiteral("album1"), QStringL= iteral("Various Artists"), + 2, 2, QTime::fromMSecsSinceStartOfDay(2), {QUrl::fromLocalFil= e(QStringLiteral("/$26"))}, + {QUrl::fromLocalFile(QStringLiteral("file://image$2"))}, 2, f= alse}, + }; + + musicDb.insertTracksList(secondNewTracks, mNewCovers, QStringLiter= al("autoTestSource2")); + + musicDbTrackAddedSpy.wait(300); + + QCOMPARE(musicDb.allAlbums().count(), 4); + QCOMPARE(musicDb.allArtists().count(), 7); + QCOMPARE(musicDbArtistAddedSpy.count(), 7); + QCOMPARE(musicDbAlbumAddedSpy.count(), 4); + QCOMPARE(musicDbTrackAddedSpy.count(), 19); + QCOMPARE(musicDbArtistRemovedSpy.count(), 0); + QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); + QCOMPARE(musicDbTrackRemovedSpy.count(), 0); + QCOMPARE(musicDbArtistModifiedSpy.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy.count(), 5); + QCOMPARE(musicDbTrackModifiedSpy.count(), 2); + + musicDb.removeAllTracksFromSource(QStringLiteral("autoTest")); + + QCOMPARE(musicDb.allAlbums().count(), 2); + QCOMPARE(musicDb.allArtists().count(), 3); + QCOMPARE(musicDbArtistAddedSpy.count(), 7); + QCOMPARE(musicDbAlbumAddedSpy.count(), 4); + QCOMPARE(musicDbTrackAddedSpy.count(), 19); + QCOMPARE(musicDbArtistRemovedSpy.count(), 4); + QCOMPARE(musicDbAlbumRemovedSpy.count(), 2); + QCOMPARE(musicDbTrackRemovedSpy.count(), 12); + QCOMPARE(musicDbArtistModifiedSpy.count(), 0); + QCOMPARE(musicDbAlbumModifiedSpy.count(), 6); + QCOMPARE(musicDbTrackModifiedSpy.count(), 2); + } }; = QTEST_GUILESS_MAIN(DatabaseInterfaceTests) diff --git a/src/databaseinterface.cpp b/src/databaseinterface.cpp index 66ba9bd..a5857ee 100644 --- a/src/databaseinterface.cpp +++ b/src/databaseinterface.cpp @@ -59,7 +59,8 @@ public: mUpdateAlbumArtUriFromAlbumIdQuery(mTracksDatabase), mUpdateAlbu= mArtistFromAlbumIdQuery(mTracksDatabase), mInsertAlbumWithoutArtistQuery(mTracksDatabase), mSelectTracksMa= ppingPriorityByTrackId(mTracksDatabase), mSelectAllTrackFilesFromSourceQuery(mTracksDatabase), mFindInval= idTrackFilesQuery(mTracksDatabase), - mSelectAlbumIdsFromArtist(mTracksDatabase) + mSelectAlbumIdsFromArtist(mTracksDatabase), mRemoveTracksMapping= FromSource(mTracksDatabase), + mRemoveTracksMapping(mTracksDatabase), mSelectTracksWithoutMappi= ngQuery(mTracksDatabase) { } = @@ -145,6 +146,12 @@ public: = QSqlQuery mSelectAlbumIdsFromArtist; = + QSqlQuery mRemoveTracksMappingFromSource; + + QSqlQuery mRemoveTracksMapping; + + QSqlQuery mSelectTracksWithoutMappingQuery; + qulonglong mAlbumId =3D 1; = qulonglong mArtistId =3D 1; @@ -661,12 +668,13 @@ void DatabaseInterface::removeAllTracksFromSource(con= st QString &sourceName) = while(d->mSelectAllTrackFilesFromSourceQuery.next()) { auto fileName =3D d->mSelectAllTrackFilesFromSourceQuery.record().= value(0).toUrl(); + allFileNames.push_back(fileName); } = d->mSelectAllTrackFilesFromSourceQuery.finish(); = - internalRemoveTracksList(allFileNames); + internalRemoveTracksList(allFileNames, sourceId); = transactionResult =3D finishTransaction(); if (!transactionResult) { @@ -703,15 +711,17 @@ void DatabaseInterface::cleanInvalidTracks() } = QList allFileNames; + auto sourceId =3D qulonglong(); = while(d->mFindInvalidTrackFilesQuery.next()) { auto fileName =3D d->mFindInvalidTrackFilesQuery.record().value(0)= .toUrl(); + sourceId =3D d->mFindInvalidTrackFilesQuery.record().value(1).toUL= ongLong(); allFileNames.push_back(fileName); } = d->mFindInvalidTrackFilesQuery.finish(); = - internalRemoveTracksList(allFileNames); + internalRemoveTracksList(allFileNames, sourceId); = transactionResult =3D finishTransaction(); if (!transactionResult) { @@ -1034,7 +1044,7 @@ void DatabaseInterface::initDatabase() const QSqlQuery alterSchemaQuery(d->mTracksDatabase); = const auto &result =3D alterSchemaQuery.exec(QStringLiteral("A= LTER TABLE `Tracks` " - "AD= D COLUMN RATING INTEGER NOT NULL DEFAULT 0")); + "ADD= COLUMN RATING INTEGER NOT NULL DEFAULT 0")); = if (!result) { qDebug() << "DatabaseInterface::initDatabase" << alterSche= maQuery.lastError(); @@ -1174,8 +1184,8 @@ void DatabaseInterface::initRequest() = { auto selectAllArtistsWithFilterText =3D QStringLiteral("SELECT `ID= `, " - "`Name` " - "FROM `Artists= `"); + "`Name` " + "FROM `Artist= s`"); = auto result =3D d->mSelectAllArtistsQuery.prepare(selectAllArtists= WithFilterText); = @@ -1206,7 +1216,7 @@ void DatabaseInterface::initRequest() "artist.`ID` =3D tracks.= `ArtistID` AND " "tracks.`AlbumID` =3D al= bum.`ID` AND " "tracksMapping.`TrackID`= =3D tracks.`ID` AND " - "tracksMapping.`Priority= ` =3D 1"); + "tracksMapping.`Priority= ` =3D (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` =3D trac= ks.`ID`)"); = auto result =3D d->mSelectAllTracksQuery.prepare(selectAllTracksTe= xt); = @@ -1240,8 +1250,7 @@ void DatabaseInterface::initRequest() "s= ource.`Name` =3D :source AND " "s= ource.`ID` =3D tracksMapping.`DiscoverID` AND " "t= racksMapping.`TrackValid` =3D 0 AND " - "t= racksMapping.`TrackID` =3D tracks.`ID` AND " - "t= racksMapping.`Priority` =3D 1"); + "t= racksMapping.`TrackID` =3D tracks.`ID`"); = auto result =3D d->mSelectAllInvalidTracksFromSourceQuery.prepare(= selectAllInvalidTracksFromSourceQueryText); = @@ -1275,7 +1284,7 @@ void DatabaseInterface::initRequest() "source.`= Name` =3D :source AND " "source.`= ID` =3D tracksMapping.`DiscoverID` AND " "tracksMa= pping.`TrackID` =3D tracks.`ID` AND " - "tracksMa= pping.`Priority` =3D 1"); + "tracksMa= pping.`Priority` =3D (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `Tr= ackID` =3D tracks.`ID`)"); = auto result =3D d->mSelectAllTracksFromSourceQuery.prepare(selectA= llTracksFromSourceQueryText); = @@ -1302,7 +1311,7 @@ void DatabaseInterface::initRequest() = { auto insertArtistsText =3D QStringLiteral("INSERT INTO `Artists` (= `ID`, `Name`) " - "VALUES (:art= istId, :name)"); + "VALUES (:artistId, :name)= "); = auto result =3D d->mInsertArtistsQuery.prepare(insertArtistsText); = @@ -1334,7 +1343,7 @@ void DatabaseInterface::initRequest() "tracks.`AlbumID` =3D := albumId AND " "artist.`ID` =3D tracks= .`ArtistID` AND " "album.`ID` =3D :albumI= d AND " - "tracksMapping.`Priorit= y` =3D 1 " + "tracksMapping.`Priorit= y` =3D (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` =3D tra= cks.`ID`) " "ORDER BY tracks.`DiscN= umber` ASC, " "tracks.`TrackNumber` A= SC"); = @@ -1367,7 +1376,7 @@ void DatabaseInterface::initRequest() "artist.`ID` =3D = tracks.`ArtistID` AND " "tracks.`AlbumID`= =3D album.`ID` AND " "tracksMapping.`T= rackID` =3D tracks.`ID` AND " - "tracksMapping.`P= riority` =3D 1"); + "tracksMapping.`P= riority` =3D (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` = =3D tracks.`ID`)"); = auto result =3D d->mSelectTrackFromIdQuery.prepare(selectTrackFrom= IdQueryText); = @@ -1411,7 +1420,7 @@ void DatabaseInterface::initRequest() = { auto insertAlbumWithoutArtistQueryText =3D QStringLiteral("INSERT = INTO Albums (`ID`, `Title`, `CoverFileName`, `TracksCount`, `IsSingleDiscAl= bum`) " - "VALUES (:albumId, :tit= le, :coverFileName, :tracksCount, :isSingleDiscAlbum)"); + "VALUES (:= albumId, :title, :coverFileName, :tracksCount, :isSingleDiscAlbum)"); = auto result =3D d->mInsertAlbumWithoutArtistQuery.prepare(insertAl= bumWithoutArtistQueryText); = @@ -1422,7 +1431,7 @@ void DatabaseInterface::initRequest() = { auto insertTrackMappingQueryText =3D QStringLiteral("INSERT INTO `= TracksMapping` (`FileName`, `DiscoverID`, `Priority`, `TrackValid`) " - "VALUES (:fileName, :di= scoverId, :priority, 1)"); + "VALUES (:fileNa= me, :discoverId, :priority, 1)"); = auto result =3D d->mInsertTrackMapping.prepare(insertTrackMappingQ= ueryText); = @@ -1452,6 +1461,57 @@ void DatabaseInterface::initRequest() } } = + { + auto removeTracksMappingFromSourceQueryText =3D QStringLiteral("DE= LETE FROM `TracksMapping` " + "WHER= E `FileName` =3D :fileName AND `DiscoverID` =3D :sourceId"); + + auto result =3D d->mRemoveTracksMappingFromSource.prepare(removeTr= acksMappingFromSourceQueryText); + + if (!result) { + qDebug() << "DatabaseInterface::initRequest" << removeTracksMa= ppingFromSourceQueryText << d->mRemoveTracksMappingFromSource.lastError(); + } + } + + { + auto removeTracksMappingQueryText =3D QStringLiteral("DELETE FROM = `TracksMapping` " + "WHERE `FileNam= e` =3D :fileName"); + + auto result =3D d->mRemoveTracksMapping.prepare(removeTracksMappin= gQueryText); + + if (!result) { + qDebug() << "DatabaseInterface::initRequest" << removeTracksMa= ppingQueryText << d->mRemoveTracksMapping.lastError(); + } + } + + { + auto selectTracksWithoutMappingQueryText =3D QStringLiteral("SELEC= T " + "tracks.= `Id`, " + "tracks.= `Title`, " + "tracks.= `AlbumID`, " + "artist.= `Name`, " + "artistA= lbum.`Name`, " + "\"\" as= FileName, " + "tracks.= `TrackNumber`, " + "tracks.= `DiscNumber`, " + "tracks.= `Duration`, " + "album.`= Title`, " + "tracks.= `Rating`, " + "album.`= CoverFileName`, " + "album.`= IsSingleDiscAlbum` " + "FROM `T= racks` tracks, `Artists` artist, `Albums` album " + "LEFT JO= IN `Artists` artistAlbum ON artistAlbum.`ID` =3D album.`ArtistID` " + "WHERE " + "artist.= `ID` =3D tracks.`ArtistID` AND " + "tracks.= `AlbumID` =3D album.`ID` AND " + "tracks.= `ID` NOT IN (SELECT tracksMapping2.`TrackID` FROM `TracksMapping` tracksMap= ping2)"); + + auto result =3D d->mSelectTracksWithoutMappingQuery.prepare(select= TracksWithoutMappingQueryText); + + if (!result) { + qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrac= ksWithoutMappingQuery.lastError(); + } + } + { auto selectTracksMappingQueryText =3D QStringLiteral("SELECT `Trac= kID`, `FileName`, `DiscoverID`, `Priority` FROM `TracksMapping` WHERE `File= Name` =3D :fileName"); = @@ -1499,7 +1559,8 @@ void DatabaseInterface::initRequest() = { auto findInvalidTrackFilesText =3D QStringLiteral("SELECT " - "tracksMapping.`Fi= leName` " + "tracksMapping.`Fi= leName`, " + "tracksMapping.`Di= scoverID` " "FROM " "`TracksMapping` t= racksMapping " "WHERE " @@ -1514,7 +1575,7 @@ void DatabaseInterface::initRequest() = { auto insertMusicSourceQueryText =3D QStringLiteral("INSERT OR IGNO= RE INTO `DiscoverSource` (`ID`, `Name`) " - "VALUES (:discoverId, := name)"); + "VALUES (:discove= rId, :name)"); = auto result =3D d->mInsertMusicSource.prepare(insertMusicSourceQue= ryText); = @@ -1543,7 +1604,7 @@ void DatabaseInterface::initRequest() "artist.`Name` =3D :art= ist AND " "artist.`ID` =3D tracks= .`ArtistID` AND " "tracksMapping.`TrackID= ` =3D tracks.`ID` AND " - "tracksMapping.`Priorit= y` =3D 1"); + "tracksMapping.`Priorit= y` =3D (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` =3D tra= cks.`ID`)"); = auto result =3D d->mSelectTrackIdFromTitleAlbumIdArtistQuery.prepa= re(selectTrackQueryText); = @@ -1619,9 +1680,9 @@ void DatabaseInterface::initRequest() = { auto updateAlbumArtUriFromAlbumIdQueryText =3D QStringLiteral("UPD= ATE `Albums` " - "SET = `CoverFileName` =3D :coverFileName " - "WHER= E " - "`ID`= =3D :albumId"); + "SET `= CoverFileName` =3D :coverFileName " + "WHERE= " + "`ID` = =3D :albumId"); = auto result =3D d->mUpdateAlbumArtUriFromAlbumIdQuery.prepare(upda= teAlbumArtUriFromAlbumIdQueryText); = @@ -1633,9 +1694,9 @@ void DatabaseInterface::initRequest() = { auto updateAlbumArtistFromAlbumIdQueryText =3D QStringLiteral("UPD= ATE `Albums` " - "SET = `ArtistID` =3D :artistId " - "WHER= E " - "`ID`= =3D :albumId"); + "SET `= ArtistID` =3D :artistId " + "WHERE= " + "`ID` = =3D :albumId"); = auto result =3D d->mUpdateAlbumArtistFromAlbumIdQuery.prepare(upda= teAlbumArtistFromAlbumIdQueryText); = @@ -1667,7 +1728,7 @@ void DatabaseInterface::initRequest() "tracks.`Alb= umID` =3D album.`ID` AND " "artist.`ID`= =3D tracks.`ArtistID` AND " "tracksMappi= ng.`TrackID` =3D tracks.`ID` AND " - "tracksMappi= ng.`Priority` =3D 1 " + "tracksMappi= ng.`Priority` =3D (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `Track= ID` =3D tracks.`ID`) " "ORDER BY tr= acks.`Title` ASC, " "album.`Titl= e` ASC"); = @@ -1697,10 +1758,10 @@ void DatabaseInterface::initRequest() = { auto selectArtistQueryText =3D QStringLiteral("SELECT `ID`, " - "`Name` " - "FROM `Artists` " - "WHERE " - "`ID` =3D :artistId"); + "`Name` " + "FROM `Artists` " + "WHERE " + "`ID` =3D :artistId"); = auto result =3D d->mSelectArtistQuery.prepare(selectArtistQueryTex= t); = @@ -1732,7 +1793,7 @@ void DatabaseInterface::initRequest() "artist.`ID= ` =3D tracks.`ArtistID` AND " "tracksMapp= ing.`TrackID` =3D tracks.`ID` AND " "tracksMapp= ing.`FileName` =3D :filePath AND " - "tracksMapp= ing.`Priority` =3D 1"); + "tracksMapp= ing.`Priority` =3D (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `Trac= kID` =3D tracks.`ID`)"); = auto result =3D d->mSelectTrackFromFilePathQuery.prepare(selectTra= ckFromFilePathQueryText); = @@ -2204,32 +2265,71 @@ MusicAudioTrack DatabaseInterface::buildTrackFromDa= tabaseRecord(const QSqlRecord = void DatabaseInterface::internalRemoveTracksList(const QList &remove= dTracks) { - QList willRemoveTrack; + for (const auto &removedTrackFileName : removedTracks) { + d->mRemoveTracksMapping.bindValue(QStringLiteral(":fileName"), rem= ovedTrackFileName.toString()); + + auto result =3D d->mRemoveTracksMapping.exec(); + + if (!result || !d->mRemoveTracksMapping.isActive()) { + qDebug() << "DatabaseInterface::internalRemoveTracksList" << d= ->mRemoveTracksMapping.lastQuery(); + qDebug() << "DatabaseInterface::internalRemoveTracksList" << d= ->mRemoveTracksMapping.boundValues(); + qDebug() << "DatabaseInterface::internalRemoveTracksList" << d= ->mRemoveTracksMapping.lastError(); = - qDebug() << "DatabaseInterface::internalRemoveTracksList" << removedTr= acks; + continue; + } + + d->mRemoveTracksMapping.finish(); + } = + internalRemoveTracksWithoutMapping(); +} + +void DatabaseInterface::internalRemoveTracksList(const QList &remove= dTracks, qulonglong sourceId) +{ for (const auto &removedTrackFileName : removedTracks) { - d->mSelectTrackFromFilePathQuery.bindValue(QStringLiteral(":filePa= th"), removedTrackFileName.toString()); + d->mRemoveTracksMappingFromSource.bindValue(QStringLiteral(":fileN= ame"), removedTrackFileName.toString()); + d->mRemoveTracksMappingFromSource.bindValue(QStringLiteral(":sourc= eId"), sourceId); = - auto result =3D d->mSelectTrackFromFilePathQuery.exec(); + auto result =3D d->mRemoveTracksMappingFromSource.exec(); = - if (!result || !d->mSelectTrackFromFilePathQuery.isSelect() || !d-= >mSelectTrackFromFilePathQuery.isActive()) { - qDebug() << "DatabaseInterface::removeTracksList" << d->mSelec= tTrackFromFilePathQuery.lastQuery(); - qDebug() << "DatabaseInterface::removeTracksList" << d->mSelec= tTrackFromFilePathQuery.boundValues(); - qDebug() << "DatabaseInterface::removeTracksList" << d->mSelec= tTrackFromFilePathQuery.lastError(); + if (!result || !d->mRemoveTracksMappingFromSource.isActive()) { + qDebug() << "DatabaseInterface::removeTracksList" << d->mRemov= eTracksMappingFromSource.lastQuery(); + qDebug() << "DatabaseInterface::removeTracksList" << d->mRemov= eTracksMappingFromSource.boundValues(); + qDebug() << "DatabaseInterface::removeTracksList" << d->mRemov= eTracksMappingFromSource.lastError(); = continue; } = - while (d->mSelectTrackFromFilePathQuery.next()) { - const auto ¤tRecord =3D d->mSelectTrackFromFilePathQuery= .record(); + d->mRemoveTracksMappingFromSource.finish(); + } = - willRemoveTrack.push_back(buildTrackFromDatabaseRecord(current= Record)); - } + internalRemoveTracksWithoutMapping(); +} + +void DatabaseInterface::internalRemoveTracksWithoutMapping() +{ + auto queryResult =3D d->mSelectTracksWithoutMappingQuery.exec(); + + if (!queryResult || !d->mSelectTracksWithoutMappingQuery.isSelect() ||= !d->mSelectTracksWithoutMappingQuery.isActive()) { + qDebug() << "DatabaseInterface::insertArtist" << d->mSelectTracksW= ithoutMappingQuery.lastQuery(); + qDebug() << "DatabaseInterface::insertArtist" << d->mSelectTracksW= ithoutMappingQuery.boundValues(); + qDebug() << "DatabaseInterface::insertArtist" << d->mSelectTracksW= ithoutMappingQuery.lastError(); + + d->mSelectTracksWithoutMappingQuery.finish(); = - d->mSelectTrackFromFilePathQuery.finish(); + return; } = + QList willRemoveTrack; + + while (d->mSelectTracksWithoutMappingQuery.next()) { + const auto ¤tRecord =3D d->mSelectTracksWithoutMappingQuery.= record(); + + willRemoveTrack.push_back(buildTrackFromDatabaseRecord(currentReco= rd)); + } + + d->mSelectTracksWithoutMappingQuery.finish(); + QSet modifiedAlbums; = for (const auto &oneRemovedTrack : willRemoveTrack) { diff --git a/src/databaseinterface.h b/src/databaseinterface.h index 87719d1..6a4b8cd 100644 --- a/src/databaseinterface.h +++ b/src/databaseinterface.h @@ -177,6 +177,10 @@ private: = void internalRemoveTracksList(const QList &removedTracks); = + void internalRemoveTracksList(const QList &removedTracks, qulong= long sourceId); + + void internalRemoveTracksWithoutMapping(); + std::unique_ptr d; = };