Rework db range primitives + fixed bug when playing all in releases/tracks views + raised limit to 1000 for ranges in subsonic API

This commit is contained in:
emeric
2023-11-10 16:17:18 +01:00
parent bd61093898
commit b7a8bf85b8
61 changed files with 1704 additions and 2603 deletions
+15 -3
View File
@@ -51,7 +51,7 @@ TEST_F(DatabaseFixture, Artist)
ASSERT_EQ(artists.results.size(), 1);
EXPECT_EQ(artists.results.front(), artist.getId());
artists = Artist::findOrphanIds(session, Range{});
artists = Artist::findOrphanIds(session);
ASSERT_EQ(artists.results.size(), 1);
EXPECT_EQ(artists.results.front(), artist.getId());
}
@@ -64,6 +64,18 @@ TEST_F(DatabaseFixture, Artist)
ASSERT_EQ(artists.results.size(), 1);
EXPECT_EQ(artists.results.front()->getId(), artist.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool visited{};
Artist::find(session, Artist::FindParameters{}, [&](const Artist::pointer& a)
{
visited = true;
EXPECT_EQ(a->getId(), artist.getId());
});
EXPECT_TRUE(visited);
}
}
TEST_F(DatabaseFixture, Artist_singleTrack)
@@ -80,7 +92,7 @@ TEST_F(DatabaseFixture, Artist_singleTrack)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(Artist::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session).results.empty());
}
{
@@ -215,7 +227,7 @@ TEST_F(DatabaseFixture, Artist_singleTrackMultiArtists)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(Artist::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session).results.empty());
}
{
+31 -380
View File
@@ -55,20 +55,20 @@ TEST_F(DatabaseFixture, Cluster)
}
{
const auto clusters{ Cluster::findOrphans(session, Range{}) };
const auto clusters{ Cluster::findOrphans(session) };
ASSERT_EQ(clusters.results.size(), 1);
EXPECT_EQ(clusters.results.front(), cluster.getId());
}
auto clusterTypes{ ClusterType::find(session, Range {}) };
auto clusterTypes{ ClusterType::find(session) };
ASSERT_EQ(clusterTypes.results.size(), 1);
EXPECT_EQ(clusterTypes.results.front(), clusterType.getId());
clusterTypes = ClusterType::findUsed(session, Range{});
clusterTypes = ClusterType::findUsed(session);
ASSERT_EQ(clusterTypes.results.size(), 1);
EXPECT_EQ(clusterTypes.results.front(), clusterType.getId());
clusterTypes = ClusterType::findOrphans(session, Range{});
clusterTypes = ClusterType::findOrphans(session);
EXPECT_TRUE(clusterTypes.results.empty());
}
}
@@ -76,11 +76,11 @@ TEST_F(DatabaseFixture, Cluster)
{
auto transaction{ session.createUniqueTransaction() };
auto clusterTypes{ ClusterType::findOrphans(session, Range {}) };
auto clusterTypes{ ClusterType::findOrphans(session) };
ASSERT_EQ(clusterTypes.results.size(), 1);
EXPECT_EQ(clusterTypes.results.front(), clusterType.getId());
ASSERT_TRUE(ClusterType::findUsed(session, Range{}).results.empty());
ASSERT_TRUE(ClusterType::findUsed(session).results.empty());
}
}
@@ -91,8 +91,8 @@ TEST_F(DatabaseFixture, Cluster_singleTrack)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(Cluster::findOrphans(session, Range{}).results.empty());
auto clusterTypes{ ClusterType::findOrphans(session, Range {}) };
EXPECT_TRUE(Cluster::findOrphans(session).results.empty());
auto clusterTypes{ ClusterType::findOrphans(session) };
ASSERT_EQ(clusterTypes.results.size(), 1);
EXPECT_EQ(clusterTypes.results.front(), clusterType.getId());
}
@@ -102,7 +102,7 @@ TEST_F(DatabaseFixture, Cluster_singleTrack)
{
auto transaction{ session.createSharedTransaction() };
auto clusters{ Cluster::findOrphans(session, Range {}) };
auto clusters{ Cluster::findOrphans(session) };
EXPECT_EQ(clusters.results.size(), 2);
EXPECT_TRUE(track->getClusters().empty());
EXPECT_TRUE(track->getClusterIds().empty());
@@ -127,11 +127,11 @@ TEST_F(DatabaseFixture, Cluster_singleTrack)
{
auto transaction{ session.createSharedTransaction() };
auto clusters{ Cluster::findOrphans(session, Range {}) };
auto clusters{ Cluster::findOrphans(session) };
ASSERT_EQ(clusters.results.size(), 1);
EXPECT_EQ(clusters.results.front(), cluster2.getId());
EXPECT_TRUE(ClusterType::findOrphans(session, Range{}).results.empty());
EXPECT_TRUE(ClusterType::findOrphans(session).results.empty());
}
{
@@ -225,11 +225,11 @@ TEST_F(DatabaseFixture, Cluster_multiTracks)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(Cluster::findOrphans(session, Range{}).results.empty());
EXPECT_TRUE(Cluster::findOrphans(session).results.empty());
EXPECT_EQ(Cluster::computeTrackCount(session, cluster.getId()), tracks.size());
for (TrackId trackId : cluster->getTracks(Range{}).results)
for (TrackId trackId : cluster->getTracks().results)
{
auto it{ std::find_if(std::cbegin(tracks), std::cend(tracks), [&](const ScopedTrack& track) { return trackId == track.getId(); }) };
EXPECT_TRUE(it != std::cend(tracks));
@@ -237,102 +237,6 @@ TEST_F(DatabaseFixture, Cluster_multiTracks)
}
}
TEST_F(DatabaseFixture, Cluster_multiTracksMultipleClustersTopRelease)
{
ScopedClusterType clusterType{ session, "ClusterType" };
ScopedCluster cluster1{ session, clusterType.lockAndGet(), "Cluster1" };
ScopedCluster cluster2{ session, clusterType.lockAndGet(), "Cluster2" };
ScopedCluster cluster3{ session, clusterType.lockAndGet(), "Cluster3" };
ScopedTrack trackA{ session, "TrackA" };
ScopedTrack trackB{ session, "TrackB" };
ScopedTrack trackC{ session, "TrackC" };
ScopedRelease releaseA{ session, "ReleaseA" };
ScopedRelease releaseB{ session, "ReleaseB" };
ScopedRelease releaseC{ session, "ReleaseC" };
ScopedUser user{ session, "MyUser" };
ScopedTrackList trackList{ session, "TrackList", TrackListType::Playlist, false, user.lockAndGet() };
{
auto transaction{ session.createSharedTransaction() };
EXPECT_EQ(trackList->getDuration(), std::chrono::seconds{ 0 });
}
{
auto transaction{ session.createUniqueTransaction() };
cluster1.get().modify()->addTrack(trackA.get());
cluster2.get().modify()->addTrack(trackB.get());
cluster2.get().modify()->addTrack(trackC.get());
cluster3.get().modify()->addTrack(trackC.get());
trackA.get().modify()->setRelease(releaseA.get());
trackB.get().modify()->setRelease(releaseB.get());
trackC.get().modify()->setRelease(releaseC.get());
}
{
auto transaction{ session.createUniqueTransaction() };
session.create<TrackListEntry>(trackA.get(), trackList.get());
session.create<TrackListEntry>(trackB.get(), trackList.get());
session.create<TrackListEntry>(trackB.get(), trackList.get());
}
{
auto transaction{ session.createSharedTransaction() };
bool hasMore;
const auto releases{ trackList->getTopReleases({}, std::nullopt, hasMore) };
ASSERT_EQ(releases.size(), 2);
EXPECT_EQ(releases[0]->getId(), releaseB.getId());
EXPECT_EQ(releases[1]->getId(), releaseA.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool hasMore;
auto releases{ trackList->getTopReleases({cluster1.getId()}, std::nullopt, hasMore) };
ASSERT_EQ(releases.size(), 1);
EXPECT_EQ(releases[0]->getId(), releaseA.getId());
releases = trackList->getTopReleases({ cluster2.getId() }, std::nullopt, hasMore);
ASSERT_EQ(releases.size(), 1);
EXPECT_EQ(releases[0]->getId(), releaseB.getId());
releases = trackList->getTopReleases({ cluster2.getId(), cluster1.getId() }, std::nullopt, hasMore);
EXPECT_TRUE(releases.empty());
releases = trackList->getTopReleases({ cluster2.getId(), cluster3.getId() }, std::nullopt, hasMore);
EXPECT_TRUE(releases.empty());
}
{
auto transaction{ session.createUniqueTransaction() };
session.create<TrackListEntry>(trackC.get(), trackList.get());
session.create<TrackListEntry>(trackC.get(), trackList.get());
session.create<TrackListEntry>(trackC.get(), trackList.get());
}
{
auto transaction{ session.createSharedTransaction() };
bool hasMore;
auto releases{ trackList->getTopReleases({cluster2.getId(), cluster3.getId()}, std::nullopt, hasMore) };
ASSERT_EQ(releases.size(), 1);
EXPECT_EQ(releases[0]->getId(), releaseC.getId());
releases = trackList->getTopReleases({ cluster2.getId() }, std::nullopt, hasMore);
ASSERT_EQ(releases.size(), 2);
EXPECT_EQ(releases[0]->getId(), releaseC.getId());
EXPECT_EQ(releases[1]->getId(), releaseB.getId());
}
}
TEST_F(DatabaseFixture, Cluster_singleTrackSingleReleaseSingleCluster)
{
ScopedTrack track{ session, "MyTrackFile" };
@@ -340,7 +244,7 @@ TEST_F(DatabaseFixture, Cluster_singleTrackSingleReleaseSingleCluster)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(Cluster::findOrphans(session, Range{}).results.empty());
EXPECT_TRUE(Cluster::findOrphans(session).results.empty());
}
ScopedClusterType clusterType{ session, "MyClusterType" };
@@ -349,7 +253,7 @@ TEST_F(DatabaseFixture, Cluster_singleTrackSingleReleaseSingleCluster)
{
auto transaction{ session.createSharedTransaction() };
ASSERT_EQ(Cluster::findOrphans(session, Range{}).results.size(), 2);
ASSERT_EQ(Cluster::findOrphans(session).results.size(), 2);
EXPECT_TRUE(Release::find(session, Release::FindParameters{}.setClusters({ unusedCluster.getId() })).results.empty());
EXPECT_EQ(Release::find(session, Release::FindParameters{}).results.size(), 1);
EXPECT_EQ(Cluster::computeReleaseCount(session, cluster.getId()), 0);
@@ -367,7 +271,7 @@ TEST_F(DatabaseFixture, Cluster_singleTrackSingleReleaseSingleCluster)
auto transaction{ session.createSharedTransaction() };
{
auto clusters{ Cluster::findOrphans(session, Range {}) };
auto clusters{ Cluster::findOrphans(session) };
ASSERT_EQ(clusters.results.size(), 1);
EXPECT_EQ(clusters.results.front(), unusedCluster.getId());
}
@@ -425,10 +329,10 @@ TEST_F(DatabaseFixture, SingleTrackSingleArtistMultiClusters)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(ClusterType::findOrphans(session, Range{}).results.empty());
EXPECT_EQ(Cluster::findOrphans(session, Range{}).results.size(), 2);
EXPECT_TRUE(Release::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(ClusterType::findOrphans(session).results.empty());
EXPECT_EQ(Cluster::findOrphans(session).results.size(), 2);
EXPECT_TRUE(Release::findOrphanIds(session).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session).results.empty());
}
{
@@ -486,9 +390,9 @@ TEST_F(DatabaseFixture, SingleTrackSingleArtistMultiRolesMultiClusters)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(Cluster::findOrphans(session, Range{}).results.empty());
EXPECT_TRUE(Release::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Cluster::findOrphans(session).results.empty());
EXPECT_TRUE(Release::findOrphanIds(session).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session).results.empty());
}
{
@@ -526,8 +430,8 @@ TEST_F(DatabaseFixture, MultiTracksSingleArtistMultiClusters)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(Cluster::findOrphans(session, Range{}).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Cluster::findOrphans(session).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session).results.empty());
}
{
@@ -562,7 +466,7 @@ TEST_F(DatabaseFixture, MultipleTracksSingleClusterSimilarity)
{
auto transaction{ session.createSharedTransaction() };
const auto similarTracks{ Track::findSimilarTrackIds(session, {tracks.front().getId()}, Range {}) };
const auto similarTracks{ Track::findSimilarTrackIds(session, {tracks.front().getId()}) };
EXPECT_EQ(similarTracks.results.size(), tracks.size() - 1);
for (const TrackId similarTrackId : similarTracks.results)
{
@@ -610,7 +514,7 @@ TEST_F(DatabaseFixture, MultipleTracksMultipleClustersSimilarity)
}
{
auto similarTracks{ Track::findSimilarTrackIds(session, {tracks.front().getId()}, Range {}) };
auto similarTracks{ Track::findSimilarTrackIds(session, {tracks.front().getId()}) };
EXPECT_EQ(similarTracks.results.size(), tracks.size() - 1);
for (const TrackId similarTrackId : similarTracks.results)
EXPECT_TRUE(std::find_if(std::next(std::cbegin(tracks), 1), std::cend(tracks), [&](const auto& track) { return similarTrackId == track.getId(); }) != std::cend(tracks));
@@ -637,10 +541,10 @@ TEST_F(DatabaseFixture, SingleTrackSingleReleaseSingleArtistSingleCluster)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(Cluster::findOrphans(session, Range{}).results.empty());
EXPECT_TRUE(ClusterType::findOrphans(session, Range{}).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Release::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Cluster::findOrphans(session).results.empty());
EXPECT_TRUE(ClusterType::findOrphans(session).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session).results.empty());
EXPECT_TRUE(Release::findOrphanIds(session).results.empty());
}
{
@@ -775,259 +679,6 @@ TEST_F(DatabaseFixture, SingleTrackListMultipleTrackMultiClusters)
}
}
TEST_F(DatabaseFixture, SingleTrackListMultipleTrackMultiClustersRecentlyPlayed)
{
ScopedUser user{ session, "MyUser" };
ScopedTrackList trackList{ session, "MyTrackList", TrackListType::Playlist, false, user.lockAndGet() };
ScopedClusterType clusterType{ session, "MyClusterType" };
ScopedCluster cluster1{ session, clusterType.lockAndGet(), "MyCluster1" };
ScopedCluster cluster2{ session, clusterType.lockAndGet(), "MyCluster2" };
ScopedCluster cluster3{ session, clusterType.lockAndGet(), "MyCluster3" };
ScopedTrack track1{ session, "MyTrack1" };
ScopedTrack track2{ session, "MyTrack1" };
ScopedArtist artist1{ session, "MyArtist1" };
ScopedArtist artist2{ session, "MyArtist2" };
ScopedRelease release1{ session, "MyRelease1" };
ScopedRelease release2{ session, "MyRelease2" };
const Wt::WDateTime now{ Wt::WDateTime::currentDateTime() };
{
auto transaction{ session.createUniqueTransaction() };
track1.get().modify()->setRelease(release1.get());
track2.get().modify()->setRelease(release2.get());
TrackArtistLink::create(session, track1.get(), artist1.get(), TrackArtistLinkType::Artist);
TrackArtistLink::create(session, track2.get(), artist2.get(), TrackArtistLinkType::Artist);
cluster1.get().modify()->addTrack(track1.get());
cluster2.get().modify()->addTrack(track2.get());
cluster3.get().modify()->addTrack(track1.get());
cluster3.get().modify()->addTrack(track2.get());
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
EXPECT_TRUE(trackList->getArtistsOrderedByRecentFirst({}, std::nullopt, std::nullopt, moreResults).empty());
EXPECT_TRUE(trackList->getReleasesOrderedByRecentFirst({}, std::nullopt, moreResults).empty());
EXPECT_TRUE(trackList->getTracksOrderedByRecentFirst({}, std::nullopt, moreResults).empty());
}
{
auto transaction{ session.createUniqueTransaction() };
session.create<TrackListEntry>(track1.get(), trackList.get(), now);
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({}, std::nullopt, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 1);
EXPECT_EQ(artists.front()->getId(), artist1.getId());
const auto releases{ trackList->getReleasesOrderedByRecentFirst({}, std::nullopt, moreResults) };
ASSERT_EQ(releases.size(), 1);
EXPECT_EQ(releases.front()->getId(), release1.getId());
const auto tracks{ trackList->getTracksOrderedByRecentFirst({}, std::nullopt, moreResults) };
ASSERT_EQ(tracks.size(), 1);
EXPECT_EQ(tracks.front()->getId(), track1.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({cluster1.getId()}, std::nullopt, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 1);
EXPECT_EQ(artists.front()->getId(), artist1.getId());
const auto releases{ trackList->getReleasesOrderedByRecentFirst({cluster1.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(releases.size(), 1);
EXPECT_EQ(releases.front()->getId(), release1.getId());
const auto tracks{ trackList->getTracksOrderedByRecentFirst({cluster1.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(tracks.size(), 1);
EXPECT_EQ(tracks.front()->getId(), track1.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({cluster3.getId()}, std::nullopt, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 1);
EXPECT_EQ(artists.front()->getId(), artist1.getId());
const auto releases{ trackList->getReleasesOrderedByRecentFirst({cluster3.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(releases.size(), 1);
EXPECT_EQ(releases.front()->getId(), release1.getId());
const auto tracks{ trackList->getTracksOrderedByRecentFirst({cluster3.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(tracks.size(), 1);
EXPECT_EQ(tracks.front()->getId(), track1.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({cluster1.getId()}, TrackArtistLinkType::Artist, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 1);
EXPECT_EQ(artists.front()->getId(), artist1.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({}, TrackArtistLinkType::Artist, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 1);
EXPECT_EQ(artists.front()->getId(), artist1.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
EXPECT_TRUE(trackList->getArtistsOrderedByRecentFirst({ cluster2.getId() }, std::nullopt, std::nullopt, moreResults).empty());
EXPECT_TRUE(trackList->getReleasesOrderedByRecentFirst({ cluster2.getId() }, std::nullopt, moreResults).empty());
EXPECT_TRUE(trackList->getTracksOrderedByRecentFirst({ cluster2.getId() }, std::nullopt, moreResults).empty());
EXPECT_TRUE(trackList->getArtistsOrderedByRecentFirst({}, TrackArtistLinkType::ReleaseArtist, std::nullopt, moreResults).empty());
}
{
auto transaction{ session.createUniqueTransaction() };
session.create<TrackListEntry>(track2.get(), trackList.get(), now.addSecs(1));
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({}, std::nullopt, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 2);
EXPECT_EQ(artists[0]->getId(), artist2.getId());
EXPECT_EQ(artists[1]->getId(), artist1.getId());
const auto releases{ trackList->getReleasesOrderedByRecentFirst({}, std::nullopt, moreResults) };
ASSERT_EQ(releases.size(), 2);
EXPECT_EQ(releases[0]->getId(), release2.getId());
EXPECT_EQ(releases[1]->getId(), release1.getId());
const auto tracks{ trackList->getTracksOrderedByRecentFirst({}, std::nullopt, moreResults) };
ASSERT_EQ(tracks.size(), 2);
EXPECT_EQ(tracks[0]->getId(), track2.getId());
EXPECT_EQ(tracks[1]->getId(), track1.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({cluster3.getId()}, std::nullopt, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 2);
EXPECT_EQ(artists[0]->getId(), artist2.getId());
EXPECT_EQ(artists[1]->getId(), artist1.getId());
const auto releases{ trackList->getReleasesOrderedByRecentFirst({cluster3.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(releases.size(), 2);
EXPECT_EQ(releases[0]->getId(), release2.getId());
EXPECT_EQ(releases[1]->getId(), release1.getId());
const auto tracks{ trackList->getTracksOrderedByRecentFirst({cluster3.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(tracks.size(), 2);
EXPECT_EQ(tracks[0]->getId(), track2.getId());
EXPECT_EQ(tracks[1]->getId(), track1.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({cluster1.getId()}, std::nullopt, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 1);
EXPECT_EQ(artists.front()->getId(), artist1.getId());
const auto releases{ trackList->getReleasesOrderedByRecentFirst({cluster1.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(releases.size(), 1);
EXPECT_EQ(releases.front()->getId(), release1.getId());
const auto tracks{ trackList->getTracksOrderedByRecentFirst({cluster1.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(tracks.size(), 1);
EXPECT_EQ(tracks.front()->getId(), track1.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({cluster2.getId()}, std::nullopt, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 1);
EXPECT_EQ(artists.front()->getId(), artist2.getId());
const auto releases{ trackList->getReleasesOrderedByRecentFirst({cluster2.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(releases.size(), 1);
EXPECT_EQ(releases.front()->getId(), release2.getId());
const auto tracks{ trackList->getTracksOrderedByRecentFirst({cluster2.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(tracks.size(), 1);
EXPECT_EQ(tracks.front()->getId(), track2.getId());
}
{
auto transaction{ session.createUniqueTransaction() };
session.create<TrackListEntry>(track1.get(), trackList.get(), now.addSecs(2));
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({}, std::nullopt, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 2);
EXPECT_EQ(artists[0]->getId(), artist1.getId());
EXPECT_EQ(artists[1]->getId(), artist2.getId());
const auto releases{ trackList->getReleasesOrderedByRecentFirst({}, std::nullopt, moreResults) };
ASSERT_EQ(releases.size(), 2);
EXPECT_EQ(releases[0]->getId(), release1.getId());
EXPECT_EQ(releases[1]->getId(), release2.getId());
const auto tracks{ trackList->getTracksOrderedByRecentFirst({}, std::nullopt, moreResults) };
ASSERT_EQ(tracks.size(), 2);
EXPECT_EQ(tracks[0]->getId(), track1.getId());
EXPECT_EQ(tracks[1]->getId(), track2.getId());
}
{
auto transaction{ session.createSharedTransaction() };
bool moreResults{};
const auto artists{ trackList->getArtistsOrderedByRecentFirst({cluster3.getId()}, std::nullopt, std::nullopt, moreResults) };
ASSERT_EQ(artists.size(), 2);
EXPECT_EQ(artists[0]->getId(), artist1.getId());
EXPECT_EQ(artists[1]->getId(), artist2.getId());
const auto releases{ trackList->getReleasesOrderedByRecentFirst({cluster3.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(releases.size(), 2);
EXPECT_EQ(releases[0]->getId(), release1.getId());
EXPECT_EQ(releases[1]->getId(), release2.getId());
const auto tracks{ trackList->getTracksOrderedByRecentFirst({cluster3.getId()}, std::nullopt, moreResults) };
ASSERT_EQ(tracks.size(), 2);
EXPECT_EQ(tracks[0]->getId(), track1.getId());
EXPECT_EQ(tracks[1]->getId(), track2.getId());
}
}
TEST_F(DatabaseFixture, MultipleTracksMultipleArtistsMultiClusters)
{
ScopedArtist artist1{ session, "MyArtist1" };
+10 -14
View File
@@ -42,8 +42,7 @@ TmpDatabase::TmpDatabase()
{
}
Database::Db&
TmpDatabase::getDb()
Database::Db& TmpDatabase::getDb()
{
return _db;
}
@@ -53,8 +52,7 @@ DatabaseFixture::~DatabaseFixture()
testDatabaseEmpty();
}
void
DatabaseFixture::SetUpTestCase()
void DatabaseFixture::SetUpTestCase()
{
_tmpDb = std::make_unique<TmpDatabase>();
{
@@ -65,8 +63,8 @@ DatabaseFixture::SetUpTestCase()
// remove default created entries
{
auto transaction{ s.createUniqueTransaction() };
auto clusterTypes{ Database::ClusterType::find(s, Database::Range {}) };
for (auto clusterTypeId : clusterTypes.results)
for (const Database::ClusterTypeId clusterTypeId : Database::ClusterType::find(s).results)
{
auto clusterType{ Database::ClusterType::find(s, clusterTypeId) };
clusterType.remove();
@@ -75,14 +73,12 @@ DatabaseFixture::SetUpTestCase()
}
}
void
DatabaseFixture::TearDownTestCase()
void DatabaseFixture::TearDownTestCase()
{
_tmpDb.reset();
}
void
DatabaseFixture::testDatabaseEmpty()
void DatabaseFixture::testDatabaseEmpty()
{
using namespace Database;
@@ -153,10 +149,10 @@ TEST_F(DatabaseFixture, Common_subRangeForeach)
{
std::vector<Range> subRanges;
foreachSubRange(test.range, test.subRangeSize, [&](Range subRange)
{
subRanges.push_back(subRange);
return true;
});
{
subRanges.push_back(subRange);
return true;
});
EXPECT_EQ(subRanges, test.expectedSubRanges) << ", test index = " << std::distance(std::cbegin(testCases), &test);
}
@@ -42,8 +42,8 @@ TEST_F(DatabaseFixture, MultiTracksSingleArtistSingleRelease)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(Release::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Release::findOrphanIds(session).results.empty());
EXPECT_TRUE(Artist::findOrphanIds(session).results.empty());
}
{
+13 -3
View File
@@ -40,7 +40,7 @@ TEST_F(DatabaseFixture, Release)
EXPECT_TRUE(Release::exists(session, release.getId()));
{
const auto releases{ Release::findOrphanIds(session, Range {}) };
const auto releases{ Release::findOrphanIds(session) };
ASSERT_EQ(releases.results.size(), 1);
EXPECT_EQ(releases.results.front(), release.getId());
}
@@ -57,6 +57,16 @@ TEST_F(DatabaseFixture, Release)
ASSERT_EQ(releases.results.size(), 1);
EXPECT_EQ(releases.results.front()->getId(), release.getId());
}
{
bool visited{};
Release::find(session, Release::FindParameters{}, [&](const Release::pointer& r)
{
visited = true;
EXPECT_EQ(r->getId(), release.getId());
});
EXPECT_TRUE(visited);
}
}
}
@@ -76,7 +86,7 @@ TEST_F(DatabaseFixture, Release_singleTrack)
{
auto transaction{ session.createSharedTransaction() };
EXPECT_TRUE(Release::findOrphanIds(session, Range{}).results.empty());
EXPECT_TRUE(Release::findOrphanIds(session).results.empty());
const auto tracks{ Track::findIds(session, Track::FindParameters {}.setRelease(release.getId())) };
ASSERT_EQ(tracks.results.size(), 1);
@@ -114,7 +124,7 @@ TEST_F(DatabaseFixture, Release_singleTrack)
const auto tracks{ Track::findIds(session, Track::FindParameters {}.setRelease(release.getId())) };
EXPECT_TRUE(tracks.results.empty());
auto releases{ Release::findOrphanIds(session, Range {}) };
auto releases{ Release::findOrphanIds(session) };
ASSERT_EQ(releases.results.size(), 1);
EXPECT_EQ(releases.results.front(), release.getId());
}
+16
View File
@@ -31,6 +31,12 @@ TEST_F(DatabaseFixture, Track)
EXPECT_EQ(Track::findIds(session, Track::FindParameters{}).results.size(), 0);
EXPECT_EQ(Track::getCount(session), 0);
EXPECT_FALSE(Track::exists(session, 0));
{
bool visited{};
Track::find(session, Track::FindParameters{}, [&](const Track::pointer&) {visited = true;});
EXPECT_FALSE(visited);
}
}
ScopedTrack track{ session, "MyTrackFile" };
@@ -44,6 +50,16 @@ TEST_F(DatabaseFixture, Track)
auto myTrack{ Track::find(session, track.getId()) };
ASSERT_TRUE(myTrack);
EXPECT_EQ(myTrack->getId(), track.getId());
{
bool visited{};
Track::find(session, Track::FindParameters{}, [&](const Track::pointer& t)
{
visited = true;
EXPECT_EQ(t->getId(), track.getId());
});
EXPECT_TRUE(visited);
}
}
}
@@ -49,7 +49,7 @@ TEST_F(DatabaseFixture, TrackBookmark)
EXPECT_EQ(TrackBookmark::getCount(session), 1);
const auto bookmarks {TrackBookmark::find(session, user.getId(), Range {})};
const auto bookmarks {TrackBookmark::find(session, user.getId())};
ASSERT_EQ(bookmarks.results.size(), 1);
EXPECT_EQ(bookmarks.results.front(), bookmark.getId());
}
@@ -41,7 +41,7 @@ TEST_F(DatabaseFixture, TrackFeatures)
auto transaction {session.createUniqueTransaction()};
EXPECT_EQ(TrackFeatures::getCount(session), 1);
auto allTrackFeatures {TrackFeatures::find(session, Range {})};
auto allTrackFeatures {TrackFeatures::find(session)};
ASSERT_EQ(allTrackFeatures.results.size(), 1);
EXPECT_EQ(allTrackFeatures.results.front(), trackFeatures.getId());
}
+140 -437
View File
@@ -25,497 +25,200 @@ using namespace Database;
TEST_F(DatabaseFixture, SingleTrackList)
{
ScopedUser user {session, "MyUser"};
{
auto transaction {session.createSharedTransaction()};
EXPECT_EQ(TrackList::getCount(session), 0);
}
ScopedUser user{ session, "MyUser" };
{
auto transaction{ session.createSharedTransaction() };
EXPECT_EQ(TrackList::getCount(session), 0);
}
ScopedTrackList trackList {session, "MytrackList", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrackList trackList{ session, "MytrackList", TrackListType::Playlist, false, user.lockAndGet() };
{
auto transaction {session.createSharedTransaction()};
EXPECT_EQ(TrackList::getCount(session), 1);
}
{
auto transaction{ session.createSharedTransaction() };
EXPECT_EQ(TrackList::getCount(session), 1);
}
}
TEST_F(DatabaseFixture, SingleTrackListSingleTrack)
{
ScopedUser user {session, "MyUser"};
ScopedTrackList trackList1 {session, "MyTrackList1", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrackList trackList2 {session, "MyTrackList2", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrack track {session, "MyTrack"};
ScopedUser user{ session, "MyUser" };
ScopedTrackList trackList1{ session, "MyTrackList1", TrackListType::Playlist, false, user.lockAndGet() };
ScopedTrackList trackList2{ session, "MyTrackList2", TrackListType::Playlist, false, user.lockAndGet() };
ScopedTrack track{ session, "MyTrack" };
{
auto transaction {session.createSharedTransaction()};
{
auto transaction{ session.createSharedTransaction() };
auto tracks {Track::findIds(session, Track::FindParameters {}.setTrackList(trackList1.getId()))};
EXPECT_EQ(tracks.results.size(), 0);
auto tracks{ Track::findIds(session, Track::FindParameters {}.setTrackList(trackList1.getId())) };
EXPECT_EQ(tracks.results.size(), 0);
tracks = Track::findIds(session, Track::FindParameters {}.setTrackList(trackList2.getId()));
EXPECT_EQ(tracks.results.size(), 0);
}
tracks = Track::findIds(session, Track::FindParameters{}.setTrackList(trackList2.getId()));
EXPECT_EQ(tracks.results.size(), 0);
}
{
auto transaction {session.createUniqueTransaction()};
{
auto transaction{ session.createUniqueTransaction() };
session.create<TrackListEntry>(track.get(), trackList1.get());
}
session.create<TrackListEntry>(track.get(), trackList1.get());
}
{
auto transaction {session.createSharedTransaction()};
{
auto transaction{ session.createSharedTransaction() };
auto tracks {Track::findIds(session, Track::FindParameters {}.setTrackList(trackList1.getId()))};
ASSERT_EQ(tracks.results.size(), 1);
EXPECT_EQ(tracks.results.front(), track.getId());
auto tracks{ Track::findIds(session, Track::FindParameters {}.setTrackList(trackList1.getId())) };
ASSERT_EQ(tracks.results.size(), 1);
EXPECT_EQ(tracks.results.front(), track.getId());
tracks = Track::findIds(session, Track::FindParameters {}.setTrackList(trackList2.getId()));
EXPECT_EQ(tracks.results.size(), 0);
}
tracks = Track::findIds(session, Track::FindParameters{}.setTrackList(trackList2.getId()));
EXPECT_EQ(tracks.results.size(), 0);
}
}
TEST_F(DatabaseFixture, TrackList_SortMethod)
{
ScopedUser user {session, "MyUser"};
ScopedTrackList trackList2 {session, "MyTrackList2", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrackList trackList1 {session, "MyTrackList1", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrack track {session, "MyTrack"};
ScopedUser user{ session, "MyUser" };
ScopedTrackList trackList2{ session, "MyTrackList2", TrackListType::Playlist, false, user.lockAndGet() };
ScopedTrackList trackList1{ session, "MyTrackList1", TrackListType::Playlist, false, user.lockAndGet() };
ScopedTrack track{ session, "MyTrack" };
{
auto transaction {session.createSharedTransaction()};
{
auto transaction{ session.createSharedTransaction() };
const auto trackLists {TrackList::find(session, TrackList::FindParameters {}.setSortMethod(TrackListSortMethod::Name))};
ASSERT_EQ(trackLists.results.size(), 2);
EXPECT_EQ(trackLists.results[0], trackList1.getId());
EXPECT_EQ(trackLists.results[1], trackList2.getId());
}
const auto trackLists{ TrackList::find(session, TrackList::FindParameters {}.setSortMethod(TrackListSortMethod::Name)) };
ASSERT_EQ(trackLists.results.size(), 2);
EXPECT_EQ(trackLists.results[0], trackList1.getId());
EXPECT_EQ(trackLists.results[1], trackList2.getId());
}
{
auto transaction {session.createUniqueTransaction()};
{
auto transaction{ session.createUniqueTransaction() };
trackList1.get().modify()->setLastModifiedDateTime(Wt::WDateTime {Wt::WDate {1900,1,1}});
trackList2.get().modify()->setLastModifiedDateTime(Wt::WDateTime {Wt::WDate {1900,1,2}});
}
trackList1.get().modify()->setLastModifiedDateTime(Wt::WDateTime{ Wt::WDate {1900,1,1} });
trackList2.get().modify()->setLastModifiedDateTime(Wt::WDateTime{ Wt::WDate {1900,1,2} });
}
{
auto transaction {session.createSharedTransaction()};
{
auto transaction{ session.createSharedTransaction() };
const auto trackLists {TrackList::find(session, TrackList::FindParameters {}.setSortMethod(TrackListSortMethod::LastModifiedDesc))};
ASSERT_EQ(trackLists.results.size(), 2);
EXPECT_EQ(trackLists.results[0], trackList2.getId());
EXPECT_EQ(trackLists.results[1], trackList1.getId());
}
const auto trackLists{ TrackList::find(session, TrackList::FindParameters {}.setSortMethod(TrackListSortMethod::LastModifiedDesc)) };
ASSERT_EQ(trackLists.results.size(), 2);
EXPECT_EQ(trackLists.results[0], trackList2.getId());
EXPECT_EQ(trackLists.results[1], trackList1.getId());
}
{
auto transaction {session.createUniqueTransaction()};
{
auto transaction{ session.createUniqueTransaction() };
trackList1.get().modify()->setLastModifiedDateTime(Wt::WDateTime {Wt::WDate {1900,1,2}});
trackList2.get().modify()->setLastModifiedDateTime(Wt::WDateTime {Wt::WDate {1900,1,1}});
}
trackList1.get().modify()->setLastModifiedDateTime(Wt::WDateTime{ Wt::WDate {1900,1,2} });
trackList2.get().modify()->setLastModifiedDateTime(Wt::WDateTime{ Wt::WDate {1900,1,1} });
}
{
auto transaction {session.createSharedTransaction()};
{
auto transaction{ session.createSharedTransaction() };
const auto trackLists {TrackList::find(session, TrackList::FindParameters {}.setSortMethod(TrackListSortMethod::LastModifiedDesc))};
ASSERT_EQ(trackLists.results.size(), 2);
EXPECT_EQ(trackLists.results[0], trackList1.getId());
EXPECT_EQ(trackLists.results[1], trackList2.getId());
}
const auto trackLists{ TrackList::find(session, TrackList::FindParameters {}.setSortMethod(TrackListSortMethod::LastModifiedDesc)) };
ASSERT_EQ(trackLists.results.size(), 2);
EXPECT_EQ(trackLists.results[0], trackList1.getId());
EXPECT_EQ(trackLists.results[1], trackList2.getId());
}
}
TEST_F(DatabaseFixture, SingleTrackListMultipleTrack)
{
ScopedUser user {session, "MyUser"};
ScopedTrackList trackList {session, "MytrackList", TrackListType::Playlist, false, user.lockAndGet()};
std::list<ScopedTrack> tracks;
ScopedUser user{ session, "MyUser" };
ScopedTrackList trackList{ session, "MytrackList", TrackListType::Playlist, false, user.lockAndGet() };
std::list<ScopedTrack> tracks;
for (std::size_t i {}; i < 10; ++i)
{
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
for (std::size_t i{}; i < 10; ++i)
{
tracks.emplace_back(session, "MyTrack" + std::to_string(i));
auto transaction {session.createUniqueTransaction()};
session.create<TrackListEntry>(tracks.back().get(), trackList.get());
}
auto transaction{ session.createUniqueTransaction() };
session.create<TrackListEntry>(tracks.back().get(), trackList.get());
}
{
auto transaction {session.createSharedTransaction()};
{
auto transaction{ session.createSharedTransaction() };
ASSERT_EQ(trackList->getCount(), tracks.size());
const auto trackIds {trackList->getTrackIds()};
ASSERT_EQ(trackIds.size(), tracks.size());
ASSERT_EQ(trackList->getCount(), tracks.size());
const auto trackIds{ trackList->getTrackIds() };
ASSERT_EQ(trackIds.size(), tracks.size());
// Same order
std::size_t i {};
for (const ScopedTrack& track : tracks)
EXPECT_EQ(track.getId(), trackIds[i++]);
}
{
auto transaction {session.createSharedTransaction()};
bool moreResults {};
const auto reverseTracks {trackList->getTracksOrderedByRecentFirst({}, std::nullopt, moreResults)};
ASSERT_EQ(reverseTracks.size(), tracks.size());
// Reverse order
ASSERT_TRUE(tracks.size() > 0);
std::size_t i {tracks.size() - 1};
for (const ScopedTrack& track : tracks)
EXPECT_EQ(track.getId(), reverseTracks[i--]->getId());
}
}
TEST_F(DatabaseFixture, SingleTrackListMultipleTrackDateTime)
{
ScopedUser user {session, "MyUser"};
ScopedTrackList trackList {session, "MytrackList", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrack track1 {session, "MyTrack1"};
ScopedTrack track2 {session, "MyTrack2"};
ScopedTrack track3 {session, "MyTrack3"};
{
Wt::WDateTime now {Wt::WDateTime::currentDateTime()};
auto transaction {session.createUniqueTransaction()};
session.create<TrackListEntry>(track1.get(), trackList.get(), now);
session.create<TrackListEntry>(track2.get(), trackList.get(), now.addSecs(-1));
session.create<TrackListEntry>(track3.get(), trackList.get(), now.addSecs(1));
}
{
auto transaction {session.createSharedTransaction()};
bool moreResults;
const auto tracks {trackList.get()->getTracksOrderedByRecentFirst({}, std::nullopt, moreResults)};
ASSERT_EQ(tracks.size(), 3);
EXPECT_EQ(tracks.front()->getId(), track3.getId());
EXPECT_EQ(tracks.back()->getId(), track2.getId());
}
}
TEST_F(DatabaseFixture, SingleTrackListMultipleTrackRecentlyPlayed)
{
ScopedUser user {session, "MyUser"};
ScopedTrackList trackList {session, "MyTrackList", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrack track1 {session, "MyTrack1"};
ScopedTrack track2 {session, "MyTrack1"};
ScopedArtist artist1 {session, "MyArtist1"};
ScopedArtist artist2 {session, "MyArtist2"};
ScopedRelease release1 {session, "MyRelease1"};
ScopedRelease release2 {session, "MyRelease2"};
const Wt::WDateTime now {Wt::WDateTime::currentDateTime()};
{
auto transaction {session.createUniqueTransaction()};
track1.get().modify()->setRelease(release1.get());
track2.get().modify()->setRelease(release2.get());
TrackArtistLink::create(session, track1.get(), artist1.get(), TrackArtistLinkType::Artist);
TrackArtistLink::create(session, track2.get(), artist2.get(), TrackArtistLinkType::Artist);
}
{
auto transaction {session.createSharedTransaction()};
bool moreResults {};
EXPECT_TRUE(trackList->getArtistsOrderedByRecentFirst({}, std::nullopt, std::nullopt, moreResults).empty());
EXPECT_TRUE(trackList->getReleasesOrderedByRecentFirst({}, std::nullopt, moreResults).empty());
EXPECT_TRUE(trackList->getTracksOrderedByRecentFirst({}, std::nullopt, moreResults).empty());
}
{
auto transaction {session.createUniqueTransaction()};
session.create<TrackListEntry>(track1.get(), trackList.get(), now);
}
{
auto transaction {session.createSharedTransaction()};
bool moreResults {};
const auto artists {trackList->getArtistsOrderedByRecentFirst({}, std::nullopt, std::nullopt, moreResults)};
ASSERT_EQ(artists.size(), 1);
EXPECT_EQ(artists.front()->getId(), artist1.getId());
const auto releases {trackList->getReleasesOrderedByRecentFirst({}, std::nullopt, moreResults)};
ASSERT_EQ(releases.size(), 1);
EXPECT_EQ(releases.front()->getId(), release1.getId());
const auto tracks {trackList->getTracksOrderedByRecentFirst({}, std::nullopt, moreResults)};
EXPECT_EQ(tracks.size(), 1);
}
{
auto transaction {session.createUniqueTransaction()};
session.create<TrackListEntry>(track2.get(), trackList.get(), now.addSecs(1));
}
{
auto transaction {session.createSharedTransaction()};
bool moreResults {};
const auto artists {trackList->getArtistsOrderedByRecentFirst({}, std::nullopt, std::nullopt, moreResults)};
ASSERT_EQ(artists.size(), 2);
EXPECT_EQ(artists[0]->getId(), artist2.getId());
EXPECT_EQ(artists[1]->getId(), artist1.getId());
const auto releases {trackList->getReleasesOrderedByRecentFirst({}, std::nullopt, moreResults)};
ASSERT_EQ(releases.size(), 2);
EXPECT_EQ(releases[0]->getId(), release2.getId());
EXPECT_EQ(releases[1]->getId(), release1.getId());
const auto tracks {trackList->getTracksOrderedByRecentFirst({}, std::nullopt, moreResults)};
ASSERT_EQ(tracks.size(), 2);
EXPECT_EQ(tracks[0]->getId(), track2.getId());
EXPECT_EQ(tracks[1]->getId(), track1.getId());
}
{
auto transaction {session.createUniqueTransaction()};
session.create<TrackListEntry>(track1.get(), trackList.get(), now.addSecs(2));
}
{
auto transaction {session.createSharedTransaction()};
bool moreResults {};
const auto artists {trackList->getArtistsOrderedByRecentFirst({}, std::nullopt, std::nullopt, moreResults)};
ASSERT_EQ(artists.size(), 2);
EXPECT_EQ(artists[0]->getId(), artist1.getId());
EXPECT_EQ(artists[1]->getId(), artist2.getId());
const auto releases {trackList->getReleasesOrderedByRecentFirst({}, std::nullopt, moreResults)};
ASSERT_EQ(releases.size(), 2);
EXPECT_EQ(releases[0]->getId(), release1.getId());
EXPECT_EQ(releases[1]->getId(), release2.getId());
const auto tracks {trackList->getTracksOrderedByRecentFirst({}, std::nullopt, moreResults)};
ASSERT_EQ(tracks.size(), 2);
EXPECT_EQ(tracks[0]->getId(), track1.getId());
EXPECT_EQ(tracks[1]->getId(), track2.getId());
}
}
TEST_F(DatabaseFixture, SingleTrackList_getArtists)
{
ScopedUser user {session, "MyUser"};
ScopedTrackList trackList {session, "MytrackList", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrack track1 {session, "MyTrack1"};
ScopedTrack track2 {session, "MyTrack2"};
ScopedRelease release {session, "MyRelease"};
ScopedArtist artist1 {session, "MyArtist1"};
ScopedArtist artist2 {session, "MyArtist2"};
{
auto transaction {session.createSharedTransaction()};
EXPECT_EQ(trackList->getCount(), 0);
bool moreResults {};
const auto artists {trackList->getArtists({} /*clusters*/, std::nullopt /* linkType */, ArtistSortMethod::ByName, std::nullopt /* range */, moreResults)};
ASSERT_TRUE(artists.empty());
}
{
auto transaction {session.createUniqueTransaction()};
TrackArtistLink::create(session, track1.get(), artist1.get(), TrackArtistLinkType::Artist);
session.create<TrackListEntry>(track1.get(), trackList.get());
}
{
auto transaction {session.createSharedTransaction()};
EXPECT_EQ(trackList->getCount(), 1);
bool moreResults {};
const auto artists {trackList->getArtists({} /*clusters*/, std::nullopt /* linkType */, ArtistSortMethod::ByName, std::nullopt /* range */, moreResults)};
ASSERT_EQ(artists.size(), 1);
EXPECT_EQ(artists.front()->getId(), artist1.getId());
}
{
auto transaction {session.createSharedTransaction()};
bool moreResults {};
const auto artists {trackList->getArtists({} /*clusters*/, TrackArtistLinkType::ReleaseArtist, ArtistSortMethod::ByName, std::nullopt /* range */, moreResults)};
EXPECT_TRUE(artists.empty());
}
{
auto transaction {session.createSharedTransaction()};
bool moreResults {};
const auto artists {trackList->getArtists({} /*clusters*/, TrackArtistLinkType::Artist, ArtistSortMethod::ByName, std::nullopt /* range */, moreResults)};
ASSERT_EQ(artists.size(), 1);
EXPECT_EQ(artists.front()->getId(), artist1.getId());
}
{
auto transaction {session.createUniqueTransaction()};
TrackArtistLink::create(session, track2.get(), artist2.get(), TrackArtistLinkType::Artist);
session.create<TrackListEntry>(track2.get(), trackList.get());
artist1.get().modify()->setSortName("ZZZ");
artist2.get().modify()->setSortName("AAA");
}
{
auto transaction {session.createSharedTransaction()};
bool moreResults {};
const auto artists {trackList->getArtists({} /*clusters*/, TrackArtistLinkType::Artist, ArtistSortMethod::ByName, std::nullopt /* range */, moreResults)};
ASSERT_EQ(artists.size(), 2);
EXPECT_EQ(artists.front()->getId(), artist1.getId());
EXPECT_EQ(artists.back()->getId(), artist2.getId());
}
{
auto transaction {session.createSharedTransaction()};
bool moreResults {};
const auto artists {trackList->getArtists({} /*clusters*/, TrackArtistLinkType::Artist, ArtistSortMethod::BySortName, std::nullopt /* range */, moreResults)};
ASSERT_EQ(artists.size(), 2);
EXPECT_EQ(artists.front()->getId(), artist2.getId());
EXPECT_EQ(artists.back()->getId(), artist1.getId());
}
}
TEST_F(DatabaseFixture, SingleTrackList_getReleases)
{
ScopedUser user {session, "MyUser"};
ScopedTrackList trackList {session, "MytrackList", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrack track {session, "MyTrack"};
ScopedRelease release {session, "MyRelease"};
{
auto transaction {session.createSharedTransaction()};
EXPECT_EQ(trackList->getCount(), 0);
bool moreResults {};
const auto releases {trackList->getReleases({} /*clusters*/, std::nullopt /* range */, moreResults)};
ASSERT_TRUE(releases.empty());
}
{
auto transaction {session.createUniqueTransaction()};
track.get().modify()->setRelease(release.get());
session.create<TrackListEntry>(track.get(), trackList.get());
}
{
auto transaction {session.createSharedTransaction()};
ASSERT_EQ(trackList->getCount(), 1);
bool moreResults {};
const auto releases {trackList->getReleases({} /*clusters*/, std::nullopt /* range */, moreResults)};
ASSERT_EQ(releases.size(), 1);
ASSERT_EQ(releases.front()->getId(), release->getId());
}
}
TEST_F(DatabaseFixture, SingleTrackList_getTracks)
{
ScopedUser user {session, "MyUser"};
ScopedTrackList trackList {session, "MytrackList", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrack track1 {session, "MyTrack1"};
ScopedTrack track2 {session, "MyTrack1"};
{
auto transaction {session.createSharedTransaction()};
EXPECT_EQ(trackList->getCount(), 0);
bool moreResults {};
const auto tracks {trackList->getTracks({} /*clusters*/, std::nullopt /* range */, moreResults)};
ASSERT_TRUE(tracks.empty());
}
{
auto transaction {session.createUniqueTransaction()};
session.create<TrackListEntry>(track1.get(), trackList.get());
session.create<TrackListEntry>(track2.get(), trackList.get());
session.create<TrackListEntry>(track1.get(), trackList.get());
}
{
auto transaction {session.createSharedTransaction()};
ASSERT_EQ(trackList->getCount(), 3);
bool moreResults {};
const auto tracks {trackList->getTracks({} /*clusters*/, std::nullopt /* range */, moreResults)};
ASSERT_EQ(tracks.size(), 2);
ASSERT_EQ(tracks[0]->getId(), track1->getId());
ASSERT_EQ(tracks[1]->getId(), track2->getId());
}
// Same order
std::size_t i{};
for (const ScopedTrack& track : tracks)
EXPECT_EQ(track.getId(), trackIds[i++]);
}
}
TEST_F(DatabaseFixture, SingleTrackListSingleTrackWithCluster)
{
ScopedUser user {session, "MyUser"};
ScopedTrackList trackList1 {session, "MyTrackList1", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrackList trackList2 {session, "MyTrackList2", TrackListType::Playlist, false, user.lockAndGet()};
ScopedClusterType clusterType {session, "MyClusterType"};
ScopedCluster cluster {session, clusterType.lockAndGet(), "MyCluster"};
ScopedTrack track {session, "MyTrack"};
ScopedUser user{ session, "MyUser" };
ScopedTrackList trackList1{ session, "MyTrackList1", TrackListType::Playlist, false, user.lockAndGet() };
ScopedTrackList trackList2{ session, "MyTrackList2", TrackListType::Playlist, false, user.lockAndGet() };
ScopedClusterType clusterType{ session, "MyClusterType" };
ScopedCluster cluster{ session, clusterType.lockAndGet(), "MyCluster" };
ScopedTrack track{ session, "MyTrack" };
{
auto transaction {session.createSharedTransaction()};
{
auto transaction{ session.createSharedTransaction() };
auto trackLists {TrackList::find(session, TrackList::FindParameters {}.setClusters({cluster.getId()}))};
EXPECT_EQ(trackLists.results.size(), 0);
}
auto trackLists{ TrackList::find(session, TrackList::FindParameters {}.setClusters({cluster.getId()})) };
EXPECT_EQ(trackLists.results.size(), 0);
}
{
auto transaction {session.createUniqueTransaction()};
{
auto transaction{ session.createUniqueTransaction() };
session.create<TrackListEntry>(track.get(), trackList1.get());
cluster.get().modify()->addTrack(track.get());
}
session.create<TrackListEntry>(track.get(), trackList1.get());
cluster.get().modify()->addTrack(track.get());
}
{
auto transaction {session.createSharedTransaction()};
{
auto transaction{ session.createSharedTransaction() };
auto trackLists {TrackList::find(session, TrackList::FindParameters {}.setClusters({cluster.getId()}))};
ASSERT_EQ(trackLists.results.size(), 1);
EXPECT_EQ(trackLists.results.front(), trackList1.getId());
}
auto trackLists{ TrackList::find(session, TrackList::FindParameters {}.setClusters({cluster.getId()})) };
ASSERT_EQ(trackLists.results.size(), 1);
EXPECT_EQ(trackLists.results.front(), trackList1.getId());
}
}
TEST_F(DatabaseFixture, SingleTrackList_getEntries)
{
ScopedUser user {session, "MyUser"};
ScopedTrackList trackList {session, "MyTrackList", TrackListType::Playlist, false, user.lockAndGet()};
ScopedTrack track1 {session, "MyTrack"};
ScopedTrack track2 {session, "MyTrack"};
ScopedUser user{ session, "MyUser" };
ScopedTrackList trackList{ session, "MyTrackList", TrackListType::Playlist, false, user.lockAndGet() };
ScopedTrack track1{ session, "MyTrack" };
ScopedTrack track2{ session, "MyTrack" };
{
auto transaction {session.createUniqueTransaction()};
session.create<TrackListEntry>(track1.get(), trackList.get());
}
{
auto transaction{ session.createUniqueTransaction() };
session.create<TrackListEntry>(track1.get(), trackList.get());
}
{
auto transaction {session.createSharedTransaction()};
auto entries {trackList.get()->getEntries()};
ASSERT_EQ(entries.size(), 1);
EXPECT_EQ(entries.front()->getTrack()->getId(), track1.getId());
}
{
auto transaction{ session.createSharedTransaction() };
auto entries{ trackList.get()->getEntries() };
ASSERT_EQ(entries.size(), 1);
EXPECT_EQ(entries.front()->getTrack()->getId(), track1.getId());
}
{
auto transaction {session.createUniqueTransaction()};
session.create<TrackListEntry>(track2.get(), trackList.get());
}
{
auto transaction{ session.createUniqueTransaction() };
session.create<TrackListEntry>(track2.get(), trackList.get());
}
{
auto transaction {session.createSharedTransaction()};
auto entries {trackList.get()->getEntries()};
ASSERT_EQ(entries.size(), 2);
EXPECT_EQ(entries[0]->getTrack()->getId(), track1.getId());
EXPECT_EQ(entries[1]->getTrack()->getId(), track2.getId());
}
{
auto transaction{ session.createSharedTransaction() };
auto entries{ trackList.get()->getEntries() };
ASSERT_EQ(entries.size(), 2);
EXPECT_EQ(entries[0]->getTrack()->getId(), track1.getId());
EXPECT_EQ(entries[1]->getTrack()->getId(), track2.getId());
}
{
auto transaction {session.createSharedTransaction()};
auto entries {trackList.get()->getEntries(Range {1, 1})};
ASSERT_EQ(entries.size(), 1);
EXPECT_EQ(entries[0]->getTrack()->getId(), track2.getId());
}
{
auto transaction{ session.createSharedTransaction() };
auto entries{ trackList.get()->getEntries(Range {1, 1}) };
ASSERT_EQ(entries.size(), 1);
EXPECT_EQ(entries[0]->getTrack()->getId(), track2.getId());
}
}