mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-18 04:19:55 +01:00
Add mostly done M3UParser with basic unit tests.
Add lots of test infrastructure.
This commit is contained in:
parent
7e500a2fa8
commit
c043eaba0c
@ -53,6 +53,7 @@ set(CLEMENTINE-SOURCES
|
||||
shortcutsdialog.cpp
|
||||
albumcovermanager.cpp
|
||||
albumcoverloader.cpp
|
||||
m3uparser.cpp
|
||||
)
|
||||
|
||||
# Header files that have Q_OBJECT in
|
||||
@ -99,6 +100,7 @@ set(CLEMENTINE-MOC-HEADERS
|
||||
shortcutsdialog.h
|
||||
albumcovermanager.h
|
||||
albumcoverloader.h
|
||||
m3uparser.h
|
||||
)
|
||||
|
||||
# UI files
|
||||
@ -148,6 +150,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/qtsingleapplication")
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/qxt")
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/gtest/include")
|
||||
|
||||
set(EXECUTABLE_OUTPUT_PATH ..)
|
||||
add_library(clementine_lib
|
||||
|
91
src/m3uparser.cpp
Normal file
91
src/m3uparser.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "m3uparser.h"
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
M3UParser::M3UParser(QIODevice* device, QDir directory, QObject* parent)
|
||||
: QObject(parent),
|
||||
device_(device),
|
||||
type_(STANDARD),
|
||||
directory_(directory) {
|
||||
}
|
||||
|
||||
const QList<Song>& M3UParser::Parse() {
|
||||
QString line = QString::fromLatin1(device_->readLine());
|
||||
if (line == "#EXTM3U") {
|
||||
// This is in extended M3U format.
|
||||
type_ = EXTENDED;
|
||||
line = QString::fromLatin1(device_->readLine());
|
||||
}
|
||||
|
||||
do {
|
||||
if (line.startsWith('#')) {
|
||||
// Extended info or comment.
|
||||
if (type_ == EXTENDED && line.startsWith("#EXT")) {
|
||||
if (!ParseMetadata(line, ¤t_metadata_)) {
|
||||
qWarning() << "Failed to parse metadata: " << line;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Track location.
|
||||
QUrl url;
|
||||
if (!ParseTrackLocation(line, &url)) {
|
||||
qWarning() << "Failed to parse location: " << line;
|
||||
}
|
||||
}
|
||||
line = QString::fromLatin1(device_->readLine());
|
||||
} while (device_->canReadLine());
|
||||
|
||||
return songs_;
|
||||
}
|
||||
|
||||
bool M3UParser::ParseMetadata(QString line, M3UParser::Metadata* metadata) const {
|
||||
// Extended info, eg.
|
||||
// #EXTINF:123,Sample Artist - Sample title
|
||||
QString info = line.section(':', 1);
|
||||
QString l = info.section(',', 0, 0);
|
||||
bool ok = false;
|
||||
int length = l.toInt(&ok);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
QString track_info = info.section(',', 1);
|
||||
QStringList list = track_info.split('-');
|
||||
if (list.size() <= 1) {
|
||||
return false;
|
||||
}
|
||||
metadata->artist = list[0].trimmed();
|
||||
metadata->title = list[1].trimmed();
|
||||
metadata->length = length;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool M3UParser::ParseTrackLocation(QString line, QUrl* url) const {
|
||||
if (line.contains(QRegExp("^[a-z]+://"))) {
|
||||
// Looks like a url.
|
||||
QUrl temp(line);
|
||||
if (temp.isValid()) {
|
||||
*url = temp;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Should be a local path.
|
||||
if (line.contains(QRegExp("^([a-zA-Z]:\\)|(/)"))) {
|
||||
// Absolute path.
|
||||
// Fix windows \.
|
||||
QString proper_path = line.replace('\\', '/');
|
||||
if (!proper_path.startsWith('/')) {
|
||||
proper_path.prepend("/");
|
||||
}
|
||||
*url = "file://" + proper_path;
|
||||
return true;
|
||||
} else {
|
||||
// Relative path.
|
||||
QString proper_path = line.replace('\\', '/');
|
||||
QString absolute_path = directory_.absoluteFilePath(proper_path);
|
||||
*url = "file://" + absolute_path;
|
||||
return true;
|
||||
}
|
||||
}
|
49
src/m3uparser.h
Normal file
49
src/m3uparser.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef M3UPARSER_H
|
||||
#define M3UPARSER_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
|
||||
#include "gtest/gtest_prod.h"
|
||||
|
||||
#include "song.h"
|
||||
|
||||
class QIODevice;
|
||||
|
||||
class M3UParser : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
M3UParser(QIODevice* device, QDir directory = QDir(), QObject* parent = 0);
|
||||
virtual ~M3UParser() {}
|
||||
|
||||
const QList<Song>& Parse();
|
||||
|
||||
struct Metadata {
|
||||
QString artist;
|
||||
QString title;
|
||||
int length;
|
||||
};
|
||||
|
||||
private:
|
||||
enum M3UType {
|
||||
STANDARD = 0,
|
||||
EXTENDED, // Includes extended info (track, artist, etc.)
|
||||
LINK // Points to a directory.
|
||||
};
|
||||
|
||||
bool ParseMetadata(QString line, Metadata* metadata) const;
|
||||
bool ParseTrackLocation(QString line, QUrl* url) const;
|
||||
|
||||
FRIEND_TEST(M3UParserTest, ParsesMetadata);
|
||||
FRIEND_TEST(M3UParserTest, ParsesTrackLocation);
|
||||
|
||||
QIODevice* device_;
|
||||
M3UType type_;
|
||||
QDir directory_;
|
||||
Metadata current_metadata_;
|
||||
|
||||
QList<Song> songs_;
|
||||
};
|
||||
|
||||
#endif // M3UPARSER_H
|
@ -12,20 +12,27 @@ set(GTEST-SOURCES
|
||||
../3rdparty/gtest/src/gtest-port.cc
|
||||
../3rdparty/gtest/src/gtest-test-part.cc
|
||||
../3rdparty/gtest/src/gtest-typed-test.cc
|
||||
test_utils.cpp
|
||||
)
|
||||
|
||||
add_library(gtest ${GTEST-SOURCES})
|
||||
|
||||
|
||||
set(SONGTEST-SOURCES
|
||||
../3rdparty/gtest/src/gtest_main.cc
|
||||
../src/song.cpp
|
||||
song_test.cpp)
|
||||
|
||||
add_executable(song_test ${SONGTEST-SOURCES})
|
||||
target_link_libraries(song_test clementine_lib gtest)
|
||||
|
||||
add_custom_target(test
|
||||
./song_test
|
||||
echo "Running tests"
|
||||
WORKING_DIRECTORY ${CURRENT_BINARY_DIR}
|
||||
DEPENDS song_test)
|
||||
DEPENDS song_test m3uparser_test)
|
||||
|
||||
# Given a file foo_test.cpp, creates a target foo_test and adds it to the test target.
|
||||
macro(add_test_file test_source)
|
||||
get_filename_component(TEST_NAME ${ARGV0} NAME_WE)
|
||||
add_executable(${TEST_NAME}
|
||||
${ARGV0}
|
||||
../3rdparty/gtest/src/gtest_main.cc)
|
||||
target_link_libraries(${TEST_NAME} clementine_lib gtest)
|
||||
add_custom_command(TARGET test POST_BUILD
|
||||
COMMAND ./${TEST_NAME})
|
||||
endmacro (add_test_file)
|
||||
|
||||
|
||||
add_test_file(m3uparser_test.cpp)
|
||||
add_test_file(song_test.cpp)
|
||||
|
29
tests/m3uparser_test.cpp
Normal file
29
tests/m3uparser_test.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
#include "m3uparser.h"
|
||||
|
||||
class M3UParserTest : public ::testing::Test {
|
||||
protected:
|
||||
M3UParserTest()
|
||||
: parser_(NULL) {
|
||||
}
|
||||
|
||||
M3UParser parser_;
|
||||
};
|
||||
|
||||
TEST_F(M3UParserTest, ParsesMetadata) {
|
||||
QString line("#EXTINF:123,Foo artist - Foo track");
|
||||
M3UParser::Metadata metadata;
|
||||
ASSERT_TRUE(parser_.ParseMetadata(line, &metadata));
|
||||
EXPECT_EQ("Foo artist", metadata.artist.toStdString());
|
||||
EXPECT_EQ("Foo track", metadata.title.toStdString());
|
||||
EXPECT_EQ(123, metadata.length);
|
||||
}
|
||||
|
||||
TEST_F(M3UParserTest, ParsesTrackLocation) {
|
||||
QString line("/foo/bar.mp3");
|
||||
QUrl url;
|
||||
ASSERT_TRUE(parser_.ParseTrackLocation(line, &url));
|
||||
EXPECT_EQ(QUrl("file:///foo/bar.mp3"), url);
|
||||
}
|
@ -3,10 +3,7 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const QString& str) {
|
||||
stream << str.toStdString();
|
||||
return stream;
|
||||
}
|
||||
#include "test_utils.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
15
tests/test_utils.cpp
Normal file
15
tests/test_utils.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "test_utils.h"
|
||||
|
||||
#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;
|
||||
}
|
||||
|
12
tests/test_utils.h
Normal file
12
tests/test_utils.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef TEST_UTILS_H
|
||||
#define TEST_UTILS_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
class QString;
|
||||
class QUrl;
|
||||
|
||||
std::ostream& operator <<(std::ostream& stream, const QString& str);
|
||||
std::ostream& operator <<(std::ostream& stream, const QUrl& url);
|
||||
|
||||
#endif // TEST_UTILS_H
|
Loading…
Reference in New Issue
Block a user