mirror of
https://github.com/clementine-player/Clementine
synced 2025-01-27 17:49:19 +01:00
Add test for taglib usage in Song, will be more helpful testing M3U/XSPF parsing.
Dave: I'm sorry.
This commit is contained in:
parent
1bf373b184
commit
4219dfa718
@ -523,7 +523,7 @@ Song Playlist::current_item_metadata() const {
|
||||
}
|
||||
|
||||
void Playlist::UpdateScrobblePoint() {
|
||||
int length = current_item_metadata().length();
|
||||
int length = qMin(current_item_metadata().length(), 240);
|
||||
|
||||
ScrobblePoint point(length / 2);
|
||||
scrobble_point_ = point;
|
||||
|
40
src/song.cpp
40
src/song.cpp
@ -19,6 +19,9 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QVariant>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
using boost::scoped_ptr;
|
||||
|
||||
#include "trackslider.h"
|
||||
#include "enginebase.h"
|
||||
#include "albumcoverloader.h"
|
||||
@ -45,6 +48,8 @@ const char* Song::kUpdateSpec =
|
||||
"ctime = :ctime, filesize = :filesize, sampler = :sampler, "
|
||||
"art_automatic = :art_automatic, art_manual = :art_manual";
|
||||
|
||||
TagLibFileRefFactory Song::kDefaultFactory;
|
||||
|
||||
SongData::SongData()
|
||||
: valid_(false),
|
||||
id_(-1),
|
||||
@ -64,23 +69,34 @@ SongData::SongData()
|
||||
{
|
||||
}
|
||||
|
||||
TagLib::FileRef* TagLibFileRefFactory::GetFileRef(const QString& filename) {
|
||||
return new TagLib::FileRef(QFile::encodeName(filename).constData());
|
||||
}
|
||||
|
||||
Song::Song()
|
||||
: d(new SongData)
|
||||
: d(new SongData),
|
||||
factory_(&kDefaultFactory)
|
||||
{
|
||||
}
|
||||
|
||||
Song::Song(const Song &other)
|
||||
: d(other.d)
|
||||
: d(other.d),
|
||||
factory_(&kDefaultFactory)
|
||||
{
|
||||
}
|
||||
|
||||
Song::Song(FileRefFactory* factory)
|
||||
: d(new SongData),
|
||||
factory_(factory) {
|
||||
}
|
||||
|
||||
void Song::InitFromFile(const QString& filename, int directory_id) {
|
||||
d->filename_ = filename;
|
||||
d->directory_id_ = directory_id;
|
||||
|
||||
TagLib::FileRef fileref(QFile::encodeName(filename).constData());
|
||||
scoped_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
||||
|
||||
if( fileref.isNull() )
|
||||
if(fileref->isNull())
|
||||
return;
|
||||
|
||||
QFileInfo info(filename);
|
||||
@ -88,7 +104,7 @@ void Song::InitFromFile(const QString& filename, int directory_id) {
|
||||
d->mtime_ = info.lastModified().toTime_t();
|
||||
d->ctime_ = info.created().toTime_t();
|
||||
|
||||
TagLib::Tag* tag = fileref.tag();
|
||||
TagLib::Tag* tag = fileref->tag();
|
||||
if (tag) {
|
||||
#define strip(x) TStringToQString( x ).trimmed()
|
||||
d->title_ = strip(tag->title());
|
||||
@ -105,7 +121,7 @@ void Song::InitFromFile(const QString& filename, int directory_id) {
|
||||
|
||||
QString disc;
|
||||
QString compilation;
|
||||
if (TagLib::MPEG::File* file = dynamic_cast<TagLib::MPEG::File*>(fileref.file())) {
|
||||
if (TagLib::MPEG::File* file = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||
if (file->ID3v2Tag()) {
|
||||
if (!file->ID3v2Tag()->frameListMap()["TPOS"].isEmpty())
|
||||
disc = TStringToQString(file->ID3v2Tag()->frameListMap()["TPOS"].front()->toString()).trimmed();
|
||||
@ -123,7 +139,7 @@ void Song::InitFromFile(const QString& filename, int directory_id) {
|
||||
compilation = TStringToQString(file->ID3v2Tag()->frameListMap()["TCMP"].front()->toString()).trimmed();
|
||||
}
|
||||
}
|
||||
else if (TagLib::Ogg::Vorbis::File* file = dynamic_cast<TagLib::Ogg::Vorbis::File*>(fileref.file())) {
|
||||
else if (TagLib::Ogg::Vorbis::File* file = dynamic_cast<TagLib::Ogg::Vorbis::File*>(fileref->file())) {
|
||||
if (file->tag()) {
|
||||
if ( !file->tag()->fieldListMap()["COMPOSER"].isEmpty() )
|
||||
d->composer_ = TStringToQString(file->tag()->fieldListMap()["COMPOSER"].front()).trimmed();
|
||||
@ -138,7 +154,7 @@ void Song::InitFromFile(const QString& filename, int directory_id) {
|
||||
compilation = TStringToQString(file->tag()->fieldListMap()["COMPILATION"].front()).trimmed();
|
||||
}
|
||||
}
|
||||
else if (TagLib::FLAC::File* file = dynamic_cast<TagLib::FLAC::File*>(fileref.file())) {
|
||||
else if (TagLib::FLAC::File* file = dynamic_cast<TagLib::FLAC::File*>(fileref->file())) {
|
||||
if ( file->xiphComment() ) {
|
||||
if (!file->xiphComment()->fieldListMap()["COMPOSER"].isEmpty())
|
||||
d->composer_ = TStringToQString( file->xiphComment()->fieldListMap()["COMPOSER"].front() ).trimmed();
|
||||
@ -172,10 +188,10 @@ void Song::InitFromFile(const QString& filename, int directory_id) {
|
||||
d->compilation_ = (i == 1);
|
||||
}
|
||||
|
||||
if (fileref.audioProperties()) {
|
||||
d->bitrate_ = fileref.audioProperties()->bitrate();
|
||||
d->length_ = fileref.audioProperties()->length();
|
||||
d->samplerate_ = fileref.audioProperties()->sampleRate();
|
||||
if (fileref->audioProperties()) {
|
||||
d->bitrate_ = fileref->audioProperties()->bitrate();
|
||||
d->length_ = fileref->audioProperties()->length();
|
||||
d->samplerate_ = fileref->audioProperties()->sampleRate();
|
||||
}
|
||||
}
|
||||
|
||||
|
19
src/song.h
19
src/song.h
@ -15,6 +15,10 @@ namespace lastfm {
|
||||
class Track;
|
||||
}
|
||||
|
||||
namespace TagLib {
|
||||
class FileRef;
|
||||
}
|
||||
|
||||
struct SongData : public QSharedData {
|
||||
SongData();
|
||||
|
||||
@ -52,10 +56,22 @@ struct SongData : public QSharedData {
|
||||
QImage image_;
|
||||
};
|
||||
|
||||
class FileRefFactory {
|
||||
public:
|
||||
virtual ~FileRefFactory() {}
|
||||
virtual TagLib::FileRef* GetFileRef(const QString& filename) = 0;
|
||||
};
|
||||
|
||||
class TagLibFileRefFactory : public FileRefFactory {
|
||||
public:
|
||||
virtual TagLib::FileRef* GetFileRef(const QString& filename);
|
||||
};
|
||||
|
||||
class Song {
|
||||
public:
|
||||
Song();
|
||||
Song(const Song& other);
|
||||
Song(FileRefFactory* factory);
|
||||
|
||||
static const char* kColumnSpec;
|
||||
static const char* kBindSpec;
|
||||
@ -152,6 +168,9 @@ class Song {
|
||||
|
||||
private:
|
||||
QSharedDataPointer<SongData> d;
|
||||
FileRefFactory* factory_;
|
||||
|
||||
static TagLibFileRefFactory kDefaultFactory;
|
||||
};
|
||||
Q_DECLARE_METATYPE(Song);
|
||||
|
||||
|
@ -30,7 +30,8 @@ target_link_libraries(gmock gtest)
|
||||
|
||||
set(TESTUTILS-SOURCES
|
||||
test_utils.cpp
|
||||
mock_networkaccessmanager.cpp)
|
||||
mock_networkaccessmanager.cpp
|
||||
mock_taglib.cpp)
|
||||
|
||||
set(TESTUTILS-MOC-HEADERS
|
||||
mock_networkaccessmanager.h)
|
||||
|
42
tests/mock_taglib.cpp
Normal file
42
tests/mock_taglib.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "mock_taglib.h"
|
||||
|
||||
#include <QTemporaryFile>
|
||||
|
||||
using ::testing::Return;
|
||||
|
||||
MockFile::MockFile(TagLib::Tag* tag, const QString& filename)
|
||||
: TagLib::File(QFile::encodeName(filename).constData()),
|
||||
tag_(tag) {
|
||||
}
|
||||
|
||||
TagLib::Tag* MockFile::tag() const {
|
||||
return tag_.get();
|
||||
}
|
||||
|
||||
TagLib::AudioProperties* MockFile::audioProperties() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool MockFile::save() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MockFileRefFactory::ExpectCall(const QString& filename,
|
||||
const QString& title,
|
||||
const QString& artist,
|
||||
const QString& album) {
|
||||
MockTag* tag = new MockTag;
|
||||
EXPECT_CALL(*tag, title()).WillRepeatedly(Return(title.toStdString()));
|
||||
EXPECT_CALL(*tag, artist()).WillRepeatedly(Return(artist.toStdString()));
|
||||
EXPECT_CALL(*tag, album()).WillRepeatedly(Return(album.toStdString()));
|
||||
tags_[filename] = tag;
|
||||
}
|
||||
|
||||
TagLib::FileRef* MockFileRefFactory::GetFileRef(const QString& filename) {
|
||||
MockTag* tag = tags_.take(filename);
|
||||
QTemporaryFile temp_file;
|
||||
temp_file.open();
|
||||
MockFile* file = new MockFile(tag, temp_file.fileName());
|
||||
TagLib::FileRef* fileref = new TagLib::FileRef(file);
|
||||
return fileref;
|
||||
}
|
60
tests/mock_taglib.h
Normal file
60
tests/mock_taglib.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef MOCK_TAGLIB_H
|
||||
#define MOCK_TAGLIB_H
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <taglib/fileref.h>
|
||||
#include <taglib/tag.h>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include "song.h"
|
||||
|
||||
class MockTag : public TagLib::Tag {
|
||||
public:
|
||||
MOCK_CONST_METHOD0(title, TagLib::String());
|
||||
MOCK_CONST_METHOD0(artist, TagLib::String());
|
||||
MOCK_CONST_METHOD0(album, TagLib::String());
|
||||
MOCK_CONST_METHOD0(comment, TagLib::String());
|
||||
MOCK_CONST_METHOD0(genre, TagLib::String());
|
||||
MOCK_METHOD1(setTitle, void(const TagLib::String&));
|
||||
MOCK_METHOD1(setArtist, void(const TagLib::String&));
|
||||
MOCK_METHOD1(setAlbum, void(const TagLib::String&));
|
||||
MOCK_METHOD1(setComment, void(const TagLib::String&));
|
||||
MOCK_METHOD1(setGenre, void(const TagLib::String&));
|
||||
|
||||
MOCK_CONST_METHOD0(year, uint());
|
||||
MOCK_CONST_METHOD0(track, uint());
|
||||
MOCK_METHOD1(setYear, void(uint));
|
||||
MOCK_METHOD1(setTrack, void(uint));
|
||||
};
|
||||
|
||||
|
||||
class MockFile : public TagLib::File {
|
||||
public:
|
||||
MockFile(TagLib::Tag* tag, const QString& filename);
|
||||
|
||||
virtual TagLib::Tag* tag() const;
|
||||
|
||||
virtual TagLib::AudioProperties* audioProperties() const;
|
||||
|
||||
virtual bool save();
|
||||
|
||||
protected:
|
||||
boost::scoped_ptr<TagLib::Tag> tag_;
|
||||
};
|
||||
|
||||
class MockFileRefFactory : public FileRefFactory {
|
||||
public:
|
||||
void ExpectCall(const QString& filename,
|
||||
const QString& title,
|
||||
const QString& artist,
|
||||
const QString& album);
|
||||
protected:
|
||||
virtual TagLib::FileRef* GetFileRef(const QString& filename);
|
||||
|
||||
QMap<QString, MockTag*> tags_;
|
||||
};
|
||||
|
||||
#endif // MOCK_TAGLIB_H
|
@ -1,14 +1,22 @@
|
||||
#include "song.h"
|
||||
#include <lastfm/Track>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "test_utils.h"
|
||||
#include "mock_taglib.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class SongTest : public ::testing::Test {
|
||||
|
||||
protected:
|
||||
static void SetUpTestCase() {
|
||||
// Return something from uninteresting mock functions.
|
||||
testing::DefaultValue<TagLib::String>::Set("foobarbaz");
|
||||
}
|
||||
|
||||
MockFileRefFactory mock_factory_;
|
||||
};
|
||||
|
||||
|
||||
@ -27,5 +35,13 @@ TEST_F(SongTest, InitsFromLastFM) {
|
||||
EXPECT_EQ("Bar", song.artist());
|
||||
}
|
||||
|
||||
TEST_F(SongTest, InitsFromFile) {
|
||||
mock_factory_.ExpectCall("foobar.mp3", "Foo", "Bar", "Baz");
|
||||
Song song(&mock_factory_);
|
||||
song.InitFromFile("foobar.mp3", 42);
|
||||
EXPECT_EQ("Foo", song.title());
|
||||
EXPECT_EQ("Bar", song.artist());
|
||||
EXPECT_EQ("Baz", song.album());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Loading…
x
Reference in New Issue
Block a user