Add tests (#193)
This commit is contained in:
parent
b9f4407815
commit
60bd90848b
|
@ -395,6 +395,7 @@ endif()
|
|||
# Subdirectories
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(dist)
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(ext/libstrawberry-common)
|
||||
add_subdirectory(ext/libstrawberry-tagreader)
|
||||
add_subdirectory(ext/strawberry-tagreader)
|
||||
|
|
|
@ -106,7 +106,8 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
|
|||
cover_loader_options_.pad_output_image_ = true;
|
||||
cover_loader_options_.scale_output_image_ = true;
|
||||
|
||||
connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QImage)), SLOT(AlbumArtLoaded(quint64, QImage)));
|
||||
if (app_)
|
||||
connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QImage)), SLOT(AlbumArtLoaded(quint64, QImage)));
|
||||
|
||||
//icon_cache_->setCacheDirectory(Utilities::GetConfigPath(Utilities::Path_CacheRoot) + "/pixmapcache");
|
||||
//icon_cache_->setMaximumCacheSize(CollectionModel::kIconCacheSize);
|
||||
|
@ -172,7 +173,8 @@ void CollectionModel::Init(bool async) {
|
|||
endResetModel();
|
||||
|
||||
// Show a loading indicator in the status bar too.
|
||||
init_task_id_ = app_->task_manager()->StartTask(tr("Loading songs"));
|
||||
if (app_)
|
||||
init_task_id_ = app_->task_manager()->StartTask(tr("Loading songs"));
|
||||
|
||||
ResetAsync();
|
||||
}
|
||||
|
@ -794,7 +796,8 @@ void CollectionModel::ResetAsyncQueryFinished(QFuture<CollectionModel::QueryResu
|
|||
PostQuery(root_, result, false);
|
||||
|
||||
if (init_task_id_ != -1) {
|
||||
app_->task_manager()->SetTaskFinished(init_task_id_);
|
||||
if (app_)
|
||||
app_->task_manager()->SetTaskFinished(init_task_id_);
|
||||
init_task_id_ = -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,8 @@
|
|||
using std::shared_ptr;
|
||||
using std::stable_sort;
|
||||
|
||||
const char *OrganiseDialog::kDefaultFormat = "%albumartist/%album{ (Disc %disc)}/{%track - }%albumartist - %album - %title.%extension";
|
||||
const char *OrganiseDialog::kDefaultFormat = "%albumartist/%album{ (Disc %disc)}/{%track - }{%albumartist - }%album{ (Disc %disc)} - %title.%extension";
|
||||
|
||||
const char *OrganiseDialog::kSettingsGroup = "OrganiseDialog";
|
||||
|
||||
OrganiseDialog::OrganiseDialog(TaskManager *task_manager, CollectionBackend *backend, QWidget *parent)
|
||||
|
|
|
@ -59,6 +59,8 @@ class OrganiseDialog : public QDialog {
|
|||
OrganiseDialog(TaskManager *task_manager, CollectionBackend *backend = nullptr, QWidget *parent = nullptr);
|
||||
~OrganiseDialog();
|
||||
|
||||
static const char *kDefaultFormat;
|
||||
|
||||
QSize sizeHint() const;
|
||||
|
||||
void SetDestinationModel(QAbstractItemModel *model, bool devices = false);
|
||||
|
@ -71,6 +73,8 @@ class OrganiseDialog : public QDialog {
|
|||
|
||||
void SetCopy(bool copy);
|
||||
|
||||
static Organise::NewSongInfoList ComputeNewSongsFilenames(const SongList &songs, const OrganiseFormat &format);
|
||||
|
||||
signals:
|
||||
void FileCopied(int);
|
||||
|
||||
|
@ -97,10 +101,7 @@ class OrganiseDialog : public QDialog {
|
|||
SongList LoadSongsBlocking(const QStringList &filenames);
|
||||
void SetLoadingSongs(bool loading);
|
||||
|
||||
static Organise::NewSongInfoList ComputeNewSongsFilenames(const SongList &songs, const OrganiseFormat &format);
|
||||
|
||||
private:
|
||||
static const char *kDefaultFormat;
|
||||
static const char *kSettingsGroup;
|
||||
|
||||
Ui_OrganiseDialog *ui_;
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
cmake_minimum_required(VERSION 2.8.11)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -fpermissive -Wno-c++11-narrowing -U__STRICT_ANSI__")
|
||||
|
||||
find_package(Qt5 ${QT_MIN_VERSION} COMPONENTS Test)
|
||||
find_package(GTest)
|
||||
find_library(GMOCK_LIBRARY gmock)
|
||||
|
||||
if(Qt5Test_FOUND AND GTEST_FOUND AND GMOCK_LIBRARY)
|
||||
|
||||
include_directories(${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS} ${QT_QTTEST_INCLUDE_DIR})
|
||||
include_directories(${TAGLIB_INCLUDE_DIRS})
|
||||
if(HAVE_GSTREAMER)
|
||||
link_directories(${GSTREAMER_LIBRARY_DIRS})
|
||||
include_directories(${GSTREAMER_INCLUDE_DIRS})
|
||||
include_directories(${GSTREAMER_APP_INCLUDE_DIRS})
|
||||
include_directories(${GSTREAMER_AUDIO_INCLUDE_DIRS})
|
||||
include_directories(${GSTREAMER_BASE_INCLUDE_DIRS})
|
||||
include_directories(${GSTREAMER_TAG_INCLUDE_DIRS})
|
||||
endif()
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src)
|
||||
include_directories(${CMAKE_BINARY_DIR}/src)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/tests/src)
|
||||
include_directories(${CMAKE_BINARY_DIR}/tests/src)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/ext/strawberry-tagreader)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-common)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-tagreader)
|
||||
include_directories(${CMAKE_BINARY_DIR}/ext/libstrawberry-tagreader)
|
||||
if(HAVE_LIBGPOD)
|
||||
include_directories(${LIBGPOD_INCLUDE_DIRS})
|
||||
endif(HAVE_LIBGPOD)
|
||||
|
||||
add_definitions(-DGTEST_USE_OWN_TR1_TUPLE=1)
|
||||
|
||||
set(TESTUTILS-SOURCES
|
||||
src/mock_networkaccessmanager.cpp
|
||||
src/mock_playlistitem.cpp
|
||||
src/test_utils.cpp
|
||||
src/testobjectdecorators.cpp
|
||||
)
|
||||
|
||||
set(TESTUTILS-MOC-HEADERS src/mock_networkaccessmanager.h src/test_utils.h src/testobjectdecorators.h)
|
||||
|
||||
qt5_wrap_cpp(TESTUTILS-SOURCES-MOC ${TESTUTILS-MOC-HEADERS})
|
||||
|
||||
add_library(test_utils STATIC EXCLUDE_FROM_ALL ${TESTUTILS-SOURCES} ${TESTUTILS-SOURCES-MOC})
|
||||
target_link_libraries(test_utils ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${QT_LIBRARIES} ${Qt5Test_LIBRARIES})
|
||||
|
||||
add_custom_target(strawberry_test echo "Running Strawberry tests" WORKING_DIRECTORY ${CURRENT_BINARY_DIR})
|
||||
add_custom_target(build_tests WORKING_DIRECTORY ${CURRENT_BINARY_DIR})
|
||||
add_dependencies(strawberry_test build_tests)
|
||||
|
||||
qt5_add_resources(TEST-RESOURCE-SOURCES data/testdata.qrc)
|
||||
|
||||
add_library(test_gui_main STATIC EXCLUDE_FROM_ALL ${TEST-RESOURCE-SOURCES} src/main.cpp)
|
||||
target_link_libraries(test_gui_main strawberry_lib)
|
||||
set_target_properties(test_gui_main PROPERTIES COMPILE_DEFINITIONS GUI)
|
||||
|
||||
add_library(test_main STATIC EXCLUDE_FROM_ALL ${TEST-RESOURCE-SOURCES} src/main.cpp)
|
||||
target_link_libraries(test_main strawberry_lib)
|
||||
|
||||
# Given a file foo_test.cpp, creates a target foo_test and adds it to the test target.
|
||||
macro(add_test_file test_source gui_required)
|
||||
get_filename_component(TEST_NAME ${test_source} NAME_WE)
|
||||
add_executable(${TEST_NAME}
|
||||
EXCLUDE_FROM_ALL
|
||||
${test_source}
|
||||
)
|
||||
target_link_libraries(${TEST_NAME} ${GMOCK_LIBRARY} strawberry_lib test_utils Qt5::Test)
|
||||
set(GUI_REQUIRED ${gui_required})
|
||||
if (GUI_REQUIRED)
|
||||
target_link_libraries(${TEST_NAME} test_gui_main)
|
||||
else (GUI_REQUIRED)
|
||||
target_link_libraries(${TEST_NAME} test_main)
|
||||
endif (GUI_REQUIRED)
|
||||
|
||||
check_cxx_compiler_flag("-Wno-bool-conversions" SUPPORTS_NOBOOL)
|
||||
if (SUPPORTS_NOBOOL)
|
||||
set_target_properties(${TEST_NAME} PROPERTIES COMPILE_FLAGS "-Wno-bool-conversions")
|
||||
endif (SUPPORTS_NOBOOL)
|
||||
|
||||
add_custom_command(TARGET strawberry_test POST_BUILD
|
||||
COMMAND ./${TEST_NAME}${CMAKE_EXECUTABLE_SUFFIX})
|
||||
add_dependencies(build_tests ${TEST_NAME})
|
||||
endmacro (add_test_file)
|
||||
|
||||
add_test_file(src/utilities_test.cpp false)
|
||||
add_test_file(src/concurrentrun_test.cpp false)
|
||||
add_test_file(src/closure_test.cpp false)
|
||||
add_test_file(src/mergedproxymodel_test.cpp false)
|
||||
add_test_file(src/sqlite_test.cpp false)
|
||||
add_test_file(src/song_test.cpp false)
|
||||
add_test_file(src/collectionbackend_test.cpp false)
|
||||
add_test_file(src/collectionmodel_test.cpp true)
|
||||
add_test_file(src/playlist_test.cpp true)
|
||||
add_test_file(src/songplaylistitem_test.cpp false)
|
||||
add_test_file(src/organiseformat_test.cpp false)
|
||||
|
||||
endif() # Qt5Test_FOUND AND GTEST_FOUND AND GMOCK_LIBRARY
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,15 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>audio/strawberry.wav</file>
|
||||
<file>audio/strawberry.flac</file>
|
||||
<file>audio/strawberry.wv</file>
|
||||
<file>audio/strawberry.oga</file>
|
||||
<file>audio/strawberry.opus</file>
|
||||
<file>audio/strawberry.spx</file>
|
||||
<file>audio/strawberry.aif</file>
|
||||
<file>audio/strawberry.asf</file>
|
||||
<file>audio/strawberry.mp3</file>
|
||||
<file>audio/strawberry.m4a</file>
|
||||
<file>audio/strawberry.mp4</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,148 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QSharedPointer>
|
||||
#include <QSignalSpy>
|
||||
|
||||
#include "core/closure.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
TEST(ClosureTest, ClosureInvokesReceiver) {
|
||||
|
||||
TestQObject sender;
|
||||
TestQObject receiver;
|
||||
_detail::ClosureBase* closure = NewClosure(&sender, SIGNAL(Emitted()), &receiver, SLOT(Invoke()));
|
||||
EXPECT_EQ(0, receiver.invoked());
|
||||
sender.Emit();
|
||||
EXPECT_EQ(1, receiver.invoked());
|
||||
|
||||
}
|
||||
|
||||
TEST(ClosureTest, ClosureDeletesSelf) {
|
||||
|
||||
TestQObject sender;
|
||||
TestQObject receiver;
|
||||
_detail::ClosureBase* closure = NewClosure(&sender, SIGNAL(Emitted()), &receiver, SLOT(Invoke()));
|
||||
_detail::ObjectHelper* helper = closure->helper();
|
||||
QSignalSpy spy(helper, SIGNAL(destroyed()));
|
||||
EXPECT_EQ(0, receiver.invoked());
|
||||
sender.Emit();
|
||||
EXPECT_EQ(1, receiver.invoked());
|
||||
|
||||
EXPECT_EQ(0, spy.count());
|
||||
QEventLoop loop;
|
||||
QObject::connect(helper, SIGNAL(destroyed()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(1, spy.count());
|
||||
|
||||
}
|
||||
|
||||
TEST(ClosureTest, ClosureDoesNotCrashWithSharedPointerSender) {
|
||||
|
||||
TestQObject receiver;
|
||||
TestQObject* sender;
|
||||
std::unique_ptr<QSignalSpy> spy;
|
||||
QPointer<_detail::ObjectHelper> closure;
|
||||
{
|
||||
QSharedPointer<TestQObject> sender_shared(new TestQObject);
|
||||
sender = sender_shared.data();
|
||||
closure = QPointer<_detail::ObjectHelper>(NewClosure(sender_shared, SIGNAL(Emitted()), &receiver, SLOT(Invoke()))->helper());
|
||||
spy.reset(new QSignalSpy(sender, SIGNAL(destroyed())));
|
||||
}
|
||||
ASSERT_EQ(0, receiver.invoked());
|
||||
sender->Emit();
|
||||
ASSERT_EQ(1, receiver.invoked());
|
||||
|
||||
ASSERT_EQ(0, spy->count());
|
||||
QEventLoop loop;
|
||||
QObject::connect(sender, SIGNAL(destroyed()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
ASSERT_EQ(1, spy->count());
|
||||
EXPECT_TRUE(closure.isNull());
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void Foo(bool* called, int question, int* answer) {
|
||||
|
||||
*called = true;
|
||||
*answer = question;
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(ClosureTest, ClosureWorksWithFunctionPointers) {
|
||||
|
||||
TestQObject sender;
|
||||
bool called = false;
|
||||
int question = 42;
|
||||
int answer = 0;
|
||||
NewClosure(&sender, SIGNAL(Emitted()), &Foo, &called, question, &answer);
|
||||
EXPECT_FALSE(called);
|
||||
sender.Emit();
|
||||
EXPECT_TRUE(called);
|
||||
EXPECT_EQ(question, answer);
|
||||
|
||||
}
|
||||
|
||||
TEST(ClosureTest, ClosureWorksWithStandardFunctions) {
|
||||
|
||||
TestQObject sender;
|
||||
bool called = false;
|
||||
int question = 42;
|
||||
int answer = 0;
|
||||
std::function<void(bool*,int,int*)> callback(&Foo);
|
||||
NewClosure(&sender, SIGNAL(Emitted()), callback, &called, question, &answer);
|
||||
EXPECT_FALSE(called);
|
||||
sender.Emit();
|
||||
EXPECT_TRUE(called);
|
||||
EXPECT_EQ(question, answer);
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class Bar {
|
||||
public:
|
||||
explicit Bar(int a) : foo_(a) {}
|
||||
bool Foo(int* answer) {
|
||||
*answer = foo_;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
int foo_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
TEST(ClosureTest, ClosureWorksWithMemberFunctionPointers) {
|
||||
|
||||
TestQObject sender;
|
||||
Bar receiver(42);
|
||||
int q = 1;
|
||||
NewClosure(&sender, SIGNAL(Emitted()), &receiver, &Bar::Foo, &q);
|
||||
EXPECT_EQ(1, q);
|
||||
sender.Emit();
|
||||
EXPECT_EQ(42, q);
|
||||
|
||||
}
|
||||
|
||||
TEST(ClosureTest, ClosureCallsLambda) {
|
||||
|
||||
TestQObject sender;
|
||||
bool called = false;
|
||||
NewClosure(&sender, SIGNAL(Emitted()), [&called] () { called = true; });
|
||||
EXPECT_FALSE(called);
|
||||
sender.Emit();
|
||||
EXPECT_TRUE(called);
|
||||
|
||||
}
|
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
* 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 <QFileInfo>
|
||||
#include <QSignalSpy>
|
||||
#include <QThread>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "test_utils.h"
|
||||
|
||||
#include "core/song.h"
|
||||
#include "core/database.h"
|
||||
#include "core/logging.h"
|
||||
#include "collection/collectionbackend.h"
|
||||
#include "collection/collection.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class CollectionBackendTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
database_.reset(new MemoryDatabase(nullptr));
|
||||
backend_.reset(new CollectionBackend);
|
||||
backend_->Init(database_.get(), SCollection::kSongsTable, SCollection::kDirsTable, SCollection::kSubdirsTable, SCollection::kFtsTable);
|
||||
}
|
||||
|
||||
Song MakeDummySong(int directory_id) {
|
||||
// Returns a valid song with all the required fields set
|
||||
Song ret;
|
||||
ret.set_directory_id(directory_id);
|
||||
ret.set_url(QUrl::fromLocalFile("foo.flac"));
|
||||
ret.set_mtime(1);
|
||||
ret.set_ctime(1);
|
||||
ret.set_filesize(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<Database> database_;
|
||||
std::unique_ptr<CollectionBackend> backend_;
|
||||
};
|
||||
|
||||
TEST_F(CollectionBackendTest, EmptyDatabase) {
|
||||
|
||||
// Check the database is empty to start with
|
||||
QStringList artists = backend_->GetAllArtists();
|
||||
EXPECT_TRUE(artists.isEmpty());
|
||||
|
||||
CollectionBackend::AlbumList albums = backend_->GetAllAlbums();
|
||||
EXPECT_TRUE(albums.isEmpty());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(CollectionBackendTest, AddDirectory) {
|
||||
|
||||
QSignalSpy spy(backend_.get(), SIGNAL(DirectoryDiscovered(Directory, SubdirectoryList)));
|
||||
|
||||
backend_->AddDirectory("/tmp");
|
||||
|
||||
// Check the signal was emitted correctly
|
||||
ASSERT_EQ(1, spy.count());
|
||||
Directory dir = spy[0][0].value<Directory>();
|
||||
EXPECT_EQ(QFileInfo("/tmp").canonicalFilePath(), dir.path);
|
||||
EXPECT_EQ(1, dir.id);
|
||||
EXPECT_EQ(0, spy[0][1].value<SubdirectoryList>().size());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(CollectionBackendTest, RemoveDirectory) {
|
||||
|
||||
// Add a directory
|
||||
Directory dir;
|
||||
dir.id = 1;
|
||||
dir.path = "/tmp";
|
||||
backend_->AddDirectory(dir.path);
|
||||
|
||||
QSignalSpy spy(backend_.get(), SIGNAL(DirectoryDeleted(Directory)));
|
||||
|
||||
// Remove the directory again
|
||||
backend_->RemoveDirectory(dir);
|
||||
|
||||
// Check the signal was emitted correctly
|
||||
ASSERT_EQ(1, spy.count());
|
||||
dir = spy[0][0].value<Directory>();
|
||||
EXPECT_EQ("/tmp", dir.path);
|
||||
EXPECT_EQ(1, dir.id);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(CollectionBackendTest, AddInvalidSong) {
|
||||
|
||||
// Adding a song without certain fields set should fail
|
||||
backend_->AddDirectory("/tmp");
|
||||
Song s;
|
||||
//s.set_url(QUrl::fromLocalFile("foo.flac"));
|
||||
s.set_directory_id(1);
|
||||
|
||||
QSignalSpy spy(database_.get(), SIGNAL(Error(QString)));
|
||||
|
||||
backend_->AddOrUpdateSongs(SongList() << s);
|
||||
//ASSERT_EQ(1, spy.count()); spy.takeFirst();
|
||||
|
||||
s.set_url(QUrl::fromLocalFile("foo.flac"));
|
||||
backend_->AddOrUpdateSongs(SongList() << s);
|
||||
//ASSERT_EQ(1, spy.count()); spy.takeFirst();
|
||||
|
||||
s.set_filesize(100);
|
||||
backend_->AddOrUpdateSongs(SongList() << s);
|
||||
//ASSERT_EQ(1, spy.count()); spy.takeFirst();
|
||||
|
||||
s.set_mtime(100);
|
||||
backend_->AddOrUpdateSongs(SongList() << s);
|
||||
//ASSERT_EQ(1, spy.count()); spy.takeFirst();
|
||||
|
||||
s.set_ctime(100);
|
||||
backend_->AddOrUpdateSongs(SongList() << s);
|
||||
ASSERT_EQ(0, spy.count());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(CollectionBackendTest, GetAlbumArtNonExistent) {
|
||||
}
|
||||
|
||||
// Test adding a single song to the database, then getting various information back about it.
|
||||
class SingleSong : public CollectionBackendTest {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
CollectionBackendTest::SetUp();
|
||||
|
||||
// Add a directory - this will get ID 1
|
||||
backend_->AddDirectory("/tmp");
|
||||
|
||||
// Make a song in that directory
|
||||
song_ = MakeDummySong(1);
|
||||
song_.set_title("Title");
|
||||
song_.set_artist("Artist");
|
||||
song_.set_album("Album");
|
||||
song_.set_url(QUrl::fromLocalFile("foo.flac"));
|
||||
}
|
||||
|
||||
void AddDummySong() {
|
||||
QSignalSpy added_spy(backend_.get(), SIGNAL(SongsDiscovered(SongList)));
|
||||
QSignalSpy deleted_spy(backend_.get(), SIGNAL(SongsDeleted(SongList)));
|
||||
|
||||
// Add the song
|
||||
backend_->AddOrUpdateSongs(SongList() << song_);
|
||||
|
||||
// Check the correct signals were emitted
|
||||
EXPECT_EQ(0, deleted_spy.count());
|
||||
ASSERT_EQ(1, added_spy.count());
|
||||
|
||||
SongList list = *(reinterpret_cast<SongList*>(added_spy[0][0].data()));
|
||||
ASSERT_EQ(1, list.count());
|
||||
EXPECT_EQ(song_.title(), list[0].title());
|
||||
EXPECT_EQ(song_.artist(), list[0].artist());
|
||||
EXPECT_EQ(song_.album(), list[0].album());
|
||||
EXPECT_EQ(1, list[0].id());
|
||||
EXPECT_EQ(1, list[0].directory_id());
|
||||
}
|
||||
|
||||
Song song_;
|
||||
|
||||
};
|
||||
|
||||
TEST_F(SingleSong, GetSongWithNoAlbum) {
|
||||
|
||||
song_.set_album("");
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
EXPECT_EQ(1, backend_->GetAllArtists().size());
|
||||
CollectionBackend::AlbumList albums = backend_->GetAllAlbums();
|
||||
//EXPECT_EQ(1, albums.size());
|
||||
//EXPECT_EQ("Artist", albums[0].artist);
|
||||
//EXPECT_EQ("", albums[0].album_name);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SingleSong, GetAllArtists) {
|
||||
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
QStringList artists = backend_->GetAllArtists();
|
||||
ASSERT_EQ(1, artists.size());
|
||||
EXPECT_EQ(song_.artist(), artists[0]);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SingleSong, GetAllAlbums) {
|
||||
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
CollectionBackend::AlbumList albums = backend_->GetAllAlbums();
|
||||
ASSERT_EQ(1, albums.size());
|
||||
EXPECT_EQ(song_.album(), albums[0].album_name);
|
||||
EXPECT_EQ(song_.artist(), albums[0].artist);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SingleSong, GetAlbumsByArtist) {
|
||||
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
CollectionBackend::AlbumList albums = backend_->GetAlbumsByArtist("Artist");
|
||||
ASSERT_EQ(1, albums.size());
|
||||
EXPECT_EQ(song_.album(), albums[0].album_name);
|
||||
EXPECT_EQ(song_.artist(), albums[0].artist);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SingleSong, GetAlbumArt) {
|
||||
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
CollectionBackend::Album album = backend_->GetAlbumArt("Artist", "AlbumArtist", "Album");
|
||||
EXPECT_EQ(song_.album(), album.album_name);
|
||||
EXPECT_EQ(song_.artist(), album.artist);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SingleSong, GetSongs) {
|
||||
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
SongList songs = backend_->GetSongs("Artist", "Album");
|
||||
ASSERT_EQ(1, songs.size());
|
||||
EXPECT_EQ(song_.album(), songs[0].album());
|
||||
EXPECT_EQ(song_.artist(), songs[0].artist());
|
||||
EXPECT_EQ(song_.title(), songs[0].title());
|
||||
EXPECT_EQ(1, songs[0].id());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SingleSong, GetSongById) {
|
||||
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
Song song = backend_->GetSongById(1);
|
||||
EXPECT_EQ(song_.album(), song.album());
|
||||
EXPECT_EQ(song_.artist(), song.artist());
|
||||
EXPECT_EQ(song_.title(), song.title());
|
||||
EXPECT_EQ(1, song.id());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SingleSong, FindSongsInDirectory) {
|
||||
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
SongList songs = backend_->FindSongsInDirectory(1);
|
||||
ASSERT_EQ(1, songs.size());
|
||||
EXPECT_EQ(song_.album(), songs[0].album());
|
||||
EXPECT_EQ(song_.artist(), songs[0].artist());
|
||||
EXPECT_EQ(song_.title(), songs[0].title());
|
||||
EXPECT_EQ(1, songs[0].id());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SingleSong, UpdateSong) {
|
||||
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
Song new_song(song_);
|
||||
new_song.set_id(1);
|
||||
new_song.set_title("A different title");
|
||||
|
||||
QSignalSpy deleted_spy(backend_.get(), SIGNAL(SongsDeleted(SongList)));
|
||||
QSignalSpy added_spy(backend_.get(), SIGNAL(SongsDiscovered(SongList)));
|
||||
|
||||
backend_->AddOrUpdateSongs(SongList() << new_song);
|
||||
|
||||
ASSERT_EQ(1, added_spy.size());
|
||||
ASSERT_EQ(1, deleted_spy.size());
|
||||
|
||||
SongList songs_added = *(reinterpret_cast<SongList*>(added_spy[0][0].data()));
|
||||
SongList songs_deleted = *(reinterpret_cast<SongList*>(deleted_spy[0][0].data()));
|
||||
ASSERT_EQ(1, songs_added.size());
|
||||
ASSERT_EQ(1, songs_deleted.size());
|
||||
EXPECT_EQ("Title", songs_deleted[0].title());
|
||||
EXPECT_EQ("A different title", songs_added[0].title());
|
||||
EXPECT_EQ(1, songs_deleted[0].id());
|
||||
EXPECT_EQ(1, songs_added[0].id());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SingleSong, DeleteSongs) {
|
||||
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
Song new_song(song_);
|
||||
new_song.set_id(1);
|
||||
|
||||
QSignalSpy deleted_spy(backend_.get(), SIGNAL(SongsDeleted(SongList)));
|
||||
|
||||
backend_->DeleteSongs(SongList() << new_song);
|
||||
|
||||
ASSERT_EQ(1, deleted_spy.size());
|
||||
|
||||
SongList songs_deleted = *(reinterpret_cast<SongList*>(deleted_spy[0][0].data()));
|
||||
ASSERT_EQ(1, songs_deleted.size());
|
||||
EXPECT_EQ("Title", songs_deleted[0].title());
|
||||
EXPECT_EQ(1, songs_deleted[0].id());
|
||||
|
||||
// Check we can't retreive that song any more
|
||||
Song song = backend_->GetSongById(1);
|
||||
EXPECT_FALSE(song.is_valid());
|
||||
EXPECT_EQ(-1, song.id());
|
||||
|
||||
// And the artist or album shouldn't show up either
|
||||
QStringList artists = backend_->GetAllArtists();
|
||||
EXPECT_EQ(0, artists.size());
|
||||
|
||||
CollectionBackend::AlbumList albums = backend_->GetAllAlbums();
|
||||
EXPECT_EQ(0, albums.size());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SingleSong, MarkSongsUnavailable) {
|
||||
|
||||
AddDummySong(); if (HasFatalFailure()) return;
|
||||
|
||||
Song new_song(song_);
|
||||
new_song.set_id(1);
|
||||
|
||||
QSignalSpy deleted_spy(backend_.get(), SIGNAL(SongsDeleted(SongList)));
|
||||
|
||||
backend_->MarkSongsUnavailable(SongList() << new_song);
|
||||
|
||||
ASSERT_EQ(1, deleted_spy.size());
|
||||
|
||||
SongList songs_deleted = *(reinterpret_cast<SongList*>(deleted_spy[0][0].data()));
|
||||
ASSERT_EQ(1, songs_deleted.size());
|
||||
EXPECT_EQ("Title", songs_deleted[0].title());
|
||||
EXPECT_EQ(1, songs_deleted[0].id());
|
||||
|
||||
// Check the song is marked as deleted.
|
||||
Song song = backend_->GetSongById(1);
|
||||
EXPECT_TRUE(song.is_valid());
|
||||
EXPECT_TRUE(song.is_unavailable());
|
||||
|
||||
// And the artist or album shouldn't show up either
|
||||
QStringList artists = backend_->GetAllArtists();
|
||||
EXPECT_EQ(0, artists.size());
|
||||
|
||||
CollectionBackend::AlbumList albums = backend_->GetAllAlbums();
|
||||
EXPECT_EQ(0, albums.size());
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
* 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 <QString>
|
||||
#include <QUrl>
|
||||
#include <QThread>
|
||||
#include <QSignalSpy>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "test_utils.h"
|
||||
|
||||
#include "core/database.h"
|
||||
#include "collection/collectionmodel.h"
|
||||
#include "collection/collectionbackend.h"
|
||||
#include "collection/collection.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class CollectionModelTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() {
|
||||
database_.reset(new MemoryDatabase(nullptr));
|
||||
backend_.reset(new CollectionBackend);
|
||||
backend_->Init(database_.get(), SCollection::kSongsTable, SCollection::kDirsTable, SCollection::kSubdirsTable, SCollection::kFtsTable);
|
||||
model_.reset(new CollectionModel(backend_.get(), nullptr));
|
||||
|
||||
added_dir_ = false;
|
||||
|
||||
model_sorted_.reset(new QSortFilterProxyModel);
|
||||
model_sorted_->setSourceModel(model_.get());
|
||||
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() == -1) song.set_mtime(1);
|
||||
if (song.ctime() == -1) song.set_ctime(1);
|
||||
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;
|
||||
}
|
||||
|
||||
Song AddSong(const QString& title, const QString& artist, const QString& album, int length) {
|
||||
Song song;
|
||||
song.Init(title, artist, album, length);
|
||||
return AddSong(song);
|
||||
}
|
||||
|
||||
std::shared_ptr<Database> database_;
|
||||
std::unique_ptr<CollectionBackend> backend_;
|
||||
std::unique_ptr<CollectionModel> model_;
|
||||
std::unique_ptr<QSortFilterProxyModel> model_sorted_;
|
||||
|
||||
bool added_dir_;
|
||||
};
|
||||
|
||||
TEST_F(CollectionModelTest, Initialisation) {
|
||||
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);
|
||||
|
||||
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);
|
||||
songs << song;
|
||||
}
|
||||
|
||||
// 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");
|
||||
|
||||
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("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
|
||||
QSignalSpy spy_preremove(model_.get(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
|
||||
QSignalSpy spy_remove(model_.get(), SIGNAL(rowsRemoved(QModelIndex,int,int)));
|
||||
QSignalSpy spy_reset(model_.get(), SIGNAL(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("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
|
||||
QSignalSpy spy_preremove(model_.get(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
|
||||
QSignalSpy spy_remove(model_.get(), SIGNAL(rowsRemoved(QModelIndex,int,int)));
|
||||
QSignalSpy spy_reset(model_.get(), SIGNAL(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("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()));
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -0,0 +1,169 @@
|
|||
#include <functional>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QThreadPool>
|
||||
#include <QEventLoop>
|
||||
#include <QFutureWatcher>
|
||||
|
||||
#include "core/concurrentrun.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
int f() {
|
||||
return 1337;
|
||||
}
|
||||
|
||||
TEST(ConcurrentRunTest, ConcurrentRun0StartAndWait) {
|
||||
|
||||
QThreadPool threadpool;
|
||||
QFuture<int> future = ConcurrentRun::Run<int>(&threadpool, &f);
|
||||
QFutureWatcher<int> watcher;
|
||||
watcher.setFuture(future);
|
||||
QEventLoop loop;
|
||||
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(1337, watcher.result());
|
||||
|
||||
}
|
||||
|
||||
int g(int i) {
|
||||
return ++i;
|
||||
}
|
||||
|
||||
TEST(ConcurrentRunTest, ConcurrentRun1StartAndWait) {
|
||||
|
||||
QThreadPool threadpool;
|
||||
int i = 1336;
|
||||
QFuture<int> future = ConcurrentRun::Run<int, int>(&threadpool, &g, i);
|
||||
QFutureWatcher<int> watcher;
|
||||
watcher.setFuture(future);
|
||||
QEventLoop loop;
|
||||
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(1337, watcher.result());
|
||||
|
||||
}
|
||||
|
||||
int max(int i, int j) {
|
||||
return (i > j ? i : j);
|
||||
}
|
||||
|
||||
TEST(ConcurrentRunTest, ConcurrentRun2StartAndWait) {
|
||||
|
||||
int i = 10;
|
||||
int j = 42;
|
||||
QThreadPool threadpool;
|
||||
QFuture<int> future = ConcurrentRun::Run<int, int, int>(&threadpool, &max, i, j);
|
||||
QFutureWatcher<int> watcher;
|
||||
watcher.setFuture(future);
|
||||
QEventLoop loop;
|
||||
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(42, watcher.result());
|
||||
|
||||
}
|
||||
|
||||
int sum(int a, int b, int c) {
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
TEST(ConcurrentRunTest, ConcurrentRun3StartAndWait) {
|
||||
|
||||
int i = 10;
|
||||
int j = 42;
|
||||
int k = 50;
|
||||
QThreadPool threadpool;
|
||||
QFuture<int> future = ConcurrentRun::Run<int, int, int, int>(&threadpool, &sum, i, j, k);
|
||||
QFutureWatcher<int> watcher;
|
||||
watcher.setFuture(future);
|
||||
QEventLoop loop;
|
||||
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(102, watcher.result());
|
||||
|
||||
}
|
||||
|
||||
void aFunction(int* n) {
|
||||
*n = 1337;
|
||||
}
|
||||
|
||||
void bFunction(int* n, int *m) {
|
||||
aFunction(n);
|
||||
*m = 1338;
|
||||
}
|
||||
|
||||
void cFunction(int* n, int *m, int *o) {
|
||||
bFunction(n, m);
|
||||
*o = 1339;
|
||||
}
|
||||
|
||||
TEST(ConcurrentRunTest, ConcurrentRunVoidFunction1Start) {
|
||||
|
||||
QThreadPool threadpool;
|
||||
|
||||
int n = 10;
|
||||
QFuture<void> future = ConcurrentRun::Run<void, int*>(&threadpool, &aFunction, &n);
|
||||
QFutureWatcher<void> watcher;
|
||||
watcher.setFuture(future);
|
||||
QEventLoop loop;
|
||||
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(1337, n);
|
||||
|
||||
}
|
||||
|
||||
TEST(ConcurrentRunTest, ConcurrentRunVoidFunction2Start) {
|
||||
|
||||
QThreadPool threadpool;
|
||||
|
||||
int n = 10, m = 11;
|
||||
QFuture<void> future = ConcurrentRun::Run<void, int*, int*>(&threadpool, &bFunction, &n, &m);
|
||||
QFutureWatcher<void> watcher;
|
||||
watcher.setFuture(future);
|
||||
QEventLoop loop;
|
||||
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(1337, n);
|
||||
EXPECT_EQ(1338, m);
|
||||
|
||||
}
|
||||
|
||||
TEST(ConcurrentRunTest, ConcurrentRunVoidFunction3Start) {
|
||||
|
||||
QThreadPool threadpool;
|
||||
|
||||
int n = 10, m = 11, o = 12;
|
||||
QFuture<void> future = ConcurrentRun::Run<void, int*, int*, int*>(&threadpool, &cFunction, &n, &m, &o);
|
||||
QFutureWatcher<void> watcher;
|
||||
watcher.setFuture(future);
|
||||
QEventLoop loop;
|
||||
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(1337, n);
|
||||
EXPECT_EQ(1338, m);
|
||||
EXPECT_EQ(1339, o);
|
||||
|
||||
}
|
||||
|
||||
class A {
|
||||
public:
|
||||
void f(int* i) {
|
||||
*i = *i + 1;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(ConcurrentRunTest, ConcurrentRunVoidBindFunctionStart) {
|
||||
|
||||
QThreadPool threadpool;
|
||||
|
||||
A a;
|
||||
int nb = 10;
|
||||
QFuture<void> future = ConcurrentRun::Run<void>(&threadpool, std::bind(&A::f, &a, &nb));
|
||||
QFutureWatcher<void> watcher;
|
||||
watcher.setFuture(future);
|
||||
QEventLoop loop;
|
||||
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
EXPECT_EQ(11, nb);
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOGGING_ENV_H
|
||||
#define LOGGING_ENV_H
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
class LoggingEnvironment : public ::testing::Environment {
|
||||
public:
|
||||
void SetUp() {
|
||||
logging::Init();
|
||||
logging::SetLevels("*:4");
|
||||
}
|
||||
};
|
||||
|
||||
#endif // LOGGING_ENV_H
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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 <gmock/gmock.h>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "logging_env.h"
|
||||
#include "metatypes_env.h"
|
||||
#include "resources_env.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
testing::InitGoogleMock(&argc, argv);
|
||||
|
||||
testing::AddGlobalTestEnvironment(new MetatypesEnvironment);
|
||||
#ifdef GUI
|
||||
QApplication a(argc, argv);
|
||||
#else
|
||||
QCoreApplication a(argc, argv);
|
||||
#endif
|
||||
testing::AddGlobalTestEnvironment(new ResourcesEnvironment);
|
||||
testing::AddGlobalTestEnvironment(new LoggingEnvironment);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
#include "test_utils.h"
|
||||
#include "core/mergedproxymodel.h"
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QSignalSpy>
|
||||
|
||||
class MergedProxyModelTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() {
|
||||
merged_.setSourceModel(&source_);
|
||||
}
|
||||
|
||||
QStandardItemModel source_;
|
||||
MergedProxyModel merged_;
|
||||
|
||||
};
|
||||
|
||||
TEST_F(MergedProxyModelTest, Flat) {
|
||||
|
||||
source_.appendRow(new QStandardItem("one"));
|
||||
source_.appendRow(new QStandardItem("two"));
|
||||
|
||||
ASSERT_EQ(2, merged_.rowCount(QModelIndex()));
|
||||
QModelIndex one_i = merged_.index(0, 0, QModelIndex());
|
||||
QModelIndex two_i = merged_.index(1, 0, QModelIndex());
|
||||
|
||||
EXPECT_EQ("one", one_i.data().toString());
|
||||
EXPECT_EQ("two", two_i.data().toString());
|
||||
EXPECT_FALSE(merged_.parent(one_i).isValid());
|
||||
EXPECT_FALSE(merged_.hasChildren(one_i));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(MergedProxyModelTest, Tree) {
|
||||
|
||||
QStandardItem* one = new QStandardItem("one");
|
||||
QStandardItem* two = new QStandardItem("two");
|
||||
source_.appendRow(one);
|
||||
one->appendRow(two);
|
||||
|
||||
ASSERT_EQ(1, merged_.rowCount(QModelIndex()));
|
||||
QModelIndex one_i = merged_.index(0, 0, QModelIndex());
|
||||
|
||||
ASSERT_EQ(1, merged_.rowCount(one_i));
|
||||
QModelIndex two_i = merged_.index(0, 0, one_i);
|
||||
|
||||
EXPECT_EQ("one", one_i.data().toString());
|
||||
EXPECT_EQ("two", two_i.data().toString());
|
||||
EXPECT_EQ("one", two_i.parent().data().toString());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(MergedProxyModelTest, Merged) {
|
||||
|
||||
source_.appendRow(new QStandardItem("one"));
|
||||
|
||||
QStandardItemModel submodel;
|
||||
submodel.appendRow(new QStandardItem("two"));
|
||||
|
||||
merged_.AddSubModel(source_.index(0, 0, QModelIndex()), &submodel);
|
||||
|
||||
ASSERT_EQ(1, merged_.rowCount(QModelIndex()));
|
||||
QModelIndex one_i = merged_.index(0, 0, QModelIndex());
|
||||
|
||||
EXPECT_EQ("one", merged_.data(one_i).toString());
|
||||
EXPECT_TRUE(merged_.hasChildren(one_i));
|
||||
|
||||
ASSERT_EQ(1, merged_.rowCount(one_i));
|
||||
QModelIndex two_i = merged_.index(0, 0, one_i);
|
||||
|
||||
EXPECT_EQ("two", merged_.data(two_i).toString());
|
||||
EXPECT_EQ(0, merged_.rowCount(two_i));
|
||||
EXPECT_FALSE(merged_.hasChildren(two_i));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(MergedProxyModelTest, SourceInsert) {
|
||||
|
||||
QSignalSpy before_spy(&merged_, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
|
||||
QSignalSpy after_spy(&merged_, SIGNAL(rowsInserted(QModelIndex,int,int)));
|
||||
|
||||
source_.appendRow(new QStandardItem("one"));
|
||||
|
||||
ASSERT_EQ(1, before_spy.count());
|
||||
ASSERT_EQ(1, after_spy.count());
|
||||
EXPECT_FALSE(before_spy[0][0].value<QModelIndex>().isValid());
|
||||
EXPECT_EQ(0, before_spy[0][1].toInt());
|
||||
EXPECT_EQ(0, before_spy[0][2].toInt());
|
||||
EXPECT_FALSE(after_spy[0][0].value<QModelIndex>().isValid());
|
||||
EXPECT_EQ(0, after_spy[0][1].toInt());
|
||||
EXPECT_EQ(0, after_spy[0][2].toInt());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(MergedProxyModelTest, SourceRemove) {
|
||||
|
||||
source_.appendRow(new QStandardItem("one"));
|
||||
|
||||
QSignalSpy before_spy(&merged_, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
|
||||
QSignalSpy after_spy(&merged_, SIGNAL(rowsRemoved(QModelIndex,int,int)));
|
||||
|
||||
source_.removeRow(0, QModelIndex());
|
||||
|
||||
ASSERT_EQ(1, before_spy.count());
|
||||
ASSERT_EQ(1, after_spy.count());
|
||||
EXPECT_FALSE(before_spy[0][0].value<QModelIndex>().isValid());
|
||||
EXPECT_EQ(0, before_spy[0][1].toInt());
|
||||
EXPECT_EQ(0, before_spy[0][2].toInt());
|
||||
EXPECT_FALSE(after_spy[0][0].value<QModelIndex>().isValid());
|
||||
EXPECT_EQ(0, after_spy[0][1].toInt());
|
||||
EXPECT_EQ(0, after_spy[0][2].toInt());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(MergedProxyModelTest, SubInsert) {
|
||||
|
||||
source_.appendRow(new QStandardItem("one"));
|
||||
QStandardItemModel submodel;
|
||||
merged_.AddSubModel(source_.index(0, 0, QModelIndex()), &submodel);
|
||||
|
||||
QSignalSpy before_spy(&merged_, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
|
||||
QSignalSpy after_spy(&merged_, SIGNAL(rowsInserted(QModelIndex,int,int)));
|
||||
|
||||
submodel.appendRow(new QStandardItem("two"));
|
||||
|
||||
ASSERT_EQ(1, before_spy.count());
|
||||
ASSERT_EQ(1, after_spy.count());
|
||||
EXPECT_EQ("one", before_spy[0][0].value<QModelIndex>().data());
|
||||
EXPECT_EQ(0, before_spy[0][1].toInt());
|
||||
EXPECT_EQ(0, before_spy[0][2].toInt());
|
||||
EXPECT_EQ("one", after_spy[0][0].value<QModelIndex>().data());
|
||||
EXPECT_EQ(0, after_spy[0][1].toInt());
|
||||
EXPECT_EQ(0, after_spy[0][2].toInt());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(MergedProxyModelTest, SubRemove) {
|
||||
|
||||
source_.appendRow(new QStandardItem("one"));
|
||||
QStandardItemModel submodel;
|
||||
merged_.AddSubModel(source_.index(0, 0, QModelIndex()), &submodel);
|
||||
|
||||
submodel.appendRow(new QStandardItem("two"));
|
||||
|
||||
QSignalSpy before_spy(&merged_, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
|
||||
QSignalSpy after_spy(&merged_, SIGNAL(rowsRemoved(QModelIndex,int,int)));
|
||||
|
||||
submodel.removeRow(0, QModelIndex());
|
||||
|
||||
ASSERT_EQ(1, before_spy.count());
|
||||
ASSERT_EQ(1, after_spy.count());
|
||||
EXPECT_EQ("one", before_spy[0][0].value<QModelIndex>().data());
|
||||
EXPECT_EQ(0, before_spy[0][1].toInt());
|
||||
EXPECT_EQ(0, before_spy[0][2].toInt());
|
||||
EXPECT_EQ("one", after_spy[0][0].value<QModelIndex>().data());
|
||||
EXPECT_EQ(0, after_spy[0][1].toInt());
|
||||
EXPECT_EQ(0, after_spy[0][2].toInt());
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef METATYPES_ENV_H
|
||||
#define METATYPES_ENV_H
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QModelIndex>
|
||||
|
||||
#include "core/song.h"
|
||||
#include "core/songloader.h"
|
||||
#include "collection/directory.h"
|
||||
|
||||
class MetatypesEnvironment : public ::testing::Environment {
|
||||
public:
|
||||
void SetUp() {
|
||||
qRegisterMetaType<Directory>("Directory");
|
||||
qRegisterMetaType<DirectoryList>("DirectoryList");
|
||||
qRegisterMetaType<Subdirectory>("Subdirectory");
|
||||
qRegisterMetaType<SubdirectoryList>("SubdirectoryList");
|
||||
qRegisterMetaType<SongList>("SongList");
|
||||
qRegisterMetaType<QModelIndex>("QModelIndex");
|
||||
qRegisterMetaType<SongLoader::Result>("SongLoader::Result");
|
||||
}
|
||||
};
|
||||
|
||||
#endif // RESOURCES_ENV_H
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MOCKCOLLECTIONBACKEND_H
|
||||
#define MOCKCOLLECTIONBACKEND_H
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "collection/collectionbackend.h"
|
||||
|
||||
class MockCollectionBackend : public CollectionBackendInterface {
|
||||
public:
|
||||
MOCK_CONST_METHOD0(songs_table, QString());
|
||||
|
||||
// Get a list of directories in the collection. Emits DirectoriesDiscovered.
|
||||
MOCK_METHOD0(LoadDirectoriesAsync, void());
|
||||
|
||||
// Counts the songs in the collection.
|
||||
MOCK_METHOD0(UpdateTotalSongCountAsync, void());
|
||||
MOCK_METHOD0(UpdateTotalAlbumCountAsync, void());
|
||||
MOCK_METHOD0(UpdateTotalArtistCountAsync, void());
|
||||
|
||||
MOCK_METHOD1(FindSongsInDirectory, SongList(int));
|
||||
MOCK_METHOD1(SubdirsInDirectory, SubdirectoryList(int));
|
||||
MOCK_METHOD0(GetAllDirectories, DirectoryList());
|
||||
MOCK_METHOD3(ChangeDirPath, void(int, const QString&, const QString&));
|
||||
|
||||
MOCK_METHOD1(GetAllArtists, QStringList(const QueryOptions&));
|
||||
MOCK_METHOD1(GetAllArtistsWithAlbums, QStringList(const QueryOptions&));
|
||||
MOCK_METHOD3(GetSongs, SongList(const QString&, const QString&, const QueryOptions&));
|
||||
|
||||
MOCK_METHOD2(GetCompilationSongs, SongList(const QString&, const QueryOptions&));
|
||||
|
||||
MOCK_METHOD1(GetAllAlbums, AlbumList(const QueryOptions&));
|
||||
MOCK_METHOD2(GetAlbumsByArtist, AlbumList(const QString&, const QueryOptions&));
|
||||
MOCK_METHOD1(GetCompilationAlbums, AlbumList(const QueryOptions&));
|
||||
|
||||
MOCK_METHOD4(UpdateManualAlbumArtAsync, void(const QString&, const QString&, const QString&, const QString&));
|
||||
MOCK_METHOD3(GetAlbumArt, Album(const QString&, const QString&, const QString&));
|
||||
|
||||
MOCK_METHOD1(GetSongById, Song(int));
|
||||
|
||||
MOCK_METHOD1(GetSongsByUrl, SongList(const QUrl&));
|
||||
MOCK_METHOD2(GetSongByUrl, Song(const QUrl&, qint64));
|
||||
|
||||
MOCK_METHOD1(AddDirectory, void(const QString&));
|
||||
MOCK_METHOD1(RemoveDirectory, void(const Directory&));
|
||||
|
||||
MOCK_METHOD1(ExecQuery, bool(CollectionQuery*));
|
||||
|
||||
MOCK_METHOD2(GetSongsByAlbum, SongList(const QString&, const QueryOptions&));
|
||||
|
||||
};
|
||||
|
||||
#endif // MOCKCOLLECTIONBACKEND_H
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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 "mock_networkaccessmanager.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QMap>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QIODevice>
|
||||
#include <QNetworkRequest>
|
||||
#include <QUrlQuery>
|
||||
#include <QtDebug>
|
||||
|
||||
using std::min;
|
||||
|
||||
using ::testing::MakeMatcher;
|
||||
using ::testing::Matcher;
|
||||
using ::testing::MatcherInterface;
|
||||
using ::testing::MatchResultListener;
|
||||
using ::testing::Return;
|
||||
|
||||
class RequestForUrlMatcher : public MatcherInterface<const QNetworkRequest&> {
|
||||
public:
|
||||
RequestForUrlMatcher(const QString& contains, const QMap<QString, QString>& expected_params)
|
||||
: contains_(contains), expected_params_(expected_params) {}
|
||||
|
||||
virtual ~RequestForUrlMatcher() {}
|
||||
|
||||
virtual bool Matches(const QNetworkRequest& req) const {
|
||||
const QUrl& url = req.url();
|
||||
|
||||
if (!url.toString().contains(contains_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QUrlQuery url_query(url);
|
||||
for (QMap<QString, QString>::const_iterator it = expected_params_.constBegin(); it != expected_params_.constEnd(); ++it) {
|
||||
if (!url_query.hasQueryItem(it.key()) || url_query.queryItemValue(it.key()) != it.value()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool MatchAndExplain(const QNetworkRequest& req, MatchResultListener* listener) const {
|
||||
*listener << "which is " << req.url().toString().toUtf8().constData();
|
||||
return Matches(req);
|
||||
}
|
||||
|
||||
virtual void DescribeTo(::std::ostream* os) const {
|
||||
*os << "matches url";
|
||||
}
|
||||
|
||||
private:
|
||||
QString contains_;
|
||||
QMap<QString, QString> expected_params_;
|
||||
|
||||
};
|
||||
|
||||
inline Matcher<const QNetworkRequest&> RequestForUrl(const QString& contains, const QMap<QString, QString>& params) {
|
||||
return MakeMatcher(new RequestForUrlMatcher(contains, params));
|
||||
}
|
||||
|
||||
MockNetworkReply* MockNetworkAccessManager::ExpectGet(const QString& contains, const QMap<QString, QString>& expected_params, int status, const QByteArray& data) {
|
||||
|
||||
MockNetworkReply* reply = new MockNetworkReply(data);
|
||||
reply->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, status);
|
||||
|
||||
EXPECT_CALL(*this, createRequest(GetOperation, RequestForUrl(contains, expected_params), nullptr)). WillOnce(Return(reply));
|
||||
|
||||
return reply;
|
||||
|
||||
}
|
||||
|
||||
MockNetworkReply::MockNetworkReply()
|
||||
: data_(nullptr) {
|
||||
}
|
||||
|
||||
MockNetworkReply::MockNetworkReply(const QByteArray& data)
|
||||
: data_(data),
|
||||
pos_(0) {
|
||||
}
|
||||
|
||||
void MockNetworkReply::SetData(const QByteArray& data) {
|
||||
data_ = data;
|
||||
pos_ = 0;
|
||||
}
|
||||
|
||||
qint64 MockNetworkReply::readData(char* data, qint64 size) {
|
||||
|
||||
if (data_.size() == pos_) {
|
||||
return -1;
|
||||
}
|
||||
qint64 bytes_to_read = min(data_.size() - pos_, size);
|
||||
memcpy(data, data_.constData() + pos_, bytes_to_read);
|
||||
pos_ += bytes_to_read;
|
||||
return bytes_to_read;
|
||||
|
||||
}
|
||||
|
||||
qint64 MockNetworkReply::writeData(const char* data, qint64) {
|
||||
|
||||
ADD_FAILURE() << "Something tried to write to a QNetworkReply";
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
void MockNetworkReply::Done() {
|
||||
|
||||
setOpenMode(QIODevice::ReadOnly);
|
||||
emit finished();
|
||||
|
||||
}
|
||||
|
||||
void MockNetworkReply::setAttribute(QNetworkRequest::Attribute code, const QVariant& value) {
|
||||
QNetworkReply::setAttribute(code, value);
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MOCK_NETWORKACCESSMANAGER_H
|
||||
#define MOCK_NETWORKACCESSMANAGER_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QMap>
|
||||
#include <QByteArray>
|
||||
#include <QUrl>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include "test_utils.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
// Usage:
|
||||
// Create a MockNetworkAccessManager.
|
||||
// Call ExpectGet() with appropriate expectations and the data you want back.
|
||||
// This will return a MockNetworkReply*. When you are ready for the reply to arrive, call MockNetworkReply::Done().
|
||||
|
||||
class MockNetworkReply : public QNetworkReply {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MockNetworkReply();
|
||||
MockNetworkReply(const QByteArray& data);
|
||||
|
||||
// Use these to set expectations.
|
||||
void SetData(const QByteArray& data);
|
||||
virtual void setAttribute(QNetworkRequest::Attribute code, const QVariant& value);
|
||||
|
||||
// Call this when you are ready for the finished() signal.
|
||||
void Done();
|
||||
|
||||
protected:
|
||||
MOCK_METHOD0(abort, void());
|
||||
virtual qint64 readData(char* data, qint64);
|
||||
virtual qint64 writeData(const char* data, qint64);
|
||||
|
||||
QByteArray data_;
|
||||
qint64 pos_;
|
||||
};
|
||||
|
||||
|
||||
class MockNetworkAccessManager : public QNetworkAccessManager {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MockNetworkReply* ExpectGet(
|
||||
const QString& contains, // A string that should be present in the URL.
|
||||
const QMap<QString, QString>& params, // Required URL parameters.
|
||||
int status, // Returned HTTP status code.
|
||||
const QByteArray& ret_data); // Returned data.
|
||||
protected:
|
||||
MOCK_METHOD3(createRequest, QNetworkReply*(Operation, const QNetworkRequest&, QIODevice*));
|
||||
};
|
||||
|
||||
#endif // MOCK_NETWORKACCESSMANAGER_H
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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 "core/song.h"
|
||||
|
||||
#include "mock_playlistitem.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
|
||||
MockPlaylistItem::MockPlaylistItem() : PlaylistItem(Song::Source_LocalFile) {}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MOCK_PLAYLISTITEM_H
|
||||
#define MOCK_PLAYLISTITEM_H
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <QVariant>
|
||||
#include <QUrl>
|
||||
|
||||
#include "core/song.h"
|
||||
#include "core/settingsprovider.h"
|
||||
#include "collection/sqlrow.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
|
||||
class MockPlaylistItem : public PlaylistItem {
|
||||
|
||||
public:
|
||||
|
||||
MockPlaylistItem();
|
||||
MOCK_CONST_METHOD0(options, Options());
|
||||
MOCK_METHOD1(InitFromQuery, bool(const SqlRow& settings));
|
||||
MOCK_METHOD0(Reload, void());
|
||||
MOCK_CONST_METHOD0(Metadata, Song());
|
||||
MOCK_CONST_METHOD0(Url, QUrl());
|
||||
MOCK_METHOD1(SetTemporaryMetadata, void(const Song& metadata));
|
||||
MOCK_METHOD0(ClearTemporaryMetadata, void());
|
||||
MOCK_METHOD1(DatabaseValue, QVariant(DatabaseColumn));
|
||||
|
||||
};
|
||||
|
||||
#endif // MOCK_PLAYLISTITEM_H
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MOCK_SETTINGSPROVIDER_H
|
||||
#define MOCK_SETTINGSPROVIDER_H
|
||||
|
||||
#include "core/settingsprovider.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
class MockSettingsProvider : public SettingsProvider {
|
||||
public:
|
||||
MOCK_METHOD1(set_group, void(const char* group));
|
||||
MOCK_CONST_METHOD2(value, QVariant(const QString& key, const QVariant& default_value));
|
||||
MOCK_METHOD2(setValue, void(const QString& key, const QVariant& value));
|
||||
MOCK_METHOD1(beginReadArray, int(const QString& prefix));
|
||||
MOCK_METHOD2(beginWriteArray, void(const QString& prefix, int size));
|
||||
MOCK_METHOD1(setArrayIndex, void(int i));
|
||||
MOCK_METHOD0(endArray, void());
|
||||
};
|
||||
|
||||
class DummySettingsProvider : public SettingsProvider {
|
||||
public:
|
||||
DummySettingsProvider() {}
|
||||
|
||||
void set_group(const char *group) {}
|
||||
|
||||
QVariant value(const QString&, const QVariant& = QVariant()) const { return QVariant(); }
|
||||
void setValue(const QString&, const QVariant&) {}
|
||||
int beginReadArray(const QString&) { return 0; }
|
||||
void beginWriteArray(const QString&, int = -1) {}
|
||||
void setArrayIndex(int) {}
|
||||
void endArray() {}
|
||||
|
||||
};
|
||||
|
||||
#endif // MOCK_SETTINGSPROVIDER_H
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* 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 <gtest/gtest.h>
|
||||
#include "test_utils.h"
|
||||
|
||||
#include "organise/organiseformat.h"
|
||||
#include "core/timeconstants.h"
|
||||
#include "core/song.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
class OrganiseFormatTest : public ::testing::Test {
|
||||
protected:
|
||||
OrganiseFormat format_;
|
||||
Song song_;
|
||||
};
|
||||
|
||||
|
||||
TEST_F(OrganiseFormatTest, BasicReplace) {
|
||||
|
||||
song_.set_title("title");
|
||||
song_.set_album("album");
|
||||
song_.set_artist("artist");
|
||||
song_.set_albumartist("albumartist");
|
||||
song_.set_track(321);
|
||||
song_.set_disc(789);
|
||||
song_.set_year(2010);
|
||||
song_.set_originalyear(1995);
|
||||
song_.set_genre("genre");
|
||||
song_.set_composer("composer");
|
||||
song_.set_performer("performer");
|
||||
song_.set_grouping("grouping");
|
||||
song_.set_comment("comment");
|
||||
song_.set_length_nanosec(987 * kNsecPerSec);
|
||||
song_.set_samplerate(654);
|
||||
song_.set_bitdepth(32);
|
||||
song_.set_bitrate(123);
|
||||
|
||||
format_.set_format("%album %albumartist %artist %bitrate %comment %composer %performer %grouping %disc %genre %length %samplerate %bitdepth %title %track %year");
|
||||
|
||||
ASSERT_TRUE(format_.IsValid());
|
||||
EXPECT_EQ("album_albumartist_artist_123_comment_composer_performer_grouping_789_genre_987_654_32_title_321_2010", format_.GetFilenameForSong(song_));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OrganiseFormatTest, Extension) {
|
||||
|
||||
song_.set_url(QUrl("file:///some/path/filename.flac"));
|
||||
|
||||
format_.set_format("%extension");
|
||||
ASSERT_TRUE(format_.IsValid());
|
||||
EXPECT_EQ("flac", format_.GetFilenameForSong(song_));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OrganiseFormatTest, ArtistInitial) {
|
||||
|
||||
song_.set_artist("bob");
|
||||
|
||||
format_.set_format("%artistinitial");
|
||||
ASSERT_TRUE(format_.IsValid());
|
||||
EXPECT_EQ("B", format_.GetFilenameForSong(song_));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OrganiseFormatTest, AlbumArtistInitial) {
|
||||
|
||||
song_.set_albumartist("bob");
|
||||
|
||||
format_.set_format("%artistinitial");
|
||||
ASSERT_TRUE(format_.IsValid());
|
||||
EXPECT_EQ("B", format_.GetFilenameForSong(song_));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OrganiseFormatTest, InvalidTag) {
|
||||
|
||||
format_.set_format("%invalid");
|
||||
EXPECT_FALSE(format_.IsValid());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OrganiseFormatTest, Blocks) {
|
||||
|
||||
format_.set_format("Before{Inside%year}After");
|
||||
ASSERT_TRUE(format_.IsValid());
|
||||
|
||||
song_.set_year(-1);
|
||||
EXPECT_EQ("BeforeAfter", format_.GetFilenameForSong(song_));
|
||||
|
||||
song_.set_year(0);
|
||||
EXPECT_EQ("BeforeAfter", format_.GetFilenameForSong(song_));
|
||||
|
||||
song_.set_year(123);
|
||||
EXPECT_EQ("BeforeInside123After", format_.GetFilenameForSong(song_));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OrganiseFormatTest, ReplaceSpaces) {
|
||||
|
||||
song_.set_title("The Song Title");
|
||||
format_.set_format("The Format String %title");
|
||||
|
||||
format_.set_replace_spaces(false);
|
||||
EXPECT_EQ("The Format String The Song Title", format_.GetFilenameForSong(song_));
|
||||
format_.set_replace_spaces(true);
|
||||
EXPECT_EQ("The_Format_String_The_Song_Title", format_.GetFilenameForSong(song_));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OrganiseFormatTest, ReplaceNonAscii) {
|
||||
|
||||
song_.set_artist(QString::fromUtf8("Röyksopp"));
|
||||
format_.set_format("%artist");
|
||||
|
||||
format_.set_remove_non_ascii(false);
|
||||
EXPECT_EQ(QString::fromUtf8("Röyksopp"), format_.GetFilenameForSong(song_));
|
||||
format_.set_remove_non_ascii(true);
|
||||
EXPECT_EQ("Royksopp", format_.GetFilenameForSong(song_));
|
||||
|
||||
song_.set_artist(QString::fromUtf8("Владимир Высоцкий"));
|
||||
EXPECT_EQ("_________________", format_.GetFilenameForSong(song_));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OrganiseFormatTest, TrackNumberPadding) {
|
||||
|
||||
format_.set_format("%track");
|
||||
|
||||
song_.set_track(9);
|
||||
EXPECT_EQ("09", format_.GetFilenameForSong(song_));
|
||||
|
||||
song_.set_track(99);
|
||||
EXPECT_EQ("99", format_.GetFilenameForSong(song_));
|
||||
|
||||
song_.set_track(999);
|
||||
EXPECT_EQ("999", format_.GetFilenameForSong(song_));
|
||||
|
||||
song_.set_track(0);
|
||||
EXPECT_EQ("", format_.GetFilenameForSong(song_));
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
TEST_F(OrganiseFormatTest, ReplaceSlashes) {
|
||||
|
||||
format_.set_format("%title");
|
||||
song_.set_title("foo/bar\\baz");
|
||||
qLog(Debug) << format_.GetFilenameForSong(song_);
|
||||
EXPECT_EQ("foo_bar_baz", format_.GetFilenameForSong(song_));
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,543 @@
|
|||
/*
|
||||
* 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 "test_utils.h"
|
||||
|
||||
#include "collection/collectionplaylistitem.h"
|
||||
#include "playlist/playlist.h"
|
||||
#include "mock_settingsprovider.h"
|
||||
#include "mock_playlistitem.h"
|
||||
|
||||
#include <QtDebug>
|
||||
#include <QUndoStack>
|
||||
|
||||
using std::shared_ptr;
|
||||
using ::testing::Return;
|
||||
|
||||
namespace {
|
||||
|
||||
class PlaylistTest : public ::testing::Test {
|
||||
protected:
|
||||
PlaylistTest()
|
||||
: playlist_(nullptr, nullptr, nullptr, 1),
|
||||
sequence_(nullptr, new DummySettingsProvider)
|
||||
{
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
playlist_.set_sequence(&sequence_);
|
||||
}
|
||||
|
||||
MockPlaylistItem* MakeMockItem(const QString& title, const QString& artist = QString(), const QString& album = QString(), int length = 123) const {
|
||||
Song metadata;
|
||||
metadata.Init(title, artist, album, length);
|
||||
|
||||
MockPlaylistItem* ret = new MockPlaylistItem;
|
||||
EXPECT_CALL(*ret, Metadata()).WillRepeatedly(Return(metadata));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
shared_ptr<PlaylistItem> MakeMockItemP(const QString& title, const QString& artist = QString(), const QString& album = QString(), int length = 123) const {
|
||||
return shared_ptr<PlaylistItem>(MakeMockItem(title, artist, album, length));
|
||||
}
|
||||
|
||||
Playlist playlist_;
|
||||
PlaylistSequence sequence_;
|
||||
|
||||
};
|
||||
|
||||
TEST_F(PlaylistTest, Basic) {
|
||||
EXPECT_EQ(0, playlist_.rowCount(QModelIndex()));
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, InsertItems) {
|
||||
|
||||
MockPlaylistItem* item = MakeMockItem("Title", "Artist", "Album", 123);
|
||||
shared_ptr<PlaylistItem> item_ptr(item);
|
||||
|
||||
// Insert the item
|
||||
EXPECT_EQ(0, playlist_.rowCount(QModelIndex()));
|
||||
playlist_.InsertItems(PlaylistItemList() << item_ptr, -1);
|
||||
ASSERT_EQ(1, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
// Get the metadata
|
||||
EXPECT_EQ("Title", playlist_.data(playlist_.index(0, Playlist::Column_Title)));
|
||||
EXPECT_EQ("Artist", playlist_.data(playlist_.index(0, Playlist::Column_Artist)));
|
||||
EXPECT_EQ("Album", playlist_.data(playlist_.index(0, Playlist::Column_Album)));
|
||||
EXPECT_EQ(123, playlist_.data(playlist_.index(0, Playlist::Column_Length)));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, Indexes) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
// Start "playing" track 1
|
||||
playlist_.set_current_row(0);
|
||||
EXPECT_EQ(0, playlist_.current_row());
|
||||
EXPECT_EQ("One", playlist_.current_item()->Metadata().title());
|
||||
EXPECT_EQ(-1, playlist_.previous_row());
|
||||
EXPECT_EQ(1, playlist_.next_row());
|
||||
|
||||
// Stop playing
|
||||
EXPECT_EQ(0, playlist_.last_played_row());
|
||||
playlist_.set_current_row(-1);
|
||||
EXPECT_EQ(0, playlist_.last_played_row());
|
||||
EXPECT_EQ(-1, playlist_.current_row());
|
||||
|
||||
// Play track 2
|
||||
playlist_.set_current_row(1);
|
||||
EXPECT_EQ(1, playlist_.current_row());
|
||||
EXPECT_EQ("Two", playlist_.current_item()->Metadata().title());
|
||||
EXPECT_EQ(0, playlist_.previous_row());
|
||||
EXPECT_EQ(2, playlist_.next_row());
|
||||
|
||||
// Play track 3
|
||||
playlist_.set_current_row(2);
|
||||
EXPECT_EQ(2, playlist_.current_row());
|
||||
EXPECT_EQ("Three", playlist_.current_item()->Metadata().title());
|
||||
EXPECT_EQ(1, playlist_.previous_row());
|
||||
EXPECT_EQ(-1, playlist_.next_row());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, RepeatPlaylist) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
playlist_.sequence()->SetRepeatMode(PlaylistSequence::Repeat_Playlist);
|
||||
|
||||
playlist_.set_current_row(0);
|
||||
EXPECT_EQ(1, playlist_.next_row());
|
||||
|
||||
playlist_.set_current_row(1);
|
||||
EXPECT_EQ(2, playlist_.next_row());
|
||||
|
||||
playlist_.set_current_row(2);
|
||||
EXPECT_EQ(0, playlist_.next_row());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, RepeatTrack) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
playlist_.sequence()->SetRepeatMode(PlaylistSequence::Repeat_Track);
|
||||
|
||||
playlist_.set_current_row(0);
|
||||
EXPECT_EQ(0, playlist_.next_row());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, RepeatAlbum) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList()
|
||||
<< MakeMockItemP("One", "Album one")
|
||||
<< MakeMockItemP("Two", "Album two")
|
||||
<< MakeMockItemP("Three", "Album one"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
playlist_.sequence()->SetRepeatMode(PlaylistSequence::Repeat_Album);
|
||||
|
||||
playlist_.set_current_row(0);
|
||||
EXPECT_EQ(2, playlist_.next_row());
|
||||
|
||||
playlist_.set_current_row(2);
|
||||
EXPECT_EQ(0, playlist_.next_row());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, RemoveBeforeCurrent) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList()
|
||||
<< MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
// Remove a row before the currently playing track
|
||||
playlist_.set_current_row(2);
|
||||
EXPECT_EQ(2, playlist_.current_row());
|
||||
playlist_.removeRow(1, QModelIndex());
|
||||
EXPECT_EQ(1, playlist_.current_row());
|
||||
EXPECT_EQ(1, playlist_.last_played_row());
|
||||
EXPECT_EQ(0, playlist_.previous_row());
|
||||
EXPECT_EQ(-1, playlist_.next_row());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, RemoveAfterCurrent) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList()
|
||||
<< MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
// Remove a row after the currently playing track
|
||||
playlist_.set_current_row(0);
|
||||
EXPECT_EQ(0, playlist_.current_row());
|
||||
playlist_.removeRow(1, QModelIndex());
|
||||
EXPECT_EQ(0, playlist_.current_row());
|
||||
EXPECT_EQ(0, playlist_.last_played_row());
|
||||
EXPECT_EQ(-1, playlist_.previous_row());
|
||||
EXPECT_EQ(1, playlist_.next_row());
|
||||
|
||||
playlist_.set_current_row(1);
|
||||
EXPECT_EQ(-1, playlist_.next_row());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, RemoveCurrent) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
// Remove the currently playing track's row
|
||||
playlist_.set_current_row(1);
|
||||
EXPECT_EQ(1, playlist_.current_row());
|
||||
playlist_.removeRow(1, QModelIndex());
|
||||
EXPECT_EQ(-1, playlist_.current_row());
|
||||
EXPECT_EQ(-1, playlist_.last_played_row());
|
||||
EXPECT_EQ(-1, playlist_.previous_row());
|
||||
EXPECT_EQ(0, playlist_.next_row());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, InsertBeforeCurrent) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
playlist_.set_current_row(1);
|
||||
EXPECT_EQ(1, playlist_.current_row());
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("Four"), 0);
|
||||
ASSERT_EQ(4, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
EXPECT_EQ(2, playlist_.current_row());
|
||||
EXPECT_EQ(2, playlist_.last_played_row());
|
||||
EXPECT_EQ(1, playlist_.previous_row());
|
||||
EXPECT_EQ(3, playlist_.next_row());
|
||||
|
||||
EXPECT_EQ("Four", playlist_.data(playlist_.index(0, Playlist::Column_Title)));
|
||||
EXPECT_EQ("One", playlist_.data(playlist_.index(1, Playlist::Column_Title)));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, InsertAfterCurrent) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
playlist_.set_current_row(1);
|
||||
EXPECT_EQ(1, playlist_.current_row());
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("Four"), 2);
|
||||
ASSERT_EQ(4, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
EXPECT_EQ(1, playlist_.current_row());
|
||||
EXPECT_EQ(1, playlist_.last_played_row());
|
||||
EXPECT_EQ(0, playlist_.previous_row());
|
||||
EXPECT_EQ(2, playlist_.next_row());
|
||||
|
||||
EXPECT_EQ("Two", playlist_.data(playlist_.index(1, Playlist::Column_Title)));
|
||||
EXPECT_EQ("Four", playlist_.data(playlist_.index(2, Playlist::Column_Title)));
|
||||
EXPECT_EQ("Three", playlist_.data(playlist_.index(3, Playlist::Column_Title)));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, Clear) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
playlist_.set_current_row(1);
|
||||
EXPECT_EQ(1, playlist_.current_row());
|
||||
playlist_.Clear();
|
||||
|
||||
EXPECT_EQ(0, playlist_.rowCount(QModelIndex()));
|
||||
EXPECT_EQ(-1, playlist_.current_row());
|
||||
EXPECT_EQ(-1, playlist_.last_played_row());
|
||||
EXPECT_EQ(-1, playlist_.previous_row());
|
||||
EXPECT_EQ(-1, playlist_.next_row());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, UndoAdd) {
|
||||
|
||||
EXPECT_FALSE(playlist_.undo_stack()->canUndo());
|
||||
EXPECT_FALSE(playlist_.undo_stack()->canRedo());
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("Title"));
|
||||
EXPECT_EQ(1, playlist_.rowCount(QModelIndex()));
|
||||
EXPECT_FALSE(playlist_.undo_stack()->canRedo());
|
||||
ASSERT_TRUE(playlist_.undo_stack()->canUndo());
|
||||
|
||||
playlist_.undo_stack()->undo();
|
||||
EXPECT_EQ(0, playlist_.rowCount(QModelIndex()));
|
||||
EXPECT_FALSE(playlist_.undo_stack()->canUndo());
|
||||
ASSERT_TRUE(playlist_.undo_stack()->canRedo());
|
||||
|
||||
playlist_.undo_stack()->redo();
|
||||
EXPECT_EQ(1, playlist_.rowCount(QModelIndex()));
|
||||
EXPECT_FALSE(playlist_.undo_stack()->canRedo());
|
||||
EXPECT_TRUE(playlist_.undo_stack()->canUndo());
|
||||
|
||||
EXPECT_EQ("Title", playlist_.data(playlist_.index(0, Playlist::Column_Title)));
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, UndoMultiAdd) {
|
||||
|
||||
// Add 1 item
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("One"));
|
||||
|
||||
// Add 2 items
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
|
||||
// Undo adding 2 items
|
||||
ASSERT_TRUE(playlist_.undo_stack()->canUndo());
|
||||
EXPECT_EQ("add 2 songs", playlist_.undo_stack()->undoText());
|
||||
playlist_.undo_stack()->undo();
|
||||
|
||||
// Undo adding 1 item
|
||||
ASSERT_TRUE(playlist_.undo_stack()->canUndo());
|
||||
EXPECT_EQ("add 1 songs", playlist_.undo_stack()->undoText());
|
||||
playlist_.undo_stack()->undo();
|
||||
|
||||
EXPECT_FALSE(playlist_.undo_stack()->canUndo());
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
TEST_F(PlaylistTest, UndoRemove) {
|
||||
|
||||
EXPECT_FALSE(playlist_.undo_stack()->canUndo());
|
||||
EXPECT_FALSE(playlist_.undo_stack()->canRedo());
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("Title"));
|
||||
playlist_.removeRow(0);
|
||||
|
||||
EXPECT_EQ(0, playlist_.rowCount(QModelIndex()));
|
||||
EXPECT_FALSE(playlist_.undo_stack()->canRedo());
|
||||
ASSERT_TRUE(playlist_.undo_stack()->canUndo());
|
||||
|
||||
playlist_.undo_stack()->undo();
|
||||
//EXPECT_EQ(1, playlist_.rowCount(QModelIndex()));
|
||||
//ASSERT_TRUE(playlist_.undo_stack()->canRedo());
|
||||
|
||||
//EXPECT_EQ("Title", playlist_.data(playlist_.index(0, Playlist::Column_Title)));
|
||||
|
||||
//playlist_.undo_stack()->redo();
|
||||
//EXPECT_EQ(0, playlist_.rowCount(QModelIndex()));
|
||||
//EXPECT_FALSE(playlist_.undo_stack()->canRedo());
|
||||
//EXPECT_TRUE(playlist_.undo_stack()->canUndo());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, UndoMultiRemove) {
|
||||
|
||||
// Add 3 items
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
// Remove 1 item
|
||||
playlist_.removeRow(1); // Item "Two"
|
||||
|
||||
// Remove 2 items
|
||||
playlist_.removeRows(0, 2); // "One" and "Three"
|
||||
|
||||
ASSERT_EQ(0, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
// Undo removing all 3 items
|
||||
ASSERT_TRUE(playlist_.undo_stack()->canUndo());
|
||||
EXPECT_EQ("remove 3 songs", playlist_.undo_stack()->undoText());
|
||||
playlist_.undo_stack()->undo();
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(PlaylistTest, UndoClear) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("One") << MakeMockItemP("Two") << MakeMockItemP("Three"));
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
playlist_.Clear();
|
||||
ASSERT_EQ(0, playlist_.rowCount(QModelIndex()));
|
||||
ASSERT_TRUE(playlist_.undo_stack()->canUndo());
|
||||
EXPECT_EQ("remove 3 songs", playlist_.undo_stack()->undoText());
|
||||
playlist_.undo_stack()->undo();
|
||||
|
||||
ASSERT_EQ(3, playlist_.rowCount(QModelIndex()));
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
TEST_F(PlaylistTest, UndoRemoveCurrent) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("Title"));
|
||||
playlist_.set_current_row(0);
|
||||
EXPECT_EQ(0, playlist_.current_row());
|
||||
EXPECT_EQ(0, playlist_.last_played_row());
|
||||
|
||||
playlist_.removeRow(0);
|
||||
EXPECT_EQ(-1, playlist_.current_row());
|
||||
EXPECT_EQ(-1, playlist_.last_played_row());
|
||||
|
||||
playlist_.undo_stack()->undo();
|
||||
EXPECT_EQ(0, playlist_.current_row());
|
||||
EXPECT_EQ(0, playlist_.last_played_row());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, UndoRemoveOldCurrent) {
|
||||
|
||||
playlist_.InsertItems(PlaylistItemList() << MakeMockItemP("Title"));
|
||||
playlist_.set_current_row(0);
|
||||
EXPECT_EQ(0, playlist_.current_row());
|
||||
EXPECT_EQ(0, playlist_.last_played_row());
|
||||
|
||||
playlist_.removeRow(0);
|
||||
EXPECT_EQ(-1, playlist_.current_row());
|
||||
EXPECT_EQ(-1, playlist_.last_played_row());
|
||||
|
||||
playlist_.set_current_row(-1);
|
||||
|
||||
playlist_.undo_stack()->undo();
|
||||
EXPECT_EQ(0, playlist_.current_row());
|
||||
EXPECT_EQ(0, playlist_.last_played_row());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, ShuffleThenNext) {
|
||||
|
||||
// Add 100 items
|
||||
PlaylistItemList items;
|
||||
for (int i=0 ; i<100 ; ++i)
|
||||
items << MakeMockItemP("Item " + QString::number(i));
|
||||
playlist_.InsertItems(items);
|
||||
|
||||
playlist_.set_current_row(0);
|
||||
|
||||
// Shuffle until the current index is not at the end
|
||||
forever {
|
||||
playlist_.Shuffle();
|
||||
if (playlist_.current_row() != items.count()-1)
|
||||
break;
|
||||
}
|
||||
|
||||
int index = playlist_.current_row();
|
||||
EXPECT_EQ("Item 0", playlist_.current_item()->Metadata().title());
|
||||
EXPECT_EQ("Item 0", playlist_.data(playlist_.index(index, Playlist::Column_Title)));
|
||||
EXPECT_EQ(index, playlist_.last_played_row());
|
||||
EXPECT_EQ(index + 1, playlist_.next_row());
|
||||
|
||||
// Shuffle until the current index *is* at the end
|
||||
forever {
|
||||
playlist_.Shuffle();
|
||||
if (playlist_.current_row() == items.count()-1)
|
||||
break;
|
||||
}
|
||||
|
||||
index = playlist_.current_row();
|
||||
EXPECT_EQ("Item 0", playlist_.current_item()->Metadata().title());
|
||||
EXPECT_EQ("Item 0", playlist_.data(playlist_.index(index, Playlist::Column_Title)));
|
||||
EXPECT_EQ(index, playlist_.last_played_row());
|
||||
EXPECT_EQ(-1, playlist_.next_row());
|
||||
EXPECT_EQ(index-1, playlist_.previous_row());
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(PlaylistTest, CollectionIdMapSingle) {
|
||||
|
||||
Song song;
|
||||
song.Init("title", "artist", "album", 123);
|
||||
song.set_id(1);
|
||||
|
||||
PlaylistItemPtr item(new CollectionPlaylistItem(song));
|
||||
playlist_.InsertItems(PlaylistItemList() << item);
|
||||
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(-1).count());
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(0).count());
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(2).count());
|
||||
ASSERT_EQ(1, playlist_.collection_items_by_id(1).count());
|
||||
EXPECT_EQ(song.title(), playlist_.collection_items_by_id(1)[0]->Metadata().title());
|
||||
|
||||
playlist_.Clear();
|
||||
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(1).count());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, CollectionIdMapInvalid) {
|
||||
|
||||
Song invalid;
|
||||
invalid.Init("title", "artist", "album", 123);
|
||||
ASSERT_EQ(-1, invalid.id());
|
||||
|
||||
PlaylistItemPtr item(new CollectionPlaylistItem(invalid));
|
||||
playlist_.InsertItems(PlaylistItemList() << item);
|
||||
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(-1).count());
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(0).count());
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(1).count());
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(2).count());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, CollectionIdMapMulti) {
|
||||
|
||||
Song one;
|
||||
one.Init("title", "artist", "album", 123);
|
||||
one.set_id(1);
|
||||
|
||||
Song two;
|
||||
two.Init("title 2", "artist 2", "album 2", 123);
|
||||
two.set_id(2);
|
||||
|
||||
PlaylistItemPtr item_one(new CollectionPlaylistItem(one));
|
||||
PlaylistItemPtr item_two(new CollectionPlaylistItem(two));
|
||||
PlaylistItemPtr item_three(new CollectionPlaylistItem(one));
|
||||
playlist_.InsertItems(PlaylistItemList() << item_one << item_two << item_three);
|
||||
|
||||
EXPECT_EQ(2, playlist_.collection_items_by_id(1).count());
|
||||
EXPECT_EQ(1, playlist_.collection_items_by_id(2).count());
|
||||
|
||||
playlist_.removeRow(1); // item_two
|
||||
EXPECT_EQ(2, playlist_.collection_items_by_id(1).count());
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(2).count());
|
||||
|
||||
playlist_.removeRow(1); // item_three
|
||||
EXPECT_EQ(1, playlist_.collection_items_by_id(1).count());
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(2).count());
|
||||
|
||||
playlist_.removeRow(0); // item_one
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(1).count());
|
||||
EXPECT_EQ(0, playlist_.collection_items_by_id(2).count());
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RESOURCES_ENV_H
|
||||
#define RESOURCES_ENV_H
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QResource>
|
||||
|
||||
class ResourcesEnvironment : public ::testing::Environment {
|
||||
public:
|
||||
void SetUp() {
|
||||
Q_INIT_RESOURCE(data);
|
||||
Q_INIT_RESOURCE(translations);
|
||||
Q_INIT_RESOURCE(testdata);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // RESOURCES_ENV_H
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* 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 "config.h"
|
||||
|
||||
#include <id3v2tag.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QByteArray>
|
||||
#include <QStringList>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTextCodec>
|
||||
#include <QRegExp>
|
||||
|
||||
#include "core/song.h"
|
||||
|
||||
#include "tagreader.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class SongTest : public ::testing::Test {
|
||||
protected:
|
||||
static void SetUpTestCase() {
|
||||
// Return something from uninteresting mock functions.
|
||||
testing::DefaultValue<TagLib::String>::Set("foobarbaz");
|
||||
}
|
||||
|
||||
static Song ReadSongFromFile(const QString& filename) {
|
||||
TagReader tag_reader;
|
||||
Song song;
|
||||
::pb::tagreader::SongMetadata pb_song;
|
||||
|
||||
// We need to init protobuf object from a Song object, to have default values initialized correctly.
|
||||
song.ToProtobuf(&pb_song);
|
||||
tag_reader.ReadFile(filename, &pb_song);
|
||||
song.InitFromProtobuf(pb_song);
|
||||
return song;
|
||||
}
|
||||
|
||||
static void WriteSongToFile(const Song& song, const QString& filename) {
|
||||
TagReader tag_reader;
|
||||
::pb::tagreader::SongMetadata pb_song;
|
||||
song.ToProtobuf(&pb_song);
|
||||
tag_reader.SaveFile(filename, pb_song);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST_F(SongTest, TestAudioFileTagging) {
|
||||
|
||||
const QStringList files_to_test = QStringList() << ":/audio/strawberry.wav"
|
||||
<< ":/audio/strawberry.flac"
|
||||
<< ":/audio/strawberry.wv"
|
||||
<< ":/audio/strawberry.oga"
|
||||
<< ":/audio/strawberry.opus"
|
||||
<< ":/audio/strawberry.spx"
|
||||
<< ":/audio/strawberry.aif"
|
||||
<< ":/audio/strawberry.m4a"
|
||||
<< ":/audio/strawberry.mp4"
|
||||
<< ":/audio/strawberry.mp3"
|
||||
<< ":/audio/strawberry.asf";
|
||||
|
||||
for (const QString& test_filename : files_to_test) {
|
||||
|
||||
TemporaryResource r(test_filename);
|
||||
Song song = ReadSongFromFile(r.fileName());
|
||||
|
||||
// Compare files
|
||||
QFile orig_file(test_filename);
|
||||
orig_file.open(QIODevice::ReadOnly);
|
||||
EXPECT_TRUE(orig_file.isOpen());
|
||||
QByteArray orig_file_data = orig_file.readAll();
|
||||
|
||||
QFile temp_file(r.fileName());
|
||||
temp_file.open(QIODevice::ReadOnly);
|
||||
EXPECT_TRUE(temp_file.isOpen());
|
||||
QByteArray temp_file_data = temp_file.readAll();
|
||||
|
||||
EXPECT_TRUE(!orig_file_data.isEmpty());
|
||||
EXPECT_TRUE(!temp_file_data.isEmpty());
|
||||
EXPECT_TRUE(orig_file_data == temp_file_data);
|
||||
|
||||
if (test_filename.contains(QRegExp(".*\\.wav$"))) continue;
|
||||
|
||||
// Write tags
|
||||
song.set_title("strawberry title");
|
||||
song.set_artist("strawberry artist");
|
||||
song.set_album("strawberry album");
|
||||
song.set_albumartist("strawberry album artist");
|
||||
song.set_composer("strawberry composer");
|
||||
song.set_performer("strawberry performer");
|
||||
song.set_grouping("strawberry grouping");
|
||||
song.set_genre("strawberry genre");
|
||||
song.set_comment("strawberry comment");
|
||||
song.set_track(12);
|
||||
song.set_disc(1234);
|
||||
song.set_year(2019);
|
||||
WriteSongToFile(song, r.fileName());
|
||||
|
||||
// Read tags
|
||||
Song new_song = ReadSongFromFile(r.fileName());
|
||||
EXPECT_EQ("strawberry title", new_song.title());
|
||||
EXPECT_EQ("strawberry artist", new_song.artist());
|
||||
EXPECT_EQ("strawberry album", new_song.album());
|
||||
if (!test_filename.contains(QRegExp(".*\\.aif$")) && !test_filename.contains(QRegExp(".*\\.asf$"))) {
|
||||
EXPECT_EQ("strawberry album artist", new_song.albumartist());
|
||||
EXPECT_EQ("strawberry composer", new_song.composer());
|
||||
if (!test_filename.contains(QRegExp(".*\\.mp4$")) && !test_filename.contains(QRegExp(".*\\.m4a$"))) {
|
||||
EXPECT_EQ("strawberry performer", new_song.performer());
|
||||
}
|
||||
EXPECT_EQ("strawberry grouping", new_song.grouping());
|
||||
EXPECT_EQ(1234, new_song.disc());
|
||||
}
|
||||
EXPECT_EQ("strawberry genre", new_song.genre());
|
||||
if (!test_filename.contains(QRegExp(".*\\.asf$"))) {
|
||||
EXPECT_EQ("strawberry comment", new_song.comment());
|
||||
}
|
||||
EXPECT_EQ(12, new_song.track());
|
||||
EXPECT_EQ(2019, new_song.year());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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 <QTemporaryFile>
|
||||
#include <QFileInfo>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "test_utils.h"
|
||||
|
||||
#include "playlist/songplaylistitem.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class SongPlaylistItemTest : public ::testing::TestWithParam<const char*> {
|
||||
protected:
|
||||
SongPlaylistItemTest() : temp_file_(GetParam()) {}
|
||||
|
||||
void SetUp() {
|
||||
// SongPlaylistItem::Url() checks if the file exists, so we need a real file
|
||||
temp_file_.open();
|
||||
|
||||
absolute_file_name_ = QFileInfo(temp_file_.fileName()).absoluteFilePath();
|
||||
|
||||
song_.Init("Title", "Artist", "Album", 123);
|
||||
song_.set_url(QUrl::fromLocalFile(absolute_file_name_));
|
||||
|
||||
item_.reset(new SongPlaylistItem(song_));
|
||||
|
||||
if (!absolute_file_name_.startsWith('/'))
|
||||
absolute_file_name_.prepend('/');
|
||||
}
|
||||
|
||||
Song song_;
|
||||
QTemporaryFile temp_file_;
|
||||
QString absolute_file_name_;
|
||||
std::unique_ptr<SongPlaylistItem> item_;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RealFiles, SongPlaylistItemTest, testing::Values(
|
||||
"normalfile.flac",
|
||||
"file with spaces.flac",
|
||||
"file with # hash.flac",
|
||||
"file with ? question.flac"
|
||||
));
|
||||
|
||||
TEST_P(SongPlaylistItemTest, Url) {
|
||||
QUrl expected;
|
||||
expected.setScheme("file");
|
||||
expected.setPath(absolute_file_name_);
|
||||
|
||||
EXPECT_EQ(expected, item_->Url());
|
||||
}
|
||||
|
||||
|
||||
} //namespace
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
TEST(SqliteTest, FTS3SupportEnabled) {
|
||||
|
||||
sqlite3* db = nullptr;
|
||||
int rc = sqlite3_open(":memory:", &db);
|
||||
ASSERT_EQ(0, rc);
|
||||
|
||||
char* errmsg = nullptr;
|
||||
rc = sqlite3_exec(db, "CREATE VIRTUAL TABLE foo USING fts3(content, TEXT)", nullptr, nullptr, &errmsg);
|
||||
ASSERT_EQ(0, rc) << errmsg;
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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 "test_utils.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QIODevice>
|
||||
#include <QDir>
|
||||
#include <QNetworkRequest>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const QString& str) {
|
||||
stream << str.toStdString();
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream& operator <<(std::ostream& stream, const QUrl& url) {
|
||||
stream << url.toString().toStdString();
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream& operator <<(std::ostream& stream, const QNetworkRequest& req) {
|
||||
stream << req.url().toString().toStdString();
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream& operator <<(std::ostream& stream, const QVariant& var) {
|
||||
stream << var.toString().toStdString();
|
||||
return stream;
|
||||
}
|
||||
|
||||
void PrintTo(const ::QString& str, std::ostream& os) {
|
||||
os << str.toStdString();
|
||||
}
|
||||
|
||||
void PrintTo(const ::QVariant& var, std::ostream& os) {
|
||||
os << var.toString().toStdString();
|
||||
}
|
||||
|
||||
void PrintTo(const ::QUrl& url, std::ostream& os) {
|
||||
os << url.toString().toStdString();
|
||||
}
|
||||
|
||||
TemporaryResource::TemporaryResource(const QString& filename) {
|
||||
|
||||
setFileTemplate(QDir::tempPath() + "/strawberry_test-XXXXXX." + filename.section('.', -1, -1));
|
||||
open();
|
||||
|
||||
QFile resource(filename);
|
||||
resource.open(QIODevice::ReadOnly);
|
||||
write(resource.readAll());
|
||||
|
||||
reset();
|
||||
|
||||
}
|
||||
|
||||
TestQObject::TestQObject(QObject* parent)
|
||||
: QObject(parent),
|
||||
invoked_(0) {
|
||||
}
|
||||
|
||||
void TestQObject::Emit() {
|
||||
emit Emitted();
|
||||
}
|
||||
|
||||
void TestQObject::Invoke() {
|
||||
++invoked_;
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TEST_UTILS_H
|
||||
#define TEST_UTILS_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QModelIndex>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
class QNetworkRequest;
|
||||
class QString;
|
||||
class QUrl;
|
||||
class QVariant;
|
||||
|
||||
std::ostream& operator <<(std::ostream& stream, const QString& str);
|
||||
std::ostream& operator <<(std::ostream& stream, const QVariant& var);
|
||||
std::ostream& operator <<(std::ostream& stream, const QUrl& url);
|
||||
std::ostream& operator <<(std::ostream& stream, const QNetworkRequest& req);
|
||||
|
||||
template <typename T>
|
||||
std::ostream& operator <<(std::ostream& stream, const QList<T>& list) {
|
||||
stream << "QList(";
|
||||
foreach (const T& item, list) {
|
||||
stream << item << ",";
|
||||
}
|
||||
stream << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
void PrintTo(const ::QString& str, std::ostream& os);
|
||||
void PrintTo(const ::QVariant& var, std::ostream& os);
|
||||
void PrintTo(const ::QUrl& url, std::ostream& os);
|
||||
|
||||
#define EXPOSE_SIGNAL0(n) \
|
||||
void Emit##n() { emit n(); }
|
||||
#define EXPOSE_SIGNAL1(n, t1) \
|
||||
void Emit##n(const t1& a1) { emit n(a1); }
|
||||
#define EXPOSE_SIGNAL2(n, t1, t2) \
|
||||
void Emit##n(const t1& a1, const t2& a2) { emit n(a1, a2); }
|
||||
|
||||
Q_DECLARE_METATYPE(QModelIndex);
|
||||
|
||||
class TemporaryResource : public QTemporaryFile {
|
||||
public:
|
||||
TemporaryResource(const QString& filename);
|
||||
};
|
||||
|
||||
class TestQObject : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestQObject(QObject* parent = 0);
|
||||
|
||||
void Emit();
|
||||
|
||||
int invoked() const { return invoked_; }
|
||||
|
||||
signals:
|
||||
void Emitted();
|
||||
|
||||
public slots:
|
||||
void Invoke();
|
||||
|
||||
private:
|
||||
int invoked_;
|
||||
};
|
||||
|
||||
#endif // TEST_UTILS_H
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define protected public
|
||||
#include <QProgressBar>
|
||||
#undef protected
|
||||
|
||||
#include "testobjectdecorators.h"
|
||||
|
||||
|
||||
void TestObjectDecorators::initStyleOption(QProgressBar* self, QStyleOptionProgressBar* opt) {
|
||||
self->initStyleOption(opt);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TESTOBJECTDECORATORS_H
|
||||
#define TESTOBJECTDECORATORS_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QProgressBar;
|
||||
class QStyleOptionProgressBar;
|
||||
|
||||
class TestObjectDecorators : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
void initStyleOption(QProgressBar* self, QStyleOptionProgressBar* opt);
|
||||
};
|
||||
|
||||
#endif // TESTOBJECTDECORATORS_H
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* 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 <gtest/gtest.h>
|
||||
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "test_utils.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
TEST(UtilitiesTest, HmacFunctions) {
|
||||
QString key("key");
|
||||
QString data("The quick brown fox jumps over the lazy dog");
|
||||
// Test Hmac Md5
|
||||
QByteArray result_hash_md5 = Utilities::HmacMd5(key.toLocal8Bit(), data.toLocal8Bit()).toHex();
|
||||
bool result_md5 = result_hash_md5 == QString("80070713463e7749b90c2dc24911e275");
|
||||
EXPECT_TRUE(result_md5);
|
||||
// Test Hmac Sha256
|
||||
QByteArray result_hash_sha256 = Utilities::HmacSha256(key.toLocal8Bit(), data.toLocal8Bit()).toHex();
|
||||
bool result_sha256 = result_hash_sha256 == QString("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8");
|
||||
EXPECT_TRUE(result_sha256);
|
||||
}
|
||||
|
||||
TEST(UtilitiesTest, ParseRFC822DateTim) {
|
||||
QDateTime result_DateTime = Utilities::ParseRFC822DateTime(QString("22 Feb 2008 00:16:17 GMT"));
|
||||
EXPECT_TRUE(result_DateTime.isValid());
|
||||
result_DateTime = Utilities::ParseRFC822DateTime(QString("Thu, 13 Dec 2012 13:27:52 +0000"));
|
||||
EXPECT_TRUE(result_DateTime.isValid());
|
||||
result_DateTime = Utilities::ParseRFC822DateTime(QString("Mon, 12 March 2012 20:00:00 +0100"));
|
||||
EXPECT_TRUE(result_DateTime.isValid());
|
||||
}
|
Loading…
Reference in New Issue