From 0b7b4c12e4d66db5a53295d4b14400869944eb78 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Thu, 10 Sep 2020 22:13:20 +0200 Subject: [PATCH] Add test for collection model container nodes --- tests/src/collectionmodel_test.cpp | 336 ++++++++++++++++++++++++++++- 1 file changed, 334 insertions(+), 2 deletions(-) diff --git a/tests/src/collectionmodel_test.cpp b/tests/src/collectionmodel_test.cpp index 99ea91aeb..ae75e5c6e 100644 --- a/tests/src/collectionmodel_test.cpp +++ b/tests/src/collectionmodel_test.cpp @@ -23,6 +23,7 @@ #include +#include #include #include #include @@ -32,6 +33,7 @@ #include "test_utils.h" +#include "core/logging.h" #include "core/database.h" #include "collection/collectionmodel.h" #include "collection/collectionbackend.h" @@ -54,9 +56,10 @@ class CollectionModelTest : public ::testing::Test { model_sorted_->setSortRole(CollectionModel::Role_SortText); model_sorted_->setDynamicSortFilter(true); model_sorted_->sort(0); + } - Song AddSong(Song& song) { + Song AddSong(Song &song) { song.set_directory_id(1); if (song.mtime() == 0) song.set_mtime(1); if (song.ctime() == 0) song.set_ctime(1); @@ -72,7 +75,7 @@ class CollectionModelTest : public ::testing::Test { return song; } - Song AddSong(const QString& title, const QString& artist, const QString& album, int length) { + Song AddSong(const QString &title, const QString &artist, const QString &album, const int length) { Song song; song.Init(title, artist, album, length); song.set_mtime(0); @@ -338,4 +341,333 @@ TEST_F(CollectionModelTest, RemoveEmptyArtists) { } +// 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. + +TEST_F(CollectionModelTest, TestContainerNodes) { + + SongList songs; + int year = 1960; + // Add some normal albums. + for (int artist_number = 1; artist_number <= 3 ; ++artist_number) { + 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) { + 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; + 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 + { + 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. + { + 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. + { + 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; + } + + { + 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; + } + + { + 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; + } + + 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; + + std::unique_ptr database1; + std::unique_ptr database2; + std::unique_ptr database3; + std::unique_ptr backend1; + std::unique_ptr backend2; + std::unique_ptr backend3; + std::unique_ptr model1; + std::unique_ptr model2; + std::unique_ptr model3; + + database1.reset(new MemoryDatabase(nullptr)); + database2.reset(new MemoryDatabase(nullptr)); + database3.reset(new MemoryDatabase(nullptr)); + backend1.reset(new CollectionBackend); + backend2.reset(new CollectionBackend); + backend3.reset(new CollectionBackend); + backend1->Init(database1.get(), Song::Source_Collection, SCollection::kSongsTable, SCollection::kDirsTable, SCollection::kSubdirsTable, SCollection::kFtsTable); + backend2->Init(database2.get(), Song::Source_Collection, SCollection::kSongsTable, SCollection::kDirsTable, SCollection::kSubdirsTable, SCollection::kFtsTable); + backend3->Init(database3.get(), Song::Source_Collection, SCollection::kSongsTable, SCollection::kDirsTable, SCollection::kSubdirsTable, SCollection::kFtsTable); + model1.reset(new CollectionModel(backend1.get(), nullptr)); + model2.reset(new CollectionModel(backend2.get(), nullptr)); + model3.reset(new 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); + + QSignalSpy model1_update(model1.get(), SIGNAL(rowsInserted(QModelIndex, int, int))); + QSignalSpy model2_update(model2.get(), SIGNAL(rowsInserted(QModelIndex, int, int))); + QSignalSpy model3_update(model3.get(), SIGNAL(rowsInserted(QModelIndex, int, int))); + + 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()); + + // Container nodes for all models should now be indentical. + 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); + } + } + + QSignalSpy database_reset_1(backend1.get(), SIGNAL(DatabaseReset())); + QSignalSpy database_reset_2(backend2.get(), SIGNAL(DatabaseReset())); + QSignalSpy database_reset_3(backend3.get(), SIGNAL(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(); + + } + } + } + +} + } // namespace