Add test for taglib usage in Song, will be more helpful testing M3U/XSPF parsing.

Dave: I'm sorry.
This commit is contained in:
John Maguire 2010-03-06 20:08:01 +00:00
parent 1bf373b184
commit 4219dfa718
7 changed files with 169 additions and 15 deletions

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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
View 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
View 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

View File

@ -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