strawberry-audio-player-win.../tests/src/collectionmodel_test.cpp

703 lines
28 KiB
C++
Raw Normal View History

2019-06-28 01:33:22 +02:00
/*
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2019, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry 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.
*
* Strawberry 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 Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <memory>
#include <gtest/gtest.h>
#include <QMap>
2019-06-28 01:33:22 +02:00
#include <QString>
#include <QUrl>
#include <QThread>
#include <QSignalSpy>
#include <QSortFilterProxyModel>
#include <QtDebug>
#include "core/logging.h"
#include "core/scoped_ptr.h"
#include "core/shared_ptr.h"
2019-06-28 01:33:22 +02:00
#include "core/database.h"
#include "collection/collectionmodel.h"
#include "collection/collectionbackend.h"
#include "collection/collection.h"
using std::make_unique;
using std::make_shared;
2021-06-20 19:04:08 +02:00
// clazy:excludeall=non-pod-global-static,returning-void-expression
2019-06-28 01:33:22 +02:00
namespace {
class CollectionModelTest : public ::testing::Test {
public:
CollectionModelTest() : added_dir_(false) {}
2019-06-28 01:33:22 +02:00
protected:
2020-06-15 21:55:05 +02:00
void SetUp() override {
database_ = make_shared<MemoryDatabase>(nullptr);
backend_ = make_shared<CollectionBackend>();
2024-04-21 19:37:39 +02:00
backend_->Init(database_, nullptr, Song::Source::Collection, QLatin1String(SCollection::kSongsTable), QLatin1String(SCollection::kFtsTable), QLatin1String(SCollection::kDirsTable), QLatin1String(SCollection::kSubdirsTable));
model_ = make_unique<CollectionModel>(backend_, nullptr);
2019-06-28 01:33:22 +02:00
added_dir_ = false;
model_sorted_ = make_unique<QSortFilterProxyModel>();
model_sorted_->setSourceModel(&*model_);
2019-06-28 01:33:22 +02:00
model_sorted_->setSortRole(CollectionModel::Role_SortText);
model_sorted_->setDynamicSortFilter(true);
model_sorted_->sort(0);
2019-06-28 01:33:22 +02:00
}
Song AddSong(Song &song) {
2019-06-28 01:33:22 +02:00
song.set_directory_id(1);
2020-04-23 21:01:34 +02:00
if (song.mtime() == 0) song.set_mtime(1);
if (song.ctime() == 0) song.set_ctime(1);
2024-04-21 19:37:39 +02:00
if (song.url().isEmpty()) song.set_url(QUrl(QStringLiteral("file:///tmp/foo")));
2019-06-28 01:33:22 +02:00
if (song.filesize() == -1) song.set_filesize(1);
if (!added_dir_) {
2024-04-21 19:37:39 +02:00
backend_->AddDirectory(QStringLiteral("/tmp"));
2019-06-28 01:33:22 +02:00
added_dir_ = true;
}
backend_->AddOrUpdateSongs(SongList() << song);
return song;
}
Song AddSong(const QString &title, const QString &artist, const QString &album, const int length) {
2019-06-28 01:33:22 +02:00
Song song;
song.Init(title, artist, album, length);
2020-05-16 19:17:06 +02:00
song.set_mtime(0);
song.set_ctime(0);
2019-06-28 01:33:22 +02:00
return AddSong(song);
}
SharedPtr<Database> database_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
SharedPtr<CollectionBackend> backend_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
ScopedPtr<CollectionModel> model_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
ScopedPtr<QSortFilterProxyModel> model_sorted_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
2019-06-28 01:33:22 +02:00
2021-06-20 19:04:08 +02:00
bool added_dir_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
2019-06-28 01:33:22 +02:00
};
2020-10-17 17:29:09 +02:00
TEST_F(CollectionModelTest, Initialization) {
2019-06-28 01:33:22 +02:00
EXPECT_EQ(0, model_->rowCount(QModelIndex()));
}
TEST_F(CollectionModelTest, WithInitialArtists) {
2024-04-21 19:37:39 +02:00
AddSong(QStringLiteral("Title"), QStringLiteral("Artist 1"), QStringLiteral("Album"), 123);
AddSong(QStringLiteral("Title"), QStringLiteral("Artist 2"), QStringLiteral("Album"), 123);
AddSong(QStringLiteral("Title"), QStringLiteral("Foo"), QStringLiteral("Album"), 123);
2019-06-28 01:33:22 +02:00
model_->Init(false);
ASSERT_EQ(5, model_sorted_->rowCount(QModelIndex()));
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("A"), model_sorted_->index(0, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("Artist 1"), model_sorted_->index(1, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("Artist 2"), model_sorted_->index(2, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("F"), model_sorted_->index(3, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("Foo"), model_sorted_->index(4, 0, QModelIndex()).data().toString());
2019-06-28 01:33:22 +02:00
}
TEST_F(CollectionModelTest, CompilationAlbums) {
Song song;
2024-04-21 19:37:39 +02:00
song.Init(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral("Album"), 123);
2019-06-28 01:33:22 +02:00
song.set_compilation(true);
2020-05-16 19:17:06 +02:00
song.set_mtime(0);
song.set_ctime(0);
2019-06-28 01:33:22 +02:00
AddSong(song);
model_->Init(false);
model_->fetchMore(model_->index(0, 0));
ASSERT_EQ(1, model_->rowCount(QModelIndex()));
QModelIndex va_index = model_->index(0, 0, QModelIndex());
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("Various artists"), va_index.data().toString());
2019-06-28 01:33:22 +02:00
EXPECT_TRUE(model_->hasChildren(va_index));
ASSERT_EQ(model_->rowCount(va_index), 1);
QModelIndex album_index = model_->index(0, 0, va_index);
2024-04-21 19:37:39 +02:00
EXPECT_EQ(model_->data(album_index).toString(), QStringLiteral("Album"));
2019-06-28 01:33:22 +02:00
EXPECT_TRUE(model_->hasChildren(album_index));
}
TEST_F(CollectionModelTest, NumericHeaders) {
2024-04-21 19:37:39 +02:00
AddSong(QStringLiteral("Title"), QStringLiteral("1artist"), QStringLiteral("Album"), 123);
AddSong(QStringLiteral("Title"), QStringLiteral("2artist"), QStringLiteral("Album"), 123);
AddSong(QStringLiteral("Title"), QStringLiteral("0artist"), QStringLiteral("Album"), 123);
AddSong(QStringLiteral("Title"), QStringLiteral("zartist"), QStringLiteral("Album"), 123);
2019-06-28 01:33:22 +02:00
model_->Init(false);
ASSERT_EQ(6, model_sorted_->rowCount(QModelIndex()));
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("0-9"), model_sorted_->index(0, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("0artist"), model_sorted_->index(1, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("1artist"), model_sorted_->index(2, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("2artist"), model_sorted_->index(3, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("Z"), model_sorted_->index(4, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("zartist"), model_sorted_->index(5, 0, QModelIndex()).data().toString());
2019-06-28 01:33:22 +02:00
}
TEST_F(CollectionModelTest, MixedCaseHeaders) {
2024-04-21 19:37:39 +02:00
AddSong(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral("Album"), 123);
AddSong(QStringLiteral("Title"), QStringLiteral("artist"), QStringLiteral("Album"), 123);
2019-06-28 01:33:22 +02:00
model_->Init(false);
ASSERT_EQ(3, model_sorted_->rowCount(QModelIndex()));
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("A"), model_sorted_->index(0, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("Artist"), model_sorted_->index(1, 0, QModelIndex()).data().toString());
EXPECT_EQ(QStringLiteral("artist"), model_sorted_->index(2, 0, QModelIndex()).data().toString());
2019-06-28 01:33:22 +02:00
}
TEST_F(CollectionModelTest, UnknownArtists) {
2024-04-21 19:37:39 +02:00
AddSong(QStringLiteral("Title"), QStringLiteral(""), QStringLiteral("Album"), 123);
2019-06-28 01:33:22 +02:00
model_->Init(false);
model_->fetchMore(model_->index(0, 0));
ASSERT_EQ(1, model_->rowCount(QModelIndex()));
QModelIndex unknown_index = model_->index(0, 0, QModelIndex());
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("Unknown"), unknown_index.data().toString());
2019-06-28 01:33:22 +02:00
ASSERT_EQ(1, model_->rowCount(unknown_index));
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("Album"), model_->index(0, 0, unknown_index).data().toString());
2019-06-28 01:33:22 +02:00
}
TEST_F(CollectionModelTest, UnknownAlbums) {
2024-04-21 19:37:39 +02:00
AddSong(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral(""), 123);
AddSong(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral("Album"), 123);
2019-06-28 01:33:22 +02:00
model_->Init(false);
model_->fetchMore(model_->index(0, 0));
QModelIndex artist_index = model_->index(0, 0, QModelIndex());
ASSERT_EQ(2, model_->rowCount(artist_index));
QModelIndex unknown_album_index = model_->index(0, 0, artist_index);
QModelIndex real_album_index = model_->index(1, 0, artist_index);
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("Unknown"), unknown_album_index.data().toString());
EXPECT_EQ(QStringLiteral("Album"), real_album_index.data().toString());
2019-06-28 01:33:22 +02:00
}
TEST_F(CollectionModelTest, VariousArtistSongs) {
SongList songs;
for (int i=0 ; i < 4 ; ++i) {
QString n = QString::number(i+1);
Song song;
2024-04-21 19:37:39 +02:00
song.Init(QStringLiteral("Title ") + n, QStringLiteral("Artist ") + n, QStringLiteral("Album"), 0);
2020-05-16 19:17:06 +02:00
song.set_mtime(0);
song.set_ctime(0);
2021-06-20 19:04:08 +02:00
songs << song; // clazy:exclude=reserve-candidates
2019-06-28 01:33:22 +02:00
}
// Different ways of putting songs in "Various Artist". Make sure they all work
songs[0].set_compilation_detected(true);
songs[1].set_compilation(true);
songs[2].set_compilation_on(true);
2024-04-21 19:37:39 +02:00
songs[3].set_compilation_detected(true); songs[3].set_artist(QStringLiteral("Various Artists"));
2019-06-28 01:33:22 +02:00
2021-06-20 19:04:08 +02:00
for (int i=0 ; i < 4 ; ++i)
2019-06-28 01:33:22 +02:00
AddSong(songs[i]);
model_->Init(false);
QModelIndex artist_index = model_->index(0, 0, QModelIndex());
model_->fetchMore(artist_index);
ASSERT_EQ(1, model_->rowCount(artist_index));
QModelIndex album_index = model_->index(0, 0, artist_index);
model_->fetchMore(album_index);
ASSERT_EQ(4, model_->rowCount(album_index));
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("Artist 1 - Title 1"), model_->index(0, 0, album_index).data().toString());
EXPECT_EQ(QStringLiteral("Artist 2 - Title 2"), model_->index(1, 0, album_index).data().toString());
EXPECT_EQ(QStringLiteral("Artist 3 - Title 3"), model_->index(2, 0, album_index).data().toString());
EXPECT_EQ(QStringLiteral("Title 4"), model_->index(3, 0, album_index).data().toString());
2019-06-28 01:33:22 +02:00
}
TEST_F(CollectionModelTest, RemoveSongsLazyLoaded) {
2024-04-21 19:37:39 +02:00
Song one = AddSong(QStringLiteral("Title 1"), QStringLiteral("Artist"), QStringLiteral("Album"), 123); one.set_id(1);
Song two = AddSong(QStringLiteral("Title 2"), QStringLiteral("Artist"), QStringLiteral("Album"), 123); two.set_id(2);
AddSong(QStringLiteral("Title 3"), QStringLiteral("Artist"), QStringLiteral("Album"), 123);
2019-06-28 01:33:22 +02:00
model_->Init(false);
// Lazy load the items
QModelIndex artist_index = model_->index(0, 0, QModelIndex());
model_->fetchMore(artist_index);
ASSERT_EQ(1, model_->rowCount(artist_index));
QModelIndex album_index = model_->index(0, 0, artist_index);
model_->fetchMore(album_index);
ASSERT_EQ(3, model_->rowCount(album_index));
// Remove the first two songs
QSignalSpy spy_preremove(&*model_, &CollectionModel::rowsAboutToBeRemoved);
QSignalSpy spy_remove(&*model_, &CollectionModel::rowsRemoved);
QSignalSpy spy_reset(&*model_, &CollectionModel::modelReset);
2019-06-28 01:33:22 +02:00
backend_->DeleteSongs(SongList() << one << two);
ASSERT_EQ(2, spy_preremove.count());
ASSERT_EQ(2, spy_remove.count());
ASSERT_EQ(0, spy_reset.count());
artist_index = model_->index(0, 0, QModelIndex());
ASSERT_EQ(1, model_->rowCount(artist_index));
album_index = model_->index(0, 0, artist_index);
ASSERT_EQ(1, model_->rowCount(album_index));
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("Title 3"), model_->index(0, 0, album_index).data().toString());
2019-06-28 01:33:22 +02:00
}
TEST_F(CollectionModelTest, RemoveSongsNotLazyLoaded) {
2024-04-21 19:37:39 +02:00
Song one = AddSong(QStringLiteral("Title 1"), QStringLiteral("Artist"), QStringLiteral("Album"), 123); one.set_id(1);
Song two = AddSong(QStringLiteral("Title 2"), QStringLiteral("Artist"), QStringLiteral("Album"), 123); two.set_id(2);
2019-06-28 01:33:22 +02:00
model_->Init(false);
// Remove the first two songs
QSignalSpy spy_preremove(&*model_, &CollectionModel::rowsAboutToBeRemoved);
QSignalSpy spy_remove(&*model_, &CollectionModel::rowsRemoved);
QSignalSpy spy_reset(&*model_, &CollectionModel::modelReset);
2019-06-28 01:33:22 +02:00
backend_->DeleteSongs(SongList() << one << two);
ASSERT_EQ(0, spy_preremove.count());
ASSERT_EQ(0, spy_remove.count());
ASSERT_EQ(1, spy_reset.count());
}
TEST_F(CollectionModelTest, RemoveEmptyAlbums) {
2024-04-21 19:37:39 +02:00
Song one = AddSong(QStringLiteral("Title 1"), QStringLiteral("Artist"), QStringLiteral("Album 1"), 123); one.set_id(1);
Song two = AddSong(QStringLiteral("Title 2"), QStringLiteral("Artist"), QStringLiteral("Album 2"), 123); two.set_id(2);
Song three = AddSong(QStringLiteral("Title 3"), QStringLiteral("Artist"), QStringLiteral("Album 2"), 123); three.set_id(3);
2019-06-28 01:33:22 +02:00
model_->Init(false);
QModelIndex artist_index = model_->index(0, 0, QModelIndex());
model_->fetchMore(artist_index);
ASSERT_EQ(2, model_->rowCount(artist_index));
// Remove one song from each album
backend_->DeleteSongs(SongList() << one << two);
// Check the model
artist_index = model_->index(0, 0, QModelIndex());
model_->fetchMore(artist_index);
ASSERT_EQ(1, model_->rowCount(artist_index));
QModelIndex album_index = model_->index(0, 0, artist_index);
model_->fetchMore(album_index);
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("Album 2"), album_index.data().toString());
2019-06-28 01:33:22 +02:00
ASSERT_EQ(1, model_->rowCount(album_index));
2024-04-21 19:37:39 +02:00
EXPECT_EQ(QStringLiteral("Title 3"), model_->index(0, 0, album_index).data().toString());
2019-06-28 01:33:22 +02:00
}
TEST_F(CollectionModelTest, RemoveEmptyArtists) {
2024-04-21 19:37:39 +02:00
Song one = AddSong(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral("Album"), 123); one.set_id(1);
2019-06-28 01:33:22 +02:00
model_->Init(false);
// Lazy load the items
QModelIndex artist_index = model_->index(0, 0, QModelIndex());
model_->fetchMore(artist_index);
ASSERT_EQ(1, model_->rowCount(artist_index));
QModelIndex album_index = model_->index(0, 0, artist_index);
model_->fetchMore(album_index);
ASSERT_EQ(1, model_->rowCount(album_index));
// The artist header is there too right?
ASSERT_EQ(2, model_->rowCount(QModelIndex()));
// Remove the song
backend_->DeleteSongs(SongList() << one);
// Everything should be gone - even the artist header
ASSERT_EQ(0, model_->rowCount(QModelIndex()));
}
// Test to check that the container nodes are created identical and unique all through the model with all possible collection groupings.
// model1 - Nodes are created from a complete reset done through lazy-loading.
// model2 - Initial container nodes are created in SongsDiscovered.
// model3 - All container nodes are created in SongsDiscovered.
// WARNING: This test can take up to 30 minutes to complete.
2020-10-19 22:32:50 +02:00
#if 0
TEST_F(CollectionModelTest, TestContainerNodes) {
SongList songs;
int year = 1960;
// Add some normal albums.
for (int artist_number = 1; artist_number <= 3 ; ++artist_number) {
2023-02-18 14:09:27 +01:00
Song song(Song::Source::Collection);
song.set_artist(QString("Artist %1").arg(artist_number));
song.set_composer(QString("Composer %1").arg(artist_number));
song.set_performer(QString("Performer %1").arg(artist_number));
song.set_mtime(1);
song.set_ctime(1);
song.set_directory_id(1);
song.set_filetype(Song::FileType_FLAC);
song.set_filesize(1);
for (int album_number = 1; album_number <= 3 ; ++album_number) {
if (year > 2020) year = 1960;
song.set_album(QString("Artist %1 - Album %2").arg(artist_number).arg(album_number));
song.set_album_id(QString::number(album_number));
song.set_year(year++);
song.set_genre("Rock");
for (int song_number = 1; song_number <= 5 ; ++song_number) {
song.set_url(QUrl(QString("file:///mnt/music/Artist %1/Album %2/%3 - artist song-n-%3").arg(artist_number).arg(album_number).arg(song_number)));
song.set_title(QString("Title %1").arg(song_number));
song.set_track(song_number);
songs << song;
}
}
}
// Add some albums with 'album artist'.
for (int album_artist_number = 1; album_artist_number <= 3 ; ++album_artist_number) {
2023-02-18 14:09:27 +01:00
Song song(Song::Source::Collection);
song.set_albumartist(QString("Album Artist %1").arg(album_artist_number));
song.set_composer(QString("Composer %1").arg(album_artist_number));
song.set_performer(QString("Performer %1").arg(album_artist_number));
song.set_mtime(1);
song.set_ctime(1);
song.set_directory_id(1);
song.set_filetype(Song::FileType_FLAC);
song.set_filesize(1);
for (int album_number = 1; album_number <= 3 ; ++album_number) {
if (year > 2020) year = 1960;
song.set_album(QString("Album Artist %1 - Album %2").arg(album_artist_number).arg(album_number));
song.set_album_id(QString::number(album_number));
song.set_year(year++);
song.set_genre("Rock");
int artist_number = 1;
for (int song_number = 1; song_number <= 5 ; ++song_number) {
song.set_url(QUrl(QString("file:///mnt/music/Album Artist %1/Album %2/%3 - album artist song-n-%3").arg(album_artist_number).arg(album_number).arg(QString::number(song_number))));
song.set_title("Title " + QString::number(song_number));
song.set_track(song_number);
song.set_artist("Artist " + QString::number(artist_number));
songs << song;
++artist_number;
}
}
}
// Add some compilation albums.
for (int album_number = 1; album_number <= 3 ; ++album_number) {
if (year > 2020) year = 1960;
2023-02-18 14:09:27 +01:00
Song song(Song::Source::Collection);
song.set_mtime(1);
song.set_ctime(1);
song.set_directory_id(1);
song.set_filetype(Song::FileType_FLAC);
song.set_filesize(1);
song.set_album(QString("Compilation Album %1").arg(album_number));
song.set_album_id(QString::number(album_number));
song.set_year(year++);
song.set_genre("Pop");
song.set_compilation(true);
int artist_number = 1;
for (int song_number = 1; song_number <= 4 ; ++song_number) {
song.set_url(QUrl(QString("file:///mnt/music/Compilation Artist %1/Compilation Album %2/%3 - compilation song-n-%3").arg(artist_number).arg(album_number).arg(QString::number(song_number))));
song.set_artist(QString("Compilation Artist %1").arg(artist_number));
song.set_composer(QString("Composer %1").arg(artist_number));
song.set_performer(QString("Performer %1").arg(artist_number));
song.set_title(QString("Title %1").arg(song_number));
song.set_track(song_number);
songs << song;
++artist_number;
}
}
// Songs with only title
{
2023-02-18 14:09:27 +01:00
Song song(Song::Source::Collection);
song.set_mtime(1);
song.set_ctime(1);
song.set_directory_id(1);
song.set_filetype(Song::FileType_FLAC);
song.set_filesize(1);
song.set_url(QUrl(QString("file:///mnt/music/no album song 1/song-only-1")));
song.set_title("Only Title 1");
songs << song;
song.set_url(QUrl(QString("file:///mnt/music/no album song 2/song-only-2")));
song.set_title("Only Title 2");
songs << song;
}
// Song with only artist, album and title.
{
2023-02-18 14:09:27 +01:00
Song song(Song::Source::Collection);
song.set_url(QUrl(QString("file:///tmp/artist-album-title-song")));
song.set_artist("Not Only Artist");
song.set_album("Not Only Album");
song.set_title("Not Only Title");
song.set_mtime(1);
song.set_ctime(1);
song.set_directory_id(1);
song.set_filetype(Song::FileType_FLAC);
song.set_filesize(1);
song.set_year(1970);
song.set_track(1);
songs << song;
}
// Add possible Various artists conflicting songs.
{
2023-02-18 14:09:27 +01:00
Song song(Song::Source::Collection);
song.set_url(QUrl(QString("file:///tmp/song-va-conflicting-1")));
song.set_artist("Various artists");
song.set_album("VA Album");
song.set_title("VA Title");
song.set_mtime(1);
song.set_ctime(1);
song.set_directory_id(1);
song.set_filetype(Song::FileType_FLAC);
song.set_filesize(1);
song.set_year(1970);
song.set_track(1);
songs << song;
}
{
2023-02-18 14:09:27 +01:00
Song song(Song::Source::Collection);
song.set_url(QUrl(QString("file:///tmp/song-va-conflicting-2")));
song.set_artist("Various artists");
song.set_albumartist("Various artists");
song.set_album("VA Album");
song.set_title("VA Title");
song.set_mtime(1);
song.set_ctime(1);
song.set_directory_id(1);
song.set_filetype(Song::FileType_FLAC);
song.set_filesize(1);
song.set_year(1970);
song.set_track(1);
songs << song;
}
{
2023-02-18 14:09:27 +01:00
Song song(Song::Source::Collection);
song.set_url(QUrl(QString("file:///tmp/song-va-conflicting-3")));
song.set_albumartist("Various artists");
song.set_album("VA Album");
song.set_title("VA Title");
song.set_mtime(1);
song.set_ctime(1);
song.set_directory_id(1);
song.set_filetype(Song::FileType_FLAC);
song.set_filesize(1);
song.set_year(1970);
song.set_track(1);
songs << song;
}
// Albums with Album ID.
for (int album_id = 0; album_id <= 2 ; ++album_id) {
2023-02-18 14:09:27 +01:00
Song song(Song::Source::Collection);
song.set_url(QUrl(QString("file:///tmp/song-with-album-id-1")));
song.set_artist("Artist with Album ID");
song.set_album(QString("Album %1 with Album ID").arg(album_id));
song.set_album_id(QString("Album ID %1").arg(album_id));
song.set_mtime(1);
song.set_ctime(1);
song.set_directory_id(1);
song.set_filetype(Song::FileType_FLAC);
song.set_filesize(1);
song.set_year(1970);
for (int i = 0; i <= 3 ; ++i) {
song.set_title(QString("Title %1 %2").arg(album_id).arg(i));
song.set_track(i);
songs << song;
}
}
for (int f = CollectionModel::GroupBy_None + 1 ; f < CollectionModel::GroupByCount ; ++f) {
for (int s = CollectionModel::GroupBy_None ; s < CollectionModel::GroupByCount ; ++s) {
for (int t = CollectionModel::GroupBy_None ; t < CollectionModel::GroupByCount ; ++t) {
qLog(Debug) << "Testing collection model grouping: " << f << s << t;
ScopedPtr<Database> database1;
ScopedPtr<Database> database2;
ScopedPtr<Database> database3;
ScopedPtr<CollectionBackend> backend1;
ScopedPtr<CollectionBackend> backend2;
ScopedPtr<CollectionBackend> backend3;
ScopedPtr<CollectionModel> model1;
ScopedPtr<CollectionModel> model2;
ScopedPtr<CollectionModel> model3;
database1 = make_unique<MemoryDatabase>(nullptr);
database2 = make_unique<MemoryDatabase>(nullptr);
database3 = make_unique<MemoryDatabase>(nullptr);
backend1 = make_unique<CollectionBackend>();
backend2= make_unique<CollectionBackend>();
backend3 = make_unique<CollectionBackend>();
2023-02-18 14:09:27 +01:00
backend1->Init(database1.get(), Song::Source::Collection, SCollection::kSongsTable, SCollection::kFtsTable, SCollection::kDirsTable, SCollection::kSubdirsTable);
backend2->Init(database2.get(), Song::Source::Collection, SCollection::kSongsTable, SCollection::kFtsTable, SCollection::kDirsTable, SCollection::kSubdirsTable);
backend3->Init(database3.get(), Song::Source::Collection, SCollection::kSongsTable, SCollection::kFtsTable, SCollection::kDirsTable, SCollection::kSubdirsTable);
model1 = make_unique<CollectionModel>(backend1.get(), nullptr);
model2 = make_unique<CollectionModel>(backend2.get(), nullptr);
model3 = make_unique<CollectionModel>(backend3.get(), nullptr);
backend1->AddDirectory("/mnt/music");
backend2->AddDirectory("/mnt/music");
backend3->AddDirectory("/mut/music");
model1->SetGroupBy(CollectionModel::Grouping(CollectionModel::GroupBy(f), CollectionModel::GroupBy(s), CollectionModel::GroupBy(t)));
model2->SetGroupBy(CollectionModel::Grouping(CollectionModel::GroupBy(f), CollectionModel::GroupBy(s), CollectionModel::GroupBy(t)));
model3->SetGroupBy(CollectionModel::Grouping(CollectionModel::GroupBy(f), CollectionModel::GroupBy(s), CollectionModel::GroupBy(t)));
model3->set_use_lazy_loading(false);
2021-01-26 16:48:04 +01:00
QSignalSpy model1_update(model1.get(), &CollectionModel::rowsInserted);
QSignalSpy model2_update(model2.get(), &CollectionModel::rowsInserted);
QSignalSpy model3_update(model3.get(), &CollectionModel::rowsInserted);
backend1->AddOrUpdateSongs(songs);
backend2->AddOrUpdateSongs(songs);
backend3->AddOrUpdateSongs(songs);
ASSERT_EQ(model1->song_nodes().count(), 0);
ASSERT_EQ(model2->song_nodes().count(), 0);
ASSERT_EQ(model3->song_nodes().count(), songs.count());
model1->Init(false);
model1->ExpandAll();
model2->ExpandAll();
// All nodes in model3 should be created already.
ASSERT_EQ(model1->song_nodes().count(), songs.count());
ASSERT_EQ(model2->song_nodes().count(), songs.count());
ASSERT_EQ(model3->song_nodes().count(), songs.count());
2021-07-02 18:45:53 +02:00
// Container nodes for all models should now be identical.
for (int i = 0 ; i < 3 ; ++i) {
for (CollectionItem *node : model1->container_nodes(i).values()) {
ASSERT_TRUE(model2->container_nodes(i).keys().contains(node->key));
CollectionItem *node2 = model2->container_nodes(i)[node->key];
ASSERT_EQ(node->key, node2->key);
ASSERT_EQ(node->display_text, node2->display_text);
ASSERT_EQ(node->sort_text, node2->sort_text);
}
for (CollectionItem *node : model1->container_nodes(i).values()) {
ASSERT_TRUE(model3->container_nodes(i).keys().contains(node->key));
CollectionItem *node2 = model2->container_nodes(i)[node->key];
ASSERT_EQ(node->key, node2->key);
ASSERT_EQ(node->display_text, node2->display_text);
ASSERT_EQ(node->sort_text, node2->sort_text);
}
for (CollectionItem *node : model2->container_nodes(i).values()) {
ASSERT_TRUE(model1->container_nodes(i).keys().contains(node->key));
CollectionItem *node2 = model2->container_nodes(i)[node->key];
ASSERT_EQ(node->key, node2->key);
ASSERT_EQ(node->display_text, node2->display_text);
ASSERT_EQ(node->sort_text, node2->sort_text);
}
for (CollectionItem *node : model2->container_nodes(i).values()) {
ASSERT_TRUE(model3->container_nodes(i).keys().contains(node->key));
CollectionItem *node2 = model2->container_nodes(i)[node->key];
ASSERT_EQ(node->key, node2->key);
ASSERT_EQ(node->display_text, node2->display_text);
ASSERT_EQ(node->sort_text, node2->sort_text);
}
for (CollectionItem *node : model3->container_nodes(i).values()) {
ASSERT_TRUE(model1->container_nodes(i).keys().contains(node->key));
CollectionItem *node2 = model2->container_nodes(i)[node->key];
ASSERT_EQ(node->key, node2->key);
ASSERT_EQ(node->display_text, node2->display_text);
ASSERT_EQ(node->sort_text, node2->sort_text);
}
for (CollectionItem *node : model3->container_nodes(i).values()) {
ASSERT_TRUE(model2->container_nodes(i).keys().contains(node->key));
CollectionItem *node2 = model2->container_nodes(i)[node->key];
ASSERT_EQ(node->key, node2->key);
ASSERT_EQ(node->display_text, node2->display_text);
ASSERT_EQ(node->sort_text, node2->sort_text);
}
}
2021-01-26 16:48:04 +01:00
QSignalSpy database_reset_1(backend1.get(), &CollectionBackend::DatabaseReset);
QSignalSpy database_reset_2(backend2.get(), &CollectionBackend::DatabaseReset);
QSignalSpy database_reset_3(backend3.get(), &CollectionBackend::DatabaseReset);
backend1->DeleteAll();
backend2->DeleteAll();
backend3->DeleteAll();
ASSERT_EQ(database_reset_1.count(), 1);
ASSERT_EQ(database_reset_2.count(), 1);
ASSERT_EQ(database_reset_3.count(), 1);
// Make sure all nodes are deleted.
ASSERT_EQ(model1->container_nodes(0).count(), 0);
ASSERT_EQ(model1->container_nodes(1).count(), 0);
ASSERT_EQ(model1->container_nodes(2).count(), 0);
ASSERT_EQ(model2->container_nodes(0).count(), 0);
ASSERT_EQ(model2->container_nodes(1).count(), 0);
ASSERT_EQ(model2->container_nodes(2).count(), 0);
ASSERT_EQ(model3->container_nodes(0).count(), 0);
ASSERT_EQ(model3->container_nodes(1).count(), 0);
ASSERT_EQ(model3->container_nodes(2).count(), 0);
ASSERT_EQ(model1->song_nodes().count(), 0);
ASSERT_EQ(model2->song_nodes().count(), 0);
ASSERT_EQ(model3->song_nodes().count(), 0);
ASSERT_EQ(model1->divider_nodes_count(), 0);
ASSERT_EQ(model2->divider_nodes_count(), 0);
ASSERT_EQ(model3->divider_nodes_count(), 0);
backend1->Close();
backend2->Close();
backend3->Close();
}
}
}
}
2020-10-19 22:32:50 +02:00
#endif
2019-06-28 01:33:22 +02:00
} // namespace