/* * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome * Copyright 2019, Jonas Kvinge * * 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 . * */ #include #include #include #include #include #include #include #include #include #include "core/logging.h" #include "core/scoped_ptr.h" #include "core/shared_ptr.h" #include "core/database.h" #include "collection/collectionmodel.h" #include "collection/collectionbackend.h" #include "collection/collection.h" using std::make_unique; using std::make_shared; // clazy:excludeall=non-pod-global-static,returning-void-expression namespace { class CollectionModelTest : public ::testing::Test { public: CollectionModelTest() : added_dir_(false) {} protected: void SetUp() override { database_ = make_shared(nullptr); backend_ = make_shared(); backend_->Init(database_, nullptr, Song::Source::Collection, QLatin1String(SCollection::kSongsTable), QLatin1String(SCollection::kFtsTable), QLatin1String(SCollection::kDirsTable), QLatin1String(SCollection::kSubdirsTable)); model_ = make_unique(backend_, nullptr); added_dir_ = false; model_sorted_ = make_unique(); model_sorted_->setSourceModel(&*model_); model_sorted_->setSortRole(CollectionModel::Role_SortText); model_sorted_->setDynamicSortFilter(true); model_sorted_->sort(0); } 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); if (song.url().isEmpty()) song.set_url(QUrl(QStringLiteral("file:///tmp/foo"))); if (song.filesize() == -1) song.set_filesize(1); if (!added_dir_) { backend_->AddDirectory(QStringLiteral("/tmp")); added_dir_ = true; } backend_->AddOrUpdateSongs(SongList() << song); return song; } 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); song.set_ctime(0); return AddSong(song); } SharedPtr database_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) SharedPtr backend_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) ScopedPtr model_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) ScopedPtr model_sorted_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) bool added_dir_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) }; TEST_F(CollectionModelTest, Initialization) { EXPECT_EQ(0, model_->rowCount(QModelIndex())); } TEST_F(CollectionModelTest, WithInitialArtists) { 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); model_->Init(false); ASSERT_EQ(5, model_sorted_->rowCount(QModelIndex())); 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()); } TEST_F(CollectionModelTest, CompilationAlbums) { Song song; song.Init(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral("Album"), 123); song.set_compilation(true); song.set_mtime(0); song.set_ctime(0); 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()); EXPECT_EQ(QStringLiteral("Various artists"), va_index.data().toString()); EXPECT_TRUE(model_->hasChildren(va_index)); ASSERT_EQ(model_->rowCount(va_index), 1); QModelIndex album_index = model_->index(0, 0, va_index); EXPECT_EQ(model_->data(album_index).toString(), QStringLiteral("Album")); EXPECT_TRUE(model_->hasChildren(album_index)); } TEST_F(CollectionModelTest, NumericHeaders) { 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); model_->Init(false); ASSERT_EQ(6, model_sorted_->rowCount(QModelIndex())); 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()); } TEST_F(CollectionModelTest, MixedCaseHeaders) { AddSong(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral("Album"), 123); AddSong(QStringLiteral("Title"), QStringLiteral("artist"), QStringLiteral("Album"), 123); model_->Init(false); ASSERT_EQ(3, model_sorted_->rowCount(QModelIndex())); 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()); } TEST_F(CollectionModelTest, UnknownArtists) { AddSong(QStringLiteral("Title"), QStringLiteral(""), QStringLiteral("Album"), 123); model_->Init(false); model_->fetchMore(model_->index(0, 0)); ASSERT_EQ(1, model_->rowCount(QModelIndex())); QModelIndex unknown_index = model_->index(0, 0, QModelIndex()); EXPECT_EQ(QStringLiteral("Unknown"), unknown_index.data().toString()); ASSERT_EQ(1, model_->rowCount(unknown_index)); EXPECT_EQ(QStringLiteral("Album"), model_->index(0, 0, unknown_index).data().toString()); } TEST_F(CollectionModelTest, UnknownAlbums) { AddSong(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral(""), 123); AddSong(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral("Album"), 123); 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); EXPECT_EQ(QStringLiteral("Unknown"), unknown_album_index.data().toString()); EXPECT_EQ(QStringLiteral("Album"), real_album_index.data().toString()); } TEST_F(CollectionModelTest, VariousArtistSongs) { SongList songs; for (int i=0 ; i < 4 ; ++i) { QString n = QString::number(i+1); Song song; song.Init(QStringLiteral("Title ") + n, QStringLiteral("Artist ") + n, QStringLiteral("Album"), 0); song.set_mtime(0); song.set_ctime(0); songs << song; // clazy:exclude=reserve-candidates } // 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); songs[3].set_compilation_detected(true); songs[3].set_artist(QStringLiteral("Various Artists")); for (int i=0 ; i < 4 ; ++i) 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)); 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()); } TEST_F(CollectionModelTest, RemoveSongsLazyLoaded) { 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); 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); 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)); EXPECT_EQ(QStringLiteral("Title 3"), model_->index(0, 0, album_index).data().toString()); } TEST_F(CollectionModelTest, RemoveSongsNotLazyLoaded) { 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); 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); 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) { 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); 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); EXPECT_EQ(QStringLiteral("Album 2"), album_index.data().toString()); ASSERT_EQ(1, model_->rowCount(album_index)); EXPECT_EQ(QStringLiteral("Title 3"), model_->index(0, 0, album_index).data().toString()); } TEST_F(CollectionModelTest, RemoveEmptyArtists) { Song one = AddSong(QStringLiteral("Title"), QStringLiteral("Artist"), QStringLiteral("Album"), 123); one.set_id(1); 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. #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) { 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; } // Albums with Album ID. for (int album_id = 0; album_id <= 2 ; ++album_id) { 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 database1; ScopedPtr database2; ScopedPtr database3; ScopedPtr backend1; ScopedPtr backend2; ScopedPtr backend3; ScopedPtr model1; ScopedPtr model2; ScopedPtr model3; database1 = make_unique(nullptr); database2 = make_unique(nullptr); database3 = make_unique(nullptr); backend1 = make_unique(); backend2= make_unique(); backend3 = make_unique(); 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(backend1.get(), nullptr); model2 = make_unique(backend2.get(), nullptr); model3 = make_unique(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(), &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()); // 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); } } 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(); } } } } #endif } // namespace