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>
2020-09-10 22:13:20 +02:00
# include <QMap>
2019-06-28 01:33:22 +02:00
# include <QString>
# include <QUrl>
# include <QThread>
# include <QSignalSpy>
# include <QSortFilterProxyModel>
# include <QtDebug>
# include "test_utils.h"
2020-09-10 22:13:20 +02:00
# include "core/logging.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"
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 {
2021-07-01 01:42:07 +02:00
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 {
2021-07-01 01:56:35 +02:00
database_ = std : : make_shared < MemoryDatabase > ( nullptr ) ;
backend_ = std : : make_unique < CollectionBackend > ( ) ;
2021-09-19 15:41:36 +02:00
backend_ - > Init ( database_ . get ( ) , nullptr , Song : : Source_Collection , SCollection : : kSongsTable , SCollection : : kFtsTable , SCollection : : kDirsTable , SCollection : : kSubdirsTable ) ;
2021-07-01 01:56:35 +02:00
model_ = std : : make_unique < CollectionModel > ( backend_ . get ( ) , nullptr ) ;
2019-06-28 01:33:22 +02:00
added_dir_ = false ;
2021-07-01 01:56:35 +02:00
model_sorted_ = std : : make_unique < QSortFilterProxyModel > ( ) ;
2019-06-28 01:33:22 +02:00
model_sorted_ - > setSourceModel ( model_ . get ( ) ) ;
model_sorted_ - > setSortRole ( CollectionModel : : Role_SortText ) ;
model_sorted_ - > setDynamicSortFilter ( true ) ;
model_sorted_ - > sort ( 0 ) ;
2020-09-10 22:13:20 +02:00
2019-06-28 01:33:22 +02:00
}
2020-09-10 22:13:20 +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 ) ;
2019-06-28 01:33:22 +02:00
if ( song . url ( ) . isEmpty ( ) ) song . set_url ( QUrl ( " file:///tmp/foo " ) ) ;
if ( song . filesize ( ) = = - 1 ) song . set_filesize ( 1 ) ;
if ( ! added_dir_ ) {
backend_ - > AddDirectory ( " /tmp " ) ;
added_dir_ = true ;
}
backend_ - > AddOrUpdateSongs ( SongList ( ) < < song ) ;
return song ;
}
2020-09-10 22:13:20 +02:00
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 ) ;
}
2021-06-20 19:04:08 +02:00
std : : shared_ptr < Database > database_ ; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
std : : unique_ptr < CollectionBackend > backend_ ; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
std : : unique_ptr < CollectionModel > model_ ; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
std : : unique_ptr < 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 ) {
AddSong ( " Title " , " Artist 1 " , " Album " , 123 ) ;
AddSong ( " Title " , " Artist 2 " , " Album " , 123 ) ;
AddSong ( " Title " , " Foo " , " Album " , 123 ) ;
model_ - > Init ( false ) ;
ASSERT_EQ ( 5 , model_sorted_ - > rowCount ( QModelIndex ( ) ) ) ;
EXPECT_EQ ( " A " , model_sorted_ - > index ( 0 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " Artist 1 " , model_sorted_ - > index ( 1 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " Artist 2 " , model_sorted_ - > index ( 2 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " F " , model_sorted_ - > index ( 3 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " Foo " , model_sorted_ - > index ( 4 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
}
TEST_F ( CollectionModelTest , CompilationAlbums ) {
Song song ;
song . Init ( " Title " , " Artist " , " Album " , 123 ) ;
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 ( ) ) ;
EXPECT_EQ ( " 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 ( ) , " Album " ) ;
EXPECT_TRUE ( model_ - > hasChildren ( album_index ) ) ;
}
TEST_F ( CollectionModelTest , NumericHeaders ) {
AddSong ( " Title " , " 1artist " , " Album " , 123 ) ;
AddSong ( " Title " , " 2artist " , " Album " , 123 ) ;
AddSong ( " Title " , " 0artist " , " Album " , 123 ) ;
AddSong ( " Title " , " zartist " , " Album " , 123 ) ;
model_ - > Init ( false ) ;
ASSERT_EQ ( 6 , model_sorted_ - > rowCount ( QModelIndex ( ) ) ) ;
EXPECT_EQ ( " 0-9 " , model_sorted_ - > index ( 0 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " 0artist " , model_sorted_ - > index ( 1 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " 1artist " , model_sorted_ - > index ( 2 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " 2artist " , model_sorted_ - > index ( 3 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " Z " , model_sorted_ - > index ( 4 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " zartist " , model_sorted_ - > index ( 5 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
}
TEST_F ( CollectionModelTest , MixedCaseHeaders ) {
AddSong ( " Title " , " Artist " , " Album " , 123 ) ;
AddSong ( " Title " , " artist " , " Album " , 123 ) ;
model_ - > Init ( false ) ;
ASSERT_EQ ( 3 , model_sorted_ - > rowCount ( QModelIndex ( ) ) ) ;
EXPECT_EQ ( " A " , model_sorted_ - > index ( 0 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " Artist " , model_sorted_ - > index ( 1 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " artist " , model_sorted_ - > index ( 2 , 0 , QModelIndex ( ) ) . data ( ) . toString ( ) ) ;
}
TEST_F ( CollectionModelTest , UnknownArtists ) {
AddSong ( " Title " , " " , " 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 ( " Unknown " , unknown_index . data ( ) . toString ( ) ) ;
ASSERT_EQ ( 1 , model_ - > rowCount ( unknown_index ) ) ;
EXPECT_EQ ( " Album " , model_ - > index ( 0 , 0 , unknown_index ) . data ( ) . toString ( ) ) ;
}
TEST_F ( CollectionModelTest , UnknownAlbums ) {
AddSong ( " Title " , " Artist " , " " , 123 ) ;
AddSong ( " Title " , " Artist " , " 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 ( " Unknown " , unknown_album_index . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " 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 ( " Title " + n , " Artist " + n , " 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 ) ;
songs [ 3 ] . set_compilation_detected ( true ) ; songs [ 3 ] . set_artist ( " Various Artists " ) ;
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 ) ) ;
EXPECT_EQ ( " Artist 1 - Title 1 " , model_ - > index ( 0 , 0 , album_index ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " Artist 2 - Title 2 " , model_ - > index ( 1 , 0 , album_index ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " Artist 3 - Title 3 " , model_ - > index ( 2 , 0 , album_index ) . data ( ) . toString ( ) ) ;
EXPECT_EQ ( " Title 4 " , model_ - > index ( 3 , 0 , album_index ) . data ( ) . toString ( ) ) ;
}
TEST_F ( CollectionModelTest , RemoveSongsLazyLoaded ) {
Song one = AddSong ( " Title 1 " , " Artist " , " Album " , 123 ) ; one . set_id ( 1 ) ;
Song two = AddSong ( " Title 2 " , " Artist " , " Album " , 123 ) ; two . set_id ( 2 ) ;
AddSong ( " Title 3 " , " Artist " , " 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
2021-01-26 16:48:04 +01:00
QSignalSpy spy_preremove ( model_ . get ( ) , & CollectionModel : : rowsAboutToBeRemoved ) ;
QSignalSpy spy_remove ( model_ . get ( ) , & CollectionModel : : rowsRemoved ) ;
QSignalSpy spy_reset ( model_ . get ( ) , & 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 ) ) ;
EXPECT_EQ ( " Title 3 " , model_ - > index ( 0 , 0 , album_index ) . data ( ) . toString ( ) ) ;
}
TEST_F ( CollectionModelTest , RemoveSongsNotLazyLoaded ) {
Song one = AddSong ( " Title 1 " , " Artist " , " Album " , 123 ) ; one . set_id ( 1 ) ;
Song two = AddSong ( " Title 2 " , " Artist " , " Album " , 123 ) ; two . set_id ( 2 ) ;
model_ - > Init ( false ) ;
// Remove the first two songs
2021-01-26 16:48:04 +01:00
QSignalSpy spy_preremove ( model_ . get ( ) , & CollectionModel : : rowsAboutToBeRemoved ) ;
QSignalSpy spy_remove ( model_ . get ( ) , & CollectionModel : : rowsRemoved ) ;
QSignalSpy spy_reset ( model_ . get ( ) , & 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 ) {
Song one = AddSong ( " Title 1 " , " Artist " , " Album 1 " , 123 ) ; one . set_id ( 1 ) ;
Song two = AddSong ( " Title 2 " , " Artist " , " Album 2 " , 123 ) ; two . set_id ( 2 ) ;
Song three = AddSong ( " Title 3 " , " Artist " , " 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 ( " Album 2 " , album_index . data ( ) . toString ( ) ) ;
ASSERT_EQ ( 1 , model_ - > rowCount ( album_index ) ) ;
EXPECT_EQ ( " Title 3 " , model_ - > index ( 0 , 0 , album_index ) . data ( ) . toString ( ) ) ;
}
TEST_F ( CollectionModelTest , RemoveEmptyArtists ) {
Song one = AddSong ( " Title " , " Artist " , " 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 ( ) ) ) ;
}
2020-09-10 22:13:20 +02:00
// 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
2020-09-10 22:13:20 +02:00
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 ;
}
2021-01-08 22:35:07 +01:00
// 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 ;
}
}
2020-09-10 22:13:20 +02:00
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 < Database > database1 ;
std : : unique_ptr < Database > database2 ;
std : : unique_ptr < Database > database3 ;
std : : unique_ptr < CollectionBackend > backend1 ;
std : : unique_ptr < CollectionBackend > backend2 ;
std : : unique_ptr < CollectionBackend > backend3 ;
std : : unique_ptr < CollectionModel > model1 ;
std : : unique_ptr < CollectionModel > model2 ;
std : : unique_ptr < CollectionModel > model3 ;
2021-07-01 01:56:35 +02:00
database1 = std : : make_unique < MemoryDatabase > ( nullptr ) ;
database2 = std : : make_unique < MemoryDatabase > ( nullptr ) ;
database3 = std : : make_unique < MemoryDatabase > ( nullptr ) ;
backend1 = std : : make_unique < CollectionBackend > ( ) ;
backend2 = std : : make_unique < CollectionBackend > ( ) ;
backend3 = std : : make_unique < CollectionBackend > ( ) ;
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 = std : : make_unique < CollectionModel > ( backend1 . get ( ) , nullptr ) ;
model2 = std : : make_unique < CollectionModel > ( backend2 . get ( ) , nullptr ) ;
model3 = std : : make_unique < CollectionModel > ( backend3 . get ( ) , nullptr ) ;
2020-09-10 22:13:20 +02:00
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 ) ;
2020-09-10 22:13:20 +02:00
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.
2020-09-10 22:13:20 +02:00
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 ) ;
2020-09-10 22:13:20 +02:00
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
2020-09-10 22:13:20 +02:00
2019-06-28 01:33:22 +02:00
} // namespace