Files
lms/src/libs/database/test/Track.cpp
T
2025-02-09 18:35:09 +01:00

442 lines
16 KiB
C++

/*
* Copyright (C) 2021 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Common.hpp"
#include <algorithm>
namespace lms::db::tests
{
TEST_F(DatabaseFixture, Track)
{
{
auto transaction{ session.createReadTransaction() };
EXPECT_EQ(Track::find(session, Track::FindParameters{}).results.size(), 0);
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 };
{
auto transaction{ session.createReadTransaction() };
EXPECT_EQ(Track::find(session, Track::FindParameters{}).results.size(), 1);
EXPECT_EQ(Track::getCount(session), 1);
EXPECT_TRUE(Track::exists(session, track.getId()));
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);
}
}
}
TEST_F(DatabaseFixture, Track_findByRangedIdBased)
{
ScopedTrack track1{ session };
ScopedTrack track2{ session };
ScopedTrack track3{ session };
ScopedMediaLibrary library{ session, "MyLibrary", "/root" };
ScopedMediaLibrary otherLibrary{ session, "OtherLibrary", "/otherRoot" };
{
auto transaction{ session.createWriteTransaction() };
track2.get().modify()->setMediaLibrary(library.get());
}
{
auto transaction{ session.createReadTransaction() };
TrackId lastRetrievedTrackId;
std::vector<Track::pointer> visitedTracks;
Track::find(session, lastRetrievedTrackId, 10, [&](const Track::pointer& track) {
visitedTracks.push_back(track);
});
ASSERT_EQ(visitedTracks.size(), 3);
EXPECT_EQ(visitedTracks[0]->getId(), track1.getId());
EXPECT_EQ(visitedTracks[1]->getId(), track2.getId());
EXPECT_EQ(visitedTracks[2]->getId(), track3.getId());
EXPECT_EQ(lastRetrievedTrackId, track3.getId());
}
{
auto transaction{ session.createReadTransaction() };
TrackId lastRetrievedTrackId{ track1.getId() };
std::vector<Track::pointer> visitedTracks;
Track::find(session, lastRetrievedTrackId, 1, [&](const Track::pointer& track) {
visitedTracks.push_back(track);
});
ASSERT_EQ(visitedTracks.size(), 1);
EXPECT_EQ(visitedTracks[0]->getId(), track2.getId());
EXPECT_EQ(lastRetrievedTrackId, track2.getId());
}
{
auto transaction{ session.createReadTransaction() };
TrackId lastRetrievedTrackId{ track1.getId() };
std::vector<Track::pointer> visitedTracks;
Track::find(session, lastRetrievedTrackId, 0, [&](const Track::pointer& track) {
visitedTracks.push_back(track);
});
ASSERT_EQ(visitedTracks.size(), 0);
EXPECT_EQ(lastRetrievedTrackId, track1.getId());
}
{
auto transaction{ session.createReadTransaction() };
TrackId lastRetrievedTrackId{};
std::vector<Track::pointer> visitedTracks;
Track::find(
session, lastRetrievedTrackId, 10, [&](const Track::pointer& track) {
visitedTracks.push_back(track);
},
otherLibrary.getId());
ASSERT_EQ(visitedTracks.size(), 0);
EXPECT_EQ(lastRetrievedTrackId, TrackId{});
}
{
auto transaction{ session.createReadTransaction() };
TrackId lastRetrievedTrackId{};
std::vector<Track::pointer> visitedTracks;
Track::find(
session, lastRetrievedTrackId, 10, [&](const Track::pointer& track) {
visitedTracks.push_back(track);
},
library.getId());
ASSERT_EQ(visitedTracks.size(), 1);
EXPECT_EQ(visitedTracks[0]->getId(), track2.getId());
EXPECT_EQ(lastRetrievedTrackId, track2.getId());
}
}
TEST_F(DatabaseFixture, Track_MediaLibrary)
{
ScopedTrack track{ session };
ScopedMediaLibrary library{ session, "MyLibrary", "/root" };
ScopedMediaLibrary otherLibrary{ session, "OtherLibrary", "/otherRoot" };
{
auto transaction{ session.createReadTransaction() };
EXPECT_TRUE(library->isEmpty());
EXPECT_TRUE(otherLibrary->isEmpty());
}
{
auto transaction{ session.createWriteTransaction() };
track.get().modify()->setMediaLibrary(library.get());
}
{
auto transaction{ session.createReadTransaction() };
EXPECT_FALSE(library->isEmpty());
EXPECT_TRUE(otherLibrary->isEmpty());
}
{
auto transaction{ session.createReadTransaction() };
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setMediaLibrary(library->getId()))) };
ASSERT_EQ(tracks.results.size(), 1);
EXPECT_EQ(tracks.results.front(), track.getId());
}
{
auto transaction{ session.createReadTransaction() };
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setFilters(Filters{}.setMediaLibrary(otherLibrary->getId()))) };
EXPECT_EQ(tracks.results.size(), 0);
}
}
TEST_F(DatabaseFixture, Track_noMediaLibrary)
{
ScopedTrack track{ session };
{
auto transaction{ session.createReadTransaction() };
MediaLibrary::pointer mediaLibrary{ track->getMediaLibrary() };
EXPECT_EQ(mediaLibrary, MediaLibrary::pointer{});
EXPECT_FALSE(mediaLibrary);
EXPECT_TRUE(!mediaLibrary);
}
}
TEST_F(DatabaseFixture, TrackNotExists)
{
auto transaction{ session.createReadTransaction() };
EXPECT_FALSE(Track::exists(session, TrackId{ 42 }));
EXPECT_EQ(Track::find(session, TrackId{ 42 }), Track::pointer{});
EXPECT_FALSE(Track::find(session, TrackId{ 42 }));
EXPECT_EQ(Track::find(session, Track::FindParameters{}).results.size(), 0);
{
auto track{ Track::find(session, TrackId{ 42 }) };
EXPECT_TRUE(!track);
EXPECT_FALSE(track);
}
}
TEST_F(DatabaseFixture, MultipleTracks)
{
ScopedTrack track1{ session };
ScopedTrack track2{ session };
{
auto transaction{ session.createReadTransaction() };
EXPECT_TRUE(track1.getId() != track2.getId());
EXPECT_TRUE(track1.get() != track2.get());
EXPECT_FALSE(track1.get() == track2.get());
}
}
TEST_F(DatabaseFixture, MultipleTracksSearchByFilter)
{
ScopedTrack track1{ session };
ScopedTrack track2{ session };
ScopedTrack track3{ session };
ScopedTrack track4{ session };
ScopedTrack track5{ session };
ScopedTrack track6{ session };
{
auto transaction{ session.createWriteTransaction() };
track1.get().modify()->setName("MyTrack");
track2.get().modify()->setName("MyTrack%");
track3.get().modify()->setName("MyTrack%Foo");
track4.get().modify()->setName("%MyTrack");
track5.get().modify()->setName("Foo%MyTrack");
track6.get().modify()->setName("M_Track");
}
{
auto transaction{ session.createReadTransaction() };
{
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setKeywords({ "Track" })) };
EXPECT_EQ(tracks.results.size(), 6);
}
{
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setKeywords({ "MyTrack" })) };
EXPECT_EQ(tracks.results.size(), 5);
EXPECT_TRUE(std::none_of(std::cbegin(tracks.results), std::cend(tracks.results), [&](const TrackId trackId) { return trackId == track6.getId(); }));
}
{
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setKeywords({ "MyTrack%" })) };
ASSERT_EQ(tracks.results.size(), 2);
EXPECT_EQ(tracks.results[0], track2.getId());
EXPECT_EQ(tracks.results[1], track3.getId());
}
{
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setKeywords({ "%MyTrack" })) };
ASSERT_EQ(tracks.results.size(), 2);
EXPECT_EQ(tracks.results[0], track4.getId());
EXPECT_EQ(tracks.results[1], track5.getId());
}
}
}
TEST_F(DatabaseFixture, Track_date)
{
ScopedTrack track{ session };
const core::PartialDateTime date{ 1995, 5, 5 };
const core::PartialDateTime originalDate{ 1994, 2, 2 };
{
auto transaction{ session.createReadTransaction() };
EXPECT_EQ(track->getYear(), std::nullopt);
EXPECT_EQ(track->getOriginalYear(), std::nullopt);
}
{
auto transaction{ session.createWriteTransaction() };
track.get().modify()->setDate(date);
track.get().modify()->setOriginalDate(originalDate);
}
{
auto transaction{ session.createReadTransaction() };
EXPECT_EQ(track->getYear(), 1995);
EXPECT_EQ(track->getOriginalYear(), 1994);
EXPECT_EQ(track->getDate(), date);
EXPECT_EQ(track->getOriginalDate(), originalDate);
}
{
auto transaction{ session.createReadTransaction() };
EXPECT_EQ(track->getYear(), date.getYear());
EXPECT_EQ(track->getOriginalYear(), originalDate.getYear());
}
}
TEST_F(DatabaseFixture, Track_writtenAfter)
{
ScopedTrack track{ session };
const Wt::WDateTime dateTime{ Wt::WDate{ 1950, 1, 1 }, Wt::WTime{ 12, 30, 20 } };
{
auto transaction{ session.createWriteTransaction() };
track.get().modify()->setLastWriteTime(dateTime);
}
{
auto transaction{ session.createReadTransaction() };
const auto tracks{ Track::findIds(session, Track::FindParameters{}) };
EXPECT_EQ(tracks.results.size(), 1);
}
{
auto transaction{ session.createReadTransaction() };
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setWrittenAfter(dateTime.addSecs(-1))) };
EXPECT_EQ(tracks.results.size(), 1);
}
{
auto transaction{ session.createReadTransaction() };
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setWrittenAfter(dateTime.addSecs(+1))) };
EXPECT_EQ(tracks.results.size(), 0);
}
}
TEST_F(DatabaseFixture, Track_path)
{
ScopedTrack track{ session };
{
auto transaction{ session.createWriteTransaction() };
track.get().modify()->setAbsoluteFilePath("/root/foo/file.path");
track.get().modify()->setRelativeFilePath("foo/file.path");
}
{
auto transaction{ session.createReadTransaction() };
EXPECT_EQ(track->getAbsoluteFilePath(), "/root/foo/file.path");
EXPECT_EQ(track->getRelativeFilePath(), "foo/file.path");
}
}
TEST_F(DatabaseFixture, Track_audioProperties)
{
ScopedTrack track{ session };
{
auto transaction{ session.createWriteTransaction() };
track.get().modify()->setBitrate(128000);
track.get().modify()->setBitsPerSample(16);
track.get().modify()->setDuration(std::chrono::minutes{ 3 });
track.get().modify()->setChannelCount(2);
track.get().modify()->setSampleRate(44100);
}
{
auto transaction{ session.createReadTransaction() };
EXPECT_EQ(track->getBitrate(), 128000);
EXPECT_EQ(track->getBitsPerSample(), 16);
EXPECT_EQ(track->getDuration(), std::chrono::minutes{ 3 });
EXPECT_EQ(track->getChannelCount(), 2);
EXPECT_EQ(track->getSampleRate(), 44100);
}
}
TEST_F(DatabaseFixture, Track_comment)
{
ScopedTrack track{ session };
{
auto transaction{ session.createReadTransaction() };
EXPECT_EQ(track->getComment(), "");
}
{
auto transaction{ session.createWriteTransaction() };
track.get().modify()->setComment("MyComment");
}
{
auto transaction{ session.createReadTransaction() };
EXPECT_EQ(track->getComment(), "MyComment");
}
}
TEST_F(DatabaseFixture, Track_sortDateAdded)
{
ScopedTrack track1{ session };
ScopedTrack track2{ session };
ScopedTrack track3{ session };
ScopedTrack track4{ session };
{
auto transaction{ session.createWriteTransaction() };
track1.get().modify()->setAddedTime(Wt::WDateTime{ Wt::WDate{ 2021, 1, 2 } });
track2.get().modify()->setAddedTime(Wt::WDateTime{ Wt::WDate{ 2021, 1, 1 } });
track4.get().modify()->setAddedTime(Wt::WDateTime{ Wt::WDate{ 2021, 1, 2 }, Wt::WTime{ 15, 36, 24 } });
}
{
auto transaction{ session.createReadTransaction() };
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setSortMethod(TrackSortMethod::AddedDesc)) };
ASSERT_EQ(tracks.results.size(), 4);
EXPECT_EQ(tracks.results[0], track4.getId());
EXPECT_EQ(tracks.results[1], track1.getId());
EXPECT_EQ(tracks.results[2], track2.getId());
EXPECT_EQ(tracks.results[3], track3.getId());
}
}
TEST_F(DatabaseFixture, Track_sortLastWritten)
{
ScopedTrack track1{ session };
ScopedTrack track2{ session };
ScopedTrack track3{ session };
ScopedTrack track4{ session };
{
auto transaction{ session.createWriteTransaction() };
track1.get().modify()->setLastWriteTime(Wt::WDateTime{ Wt::WDate{ 2021, 1, 2 } });
track2.get().modify()->setLastWriteTime(Wt::WDateTime{ Wt::WDate{ 2021, 1, 1 } });
track4.get().modify()->setLastWriteTime(Wt::WDateTime{ Wt::WDate{ 2021, 1, 2 }, Wt::WTime{ 15, 36, 24 } });
}
{
auto transaction{ session.createReadTransaction() };
const auto tracks{ Track::findIds(session, Track::FindParameters{}.setSortMethod(TrackSortMethod::LastWrittenDesc)) };
ASSERT_EQ(tracks.results.size(), 4);
EXPECT_EQ(tracks.results[0], track4.getId());
EXPECT_EQ(tracks.results[1], track1.getId());
EXPECT_EQ(tracks.results[2], track2.getId());
EXPECT_EQ(tracks.results[3], track3.getId());
}
}
} // namespace lms::db::tests