diff options
-rw-r--r-- | tests/fuzzy-test/commandlineparser.cpp | 8 | ||||
-rw-r--r-- | tests/fuzzy-test/commandlineparser.h | 2 | ||||
-rw-r--r-- | tests/fuzzy-test/fuzzytester.cpp | 68 | ||||
-rw-r--r-- | tests/fuzzy-test/fuzzytester.h | 8 | ||||
-rw-r--r-- | tests/fuzzy-test/main.cpp | 17 |
5 files changed, 80 insertions, 23 deletions
diff --git a/tests/fuzzy-test/commandlineparser.cpp b/tests/fuzzy-test/commandlineparser.cpp index 9588c00ce..c49381757 100644 --- a/tests/fuzzy-test/commandlineparser.cpp +++ b/tests/fuzzy-test/commandlineparser.cpp @@ -37,6 +37,7 @@ static QString profileOption() { return "--profile"; } static QString startCommitOption() { return "--start-commit"; } static QString maxDurationoption() { return "--max-duration"; } static QString jobCountOption() { return "--jobs"; } +static QString logOption() { return "--log"; } CommandLineParser::CommandLineParser() { @@ -48,6 +49,7 @@ void CommandLineParser::parse(const QStringList &commandLine) m_startCommit.clear(); m_maxDuration = 0; m_jobCount = 0; + m_log = false; m_commandLine = commandLine; Q_ASSERT(!m_commandLine.isEmpty()); m_command = m_commandLine.takeFirst(); @@ -61,6 +63,8 @@ void CommandLineParser::parse(const QStringList &commandLine) assignOptionArgument(arg, m_jobCount); else if (arg == maxDurationoption()) parseDuration(); + else if (arg == logOption()) + m_log = true; else throw ParseException(QString::fromLocal8Bit("Unknown parameter '%1'").arg(arg)); } @@ -73,9 +77,9 @@ void CommandLineParser::parse(const QStringList &commandLine) QString CommandLineParser::usageString() const { return QString::fromLocal8Bit("%1 %2 <profile> %3 <start commit> [%4 <duration>] " - "[%5 <job count>]") + "[%5 <job count>] [%6]") .arg(QFileInfo(m_command).fileName(), profileOption(), startCommitOption(), - maxDurationoption(), jobCountOption()); + maxDurationoption(), jobCountOption(), logOption()); } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) diff --git a/tests/fuzzy-test/commandlineparser.h b/tests/fuzzy-test/commandlineparser.h index 8682e9ef4..963ae78e1 100644 --- a/tests/fuzzy-test/commandlineparser.h +++ b/tests/fuzzy-test/commandlineparser.h @@ -57,6 +57,7 @@ public: QString startCommit() const { return m_startCommit; } int maxDurationInMinutes() const { return m_maxDuration; } int jobCount() const { return m_jobCount; } + bool log() const { return m_log; } QString usageString() const; @@ -71,6 +72,7 @@ private: QString m_startCommit; int m_maxDuration; int m_jobCount; + bool m_log; }; #endif // Include guard. diff --git a/tests/fuzzy-test/fuzzytester.cpp b/tests/fuzzy-test/fuzzytester.cpp index eb5fdb468..d465a3bdc 100644 --- a/tests/fuzzy-test/fuzzytester.cpp +++ b/tests/fuzzy-test/fuzzytester.cpp @@ -31,21 +31,27 @@ #include <QDir> #include <QElapsedTimer> +#include <QFile> #include <QProcess> #include <algorithm> #include <cstdlib> #include <ctime> +static QString resolveIncrementalActivity() { return "resolve-incremental"; } +static QString buildIncrementalActivity() { return "build-incremental"; } +static QString buildFromScratchActivity() { return "build-from-scratch"; } + FuzzyTester::FuzzyTester() { } void FuzzyTester::runTest(const QString &profile, const QString &startCommit, - int maxDurationInMinutes, int jobCount) + int maxDurationInMinutes, int jobCount, bool log) { m_profile = profile; m_jobCount = jobCount; + m_log = log; runGit(QStringList() << "rev-parse" << "HEAD", &m_headCommit); qDebug("HEAD is %s", qPrintable(m_headCommit)); @@ -78,6 +84,7 @@ void FuzzyTester::runTest(const QString &profile, const QString &startCommit, break; } + m_currentCommit = currentCommit; buildSequence << currentCommit; checkoutCommit(currentCommit); qDebug("Testing incremental build #%d (%s)", buildSequence.count() - 1, @@ -86,23 +93,32 @@ void FuzzyTester::runTest(const QString &profile, const QString &startCommit, // Doing "resolve" and "build" separately introduces additional possibilities // for errors, as information from change tracking has to be serialized correctly. QString qbsError; + m_currentActivity = resolveIncrementalActivity(); bool success = runQbs(defaultBuildDir(), QLatin1String("resolve"), &qbsError); - if (success) + if (success) { + m_currentActivity = buildIncrementalActivity(); success = runQbs(defaultBuildDir(), QLatin1String("build"), &qbsError); + } + m_currentActivity = buildFromScratchActivity(); if (success) { if (!doCleanBuild(&qbsError)) { - const QString message = QString::fromLocal8Bit("An incremental build succeeded " - "with a commit for which a clean build failed.\n" - "The qbs error message for the clean build was: '%1'").arg(qbsError); + QString message = "An incremental build succeeded " + "with a commit for which a clean build failed."; + if (!m_log) { + message += QString::fromLocal8Bit("\nThe qbs error message " + "for the clean build was: '%1'").arg(qbsError); + } throwIncrementalBuildError(message, buildSequence); } } else { qDebug("Incremental build failed. Checking whether clean build works..."); if (doCleanBuild()) { - const QString message = QString::fromLocal8Bit("An incremental build failed " - "with a commit for which a clean build succeeded.\n" - "The qbs error message for the incremental build was: '%1'") - .arg(qbsError); + QString message = "An incremental build failed " + "with a commit for which a clean build succeeded."; + if (!m_log) { + message += QString::fromLocal8Bit("\nThe qbs error message for " + "the incremental build was: '%1'").arg(qbsError); + } throwIncrementalBuildError(message, buildSequence); } else { qDebug("Clean build also fails. Continuing."); @@ -128,17 +144,19 @@ QStringList FuzzyTester::findAllCommits(const QString &startCommit) QString allCommitsString; runGit(QStringList() << "log" << (startCommit + "~1.." + m_headCommit) << "--format=format:%h", &allCommitsString); - return allCommitsString.simplified().split(QLatin1Char(' ')); + return allCommitsString.simplified().split(QLatin1Char(' '), QString::SkipEmptyParts); } QString FuzzyTester::findWorkingStartCommit(const QString &startCommit) { const QStringList allCommits = findAllCommits(startCommit); QString qbsError; + m_currentActivity = buildFromScratchActivity(); for (int i = allCommits.count() - 1; i >= 0; --i) { QString currentCommit = allCommits.at(i); checkoutCommit(currentCommit); removeDir(defaultBuildDir()); + m_currentCommit = currentCommit; if (runQbs(defaultBuildDir(), QLatin1String("build"), &qbsError)) return currentCommit; qDebug("Commit %s is not buildable.", qPrintable(currentCommit)); @@ -168,13 +186,32 @@ bool FuzzyTester::runQbs(const QString &buildDir, const QString &command, QStrin if (errorOutput) errorOutput->clear(); QProcess qbs; - QStringList commandLine = QStringList(command) << "-qq" << "-d" << buildDir; + QStringList commandLine = QStringList(command) << "-d" << buildDir; + if (m_log) { + commandLine << "-vv"; + const int maxLoggedCommits = 2; + Q_ASSERT(m_commitsWithLogFiles.count() <= maxLoggedCommits + 1); + if (m_commitsWithLogFiles.count() == maxLoggedCommits + 1) { + static const QStringList allActivities = QStringList() << resolveIncrementalActivity() + << buildIncrementalActivity() << buildFromScratchActivity(); + const QString oldCommit = m_commitsWithLogFiles.dequeue(); + foreach (const QString &a, allActivities) + QFile::remove(logFilePath(oldCommit, a)); + } + qbs.setStandardErrorFile(logFilePath(m_currentCommit, m_currentActivity)); + if (m_commitsWithLogFiles.isEmpty() || m_commitsWithLogFiles.last() != m_currentCommit) + m_commitsWithLogFiles.enqueue(m_currentCommit); + } else { + commandLine << "-qq"; + } if (m_jobCount != 0) commandLine << "--jobs" << QString::number(m_jobCount); commandLine << ("profile:" + m_profile); qbs.start("qbs", commandLine); - if (!qbs.waitForStarted()) - throw TestError("Failed to start qbs. It is expected to be in the PATH."); + if (!qbs.waitForStarted()) { + throw TestError(QString::fromLocal8Bit("Failed to start qbs. It is expected to be " + "in the PATH. QProcess error string: '%1'").arg(qbs.errorString())); + } if (!qbs.waitForFinished(-1) || qbs.exitCode() != 0) { if (errorOutput) *errorOutput = QString::fromLocal8Bit(qbs.readAllStandardError()); @@ -208,6 +245,11 @@ void FuzzyTester::throwIncrementalBuildError(const QString &message, "The sequence of commits was: %2.").arg(message, commitSequenceString)); } +QString FuzzyTester::logFilePath(const QString &commit, const QString &activity) +{ + return "log." + commit + '.' + activity; +} + QString FuzzyTester::defaultBuildDir() { return "fuzzytest-build"; diff --git a/tests/fuzzy-test/fuzzytester.h b/tests/fuzzy-test/fuzzytester.h index 4639e7394..1ae8a602c 100644 --- a/tests/fuzzy-test/fuzzytester.h +++ b/tests/fuzzy-test/fuzzytester.h @@ -30,6 +30,7 @@ #ifndef QBS_FUZZYTESTER_H #define QBS_FUZZYTESTER_H +#include <QQueue> #include <QString> #include <exception> @@ -56,7 +57,7 @@ public: FuzzyTester(); void runTest(const QString &profile, const QString &startCommit, int maxDurationInMinutes, - int jobCount); + int jobCount, bool log); private: void checkoutCommit(const QString &commit); @@ -68,11 +69,16 @@ private: bool doCleanBuild(QString *errorMessage = 0); void throwIncrementalBuildError(const QString &message, const QStringList &commitSequence); + static QString logFilePath(const QString &commit, const QString &activity); static QString defaultBuildDir(); QString m_profile; int m_jobCount; + bool m_log; QString m_headCommit; + QString m_currentCommit; + QString m_currentActivity; + QQueue<QString> m_commitsWithLogFiles; }; #endif // Include guard. diff --git a/tests/fuzzy-test/main.cpp b/tests/fuzzy-test/main.cpp index efc503d1f..1bd8ee26c 100644 --- a/tests/fuzzy-test/main.cpp +++ b/tests/fuzzy-test/main.cpp @@ -37,9 +37,9 @@ #include <iostream> static bool parseCommandLine(const QStringList &commandLine, QString &profile, - QString &startCommi, int &maxDuration, int &jobCount); + QString &startCommi, int &maxDuration, int &jobCount, bool &log); static bool runTest(const QString &profile, const QString &startCommit, int maxDuration, - int jobCount); + int jobCount, bool log); int main(int argc, char *argv[]) { @@ -49,16 +49,17 @@ int main(int argc, char *argv[]) QString startCommit; int maxDuration; int jobCount; - if (!parseCommandLine(app.arguments(), profile, startCommit, maxDuration, jobCount)) + bool log; + if (!parseCommandLine(app.arguments(), profile, startCommit, maxDuration, jobCount, log)) return EXIT_FAILURE; - if (!runTest(profile, startCommit, maxDuration, jobCount)) + if (!runTest(profile, startCommit, maxDuration, jobCount, log)) return EXIT_FAILURE; std::cout << "Test finished successfully." << std::endl; return EXIT_SUCCESS; } bool parseCommandLine(const QStringList &commandLine, QString &profile, QString &startCommit, - int &maxDuration, int &jobCount) + int &maxDuration, int &jobCount, bool &log) { CommandLineParser cmdParser; try { @@ -72,13 +73,15 @@ bool parseCommandLine(const QStringList &commandLine, QString &profile, QString startCommit = cmdParser.startCommit(); maxDuration = cmdParser.maxDurationInMinutes(); jobCount = cmdParser.jobCount(); + log = cmdParser.log(); return true; } -bool runTest(const QString &profile, const QString &startCommit, int maxDuration, int jobCount) +bool runTest(const QString &profile, const QString &startCommit, int maxDuration, int jobCount, + bool log) { try { - FuzzyTester().runTest(profile, startCommit, maxDuration, jobCount); + FuzzyTester().runTest(profile, startCommit, maxDuration, jobCount, log); } catch (const TestError &e) { std::cerr << qPrintable(e.errorMessage) << std::endl; return false; |