forked from qt-creator/qt-creator
Add unit tests for gnumake parser
* Improve parser to recognize gnu make errors.
This commit is contained in:
@@ -28,6 +28,8 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "gnumakeparser.h"
|
||||
|
||||
#include "projectexplorerconstants.h"
|
||||
#include "taskwindow.h"
|
||||
|
||||
#include <QtCore/QDir>
|
||||
@@ -35,11 +37,17 @@
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace {
|
||||
const char * const MAKE_PATTERN("^(mingw(32|64)-|g)?make(\\[\\d+\\])?:\\s");
|
||||
}
|
||||
|
||||
GnuMakeParser::GnuMakeParser(const QString &dir)
|
||||
{
|
||||
//make[4]: Entering directory `/some/dir'
|
||||
m_makeDir.setPattern("^(?:mingw32-)?make.*: (\\w+) directory .(.+).$");
|
||||
m_makeDir.setPattern(QLatin1String(MAKE_PATTERN) +
|
||||
QLatin1String("(\\w+) directory .(.+).$"));
|
||||
m_makeDir.setMinimal(true);
|
||||
m_makeLine.setPattern(QLatin1String(MAKE_PATTERN) + QLatin1String("(.*)$"));
|
||||
m_makeLine.setMinimal(true);
|
||||
addDirectory(dir);
|
||||
}
|
||||
|
||||
@@ -48,10 +56,24 @@ void GnuMakeParser::stdOutput(const QString &line)
|
||||
QString lne = line.trimmed();
|
||||
|
||||
if (m_makeDir.indexIn(lne) > -1) {
|
||||
if (m_makeDir.cap(1) == "Leaving")
|
||||
removeDirectory(m_makeDir.cap(2));
|
||||
if (m_makeDir.cap(4) == "Leaving")
|
||||
removeDirectory(m_makeDir.cap(5));
|
||||
else
|
||||
addDirectory(m_makeDir.cap(2));
|
||||
addDirectory(m_makeDir.cap(5));
|
||||
return;
|
||||
}
|
||||
if (m_makeLine.indexIn(lne) > -1) {
|
||||
QString message = m_makeLine.cap(4);
|
||||
Task task(Task::Warning,
|
||||
message,
|
||||
QString() /* filename */,
|
||||
-1, /* line */
|
||||
Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||
if (message.startsWith(QLatin1String("*** "))) {
|
||||
task.description = task.description.mid(4);
|
||||
task.type = Task::Error;
|
||||
}
|
||||
addTask(task);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -70,9 +92,9 @@ void GnuMakeParser::removeDirectory(const QString &dir)
|
||||
m_directories.removeAll(dir);
|
||||
}
|
||||
|
||||
void GnuMakeParser::taskAdded(const ProjectExplorer::Task &task)
|
||||
void GnuMakeParser::taskAdded(const Task &task)
|
||||
{
|
||||
ProjectExplorer::Task editable(task);
|
||||
Task editable(task);
|
||||
QString filePath(QDir::cleanPath(task.file.trimmed()));
|
||||
|
||||
if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) {
|
||||
@@ -93,3 +115,237 @@ void GnuMakeParser::taskAdded(const ProjectExplorer::Task &task)
|
||||
|
||||
IOutputParser::taskAdded(editable);
|
||||
}
|
||||
|
||||
#if defined WITH_TESTS
|
||||
QStringList GnuMakeParser::searchDirectories() const
|
||||
{
|
||||
return m_directories;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unit tests:
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
# include <QTest>
|
||||
|
||||
# include <QtCore/QDebug>
|
||||
# include <QtCore/QUuid>
|
||||
|
||||
# include "outputparser_test.h"
|
||||
# include "projectexplorer.h"
|
||||
# include "projectexplorerconstants.h"
|
||||
|
||||
# include "metatypedeclarations.h"
|
||||
|
||||
void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("extraSearchDirs");
|
||||
QTest::addColumn<QString>("input");
|
||||
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
|
||||
QTest::addColumn<QString>("childStdOutLines");
|
||||
QTest::addColumn<QString>("childStdErrLines");
|
||||
QTest::addColumn<QList<Task> >("tasks");
|
||||
QTest::addColumn<QString>("outputLines");
|
||||
QTest::addColumn<QStringList>("additionalSearchDirs");
|
||||
|
||||
QTest::newRow("pass-through stdout")
|
||||
<< QStringList()
|
||||
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
|
||||
<< QString::fromLatin1("Sometext") << QString()
|
||||
<< QList<Task>()
|
||||
<< QString()
|
||||
<< QStringList();
|
||||
QTest::newRow("pass-through stderr")
|
||||
<< QStringList()
|
||||
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
|
||||
<< QString() << QString::fromLatin1("Sometext")
|
||||
<< QList<Task>()
|
||||
<< QString()
|
||||
<< QStringList();
|
||||
// make sure adding directories works (once;-)
|
||||
QTest::newRow("entering directory")
|
||||
<< (QStringList() << QString::fromLatin1("/test/dir") )
|
||||
<< QString::fromLatin1("make[4]: Entering directory `/home/code/build/qt/examples/opengl/grabber'\n"
|
||||
"make[4]: Entering directory `/home/code/build/qt/examples/opengl/grabber'\n")
|
||||
<< OutputParserTester::STDOUT
|
||||
<< QString() << QString()
|
||||
<< QList<Task>()
|
||||
<< QString()
|
||||
<< (QStringList() << QString::fromLatin1("/home/code/build/qt/examples/opengl/grabber") << QString::fromLatin1("/test/dir"));
|
||||
QTest::newRow("leaving directory")
|
||||
<< (QStringList() << QString::fromLatin1("/home/code/build/qt/examples/opengl/grabber") << QString::fromLatin1("/test/dir"))
|
||||
<< QString::fromLatin1("make[4]: Leaving directory `/home/code/build/qt/examples/opengl/grabber'")
|
||||
<< OutputParserTester::STDOUT
|
||||
<< QString() << QString()
|
||||
<< QList<Task>()
|
||||
<< QString()
|
||||
<< (QStringList() << QString::fromLatin1("/test/dir"));
|
||||
QTest::newRow("make error")
|
||||
<< QStringList()
|
||||
<< QString::fromLatin1("make: *** No rule to make target `hello.c', needed by `hello.o'. Stop.")
|
||||
<< OutputParserTester::STDOUT
|
||||
<< QString() << QString()
|
||||
<< (QList<Task>()
|
||||
<< Task(Task::Error,
|
||||
QString::fromLatin1("No rule to make target `hello.c', needed by `hello.o'. Stop."),
|
||||
QString(), -1,
|
||||
Constants::TASK_CATEGORY_BUILDSYSTEM))
|
||||
<< QString()
|
||||
<< QStringList();
|
||||
QTest::newRow("make warning")
|
||||
<< QStringList()
|
||||
<< QString::fromLatin1("make: warning: ignoring old commands for target `xxx'")
|
||||
<< OutputParserTester::STDOUT
|
||||
<< QString() << QString()
|
||||
<< (QList<Task>()
|
||||
<< Task(Task::Warning,
|
||||
QString::fromLatin1("warning: ignoring old commands for target `xxx'"),
|
||||
QString(), -1,
|
||||
Constants::TASK_CATEGORY_BUILDSYSTEM))
|
||||
<< QString()
|
||||
<< QStringList();
|
||||
}
|
||||
|
||||
void ProjectExplorerPlugin::testGnuMakeParserParsing()
|
||||
{
|
||||
OutputParserTester testbench;
|
||||
GnuMakeParser *childParser = new GnuMakeParser;
|
||||
testbench.appendOutputParser(childParser);
|
||||
QFETCH(QStringList, extraSearchDirs);
|
||||
QFETCH(QString, input);
|
||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||
QFETCH(QList<Task>, tasks);
|
||||
QFETCH(QString, childStdOutLines);
|
||||
QFETCH(QString, childStdErrLines);
|
||||
QFETCH(QString, outputLines);
|
||||
QFETCH(QStringList, additionalSearchDirs);
|
||||
|
||||
QStringList searchDirs = childParser->searchDirectories();
|
||||
|
||||
// add extra directories:
|
||||
foreach(const QString &dir, extraSearchDirs)
|
||||
childParser->addDirectory(dir);
|
||||
|
||||
testbench.testParsing(input, inputChannel,
|
||||
tasks, childStdOutLines, childStdErrLines,
|
||||
outputLines);
|
||||
|
||||
// make sure we still have all the original dirs
|
||||
QStringList newSearchDirs = childParser->searchDirectories();
|
||||
foreach (const QString &dir, searchDirs) {
|
||||
QVERIFY(newSearchDirs.contains(dir));
|
||||
newSearchDirs.removeOne(dir);
|
||||
}
|
||||
|
||||
// make sure we have all additional dirs:
|
||||
foreach (const QString &dir, additionalSearchDirs) {
|
||||
QVERIFY(newSearchDirs.contains(dir));
|
||||
newSearchDirs.removeOne(dir);
|
||||
}
|
||||
// make sure we have no extra cruft:
|
||||
QVERIFY(newSearchDirs.isEmpty());
|
||||
}
|
||||
|
||||
void ProjectExplorerPlugin::testGnuMakeParserTaskMangling_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("files");
|
||||
QTest::addColumn<QStringList>("searchDirectories");
|
||||
QTest::addColumn<Task>("inputTask");
|
||||
QTest::addColumn<Task>("outputTask");
|
||||
|
||||
QTest::newRow("no filename")
|
||||
<< QStringList()
|
||||
<< QStringList()
|
||||
<< Task(Task::Error,
|
||||
QLatin1String("no filename, no mangling"),
|
||||
QString(),
|
||||
-1,
|
||||
Constants::TASK_CATEGORY_COMPILE)
|
||||
<< Task(Task::Error,
|
||||
QLatin1String("no filename, no mangling"),
|
||||
QString(),
|
||||
-1,
|
||||
Constants::TASK_CATEGORY_COMPILE);
|
||||
QTest::newRow("no mangling")
|
||||
<< QStringList()
|
||||
<< QStringList()
|
||||
<< Task(Task::Error,
|
||||
QLatin1String("unknown filename, no mangling"),
|
||||
QString::fromLatin1("some/path/unknown.cpp"),
|
||||
-1,
|
||||
Constants::TASK_CATEGORY_COMPILE)
|
||||
<< Task(Task::Error,
|
||||
QLatin1String("unknown filename, no mangling"),
|
||||
QString::fromLatin1("some/path/unknown.cpp"),
|
||||
-1,
|
||||
Constants::TASK_CATEGORY_COMPILE);
|
||||
QTest::newRow("find file")
|
||||
<< (QStringList() << "test/file.cpp")
|
||||
<< (QStringList() << "test")
|
||||
<< Task(Task::Error,
|
||||
QLatin1String("mangling"),
|
||||
QString::fromLatin1("file.cpp"),
|
||||
10,
|
||||
Constants::TASK_CATEGORY_COMPILE)
|
||||
<< Task(Task::Error,
|
||||
QLatin1String("mangling"),
|
||||
QString::fromLatin1("$TMPDIR/test/file.cpp"),
|
||||
10,
|
||||
Constants::TASK_CATEGORY_COMPILE);
|
||||
}
|
||||
|
||||
void ProjectExplorerPlugin::testGnuMakeParserTaskMangling()
|
||||
{
|
||||
OutputParserTester testbench;
|
||||
GnuMakeParser *childParser = new GnuMakeParser;
|
||||
testbench.appendOutputParser(childParser);
|
||||
|
||||
QFETCH(QStringList, files);
|
||||
QFETCH(QStringList, searchDirectories);
|
||||
QFETCH(Task, inputTask);
|
||||
QFETCH(Task, outputTask);
|
||||
|
||||
// setup files:
|
||||
QString tempdir;
|
||||
#if defined Q_OS_WIN
|
||||
tempdir = QDir::fromNativeSeparators(qgetenv("TEMP"));
|
||||
#else
|
||||
tempdir = QLatin1String("/tmp");
|
||||
#endif
|
||||
tempdir.append(QChar('/'));
|
||||
tempdir.append(QUuid::createUuid().toString());
|
||||
tempdir.append(QChar('/'));
|
||||
|
||||
QDir filedir(tempdir);
|
||||
foreach (const QString &file, files) {
|
||||
Q_ASSERT(!file.startsWith(QChar('/')));
|
||||
Q_ASSERT(!file.contains(QLatin1String("../")));
|
||||
|
||||
filedir.mkpath(file.left(file.lastIndexOf(QChar('/'))));
|
||||
|
||||
QFile tempfile(tempdir + file);
|
||||
if (!tempfile.open(QIODevice::WriteOnly))
|
||||
continue;
|
||||
tempfile.write("Delete me again!");
|
||||
tempfile.close();
|
||||
}
|
||||
|
||||
// setup search dirs:
|
||||
foreach (const QString &dir, searchDirectories) {
|
||||
Q_ASSERT(!dir.startsWith(QChar('/')));
|
||||
Q_ASSERT(!dir.contains(QLatin1String("../")));
|
||||
childParser->addDirectory(tempdir + dir);
|
||||
}
|
||||
|
||||
// fix up output task file:
|
||||
if (outputTask.file.startsWith(QLatin1String("$TMPDIR/")))
|
||||
outputTask.file = outputTask.file.replace(QLatin1String("$TMPDIR/"), tempdir);
|
||||
|
||||
// test mangling:
|
||||
testbench.testTaskMangling(inputTask, outputTask);
|
||||
|
||||
// clean up:
|
||||
foreach (const QString &file, files)
|
||||
filedir.rmpath(tempdir + file);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user