blob: a56e0fd7d4949f676fb6994b8d8c33be461f03dc [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QProcess>
#include <QTemporaryDir>
#include <QtTest>
class tst_generatedOutput : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void init();
void htmlFromQDocFile();
void htmlFromCpp();
void htmlFromQml();
void htmlFromCppBug80259();
void webXmlFromQDocFile();
void webXmlFromCpp();
void webXmlFromQml();
void webXmlFromCppBug80259();
void examplesManifestXml();
private:
QScopedPointer<QTemporaryDir> m_outputDir;
QString m_qdoc;
void removeFullPathStrings(QString& str);
void runQDocProcess(const QStringList &arguments);
void compareLineByLine(const QStringList &expectedFiles);
void testAndCompare(const char *input,
const char *outNames,
const char *extraParams = nullptr,
const char *outputPathPrefix = nullptr);
};
void tst_generatedOutput::initTestCase()
{
// Build the path to the QDoc binary the same way moc tests do for moc.
const auto binpath = QLibraryInfo::location(QLibraryInfo::BinariesPath);
const auto extension = QSysInfo::productType() == "windows" ? ".exe" : "";
m_qdoc = binpath + QLatin1String("/qdoc") + extension;
}
void tst_generatedOutput::init()
{
m_outputDir.reset(new QTemporaryDir());
if (!m_outputDir->isValid()) {
const QString errorMessage =
"Couldn't create temporary directory: " + m_outputDir->errorString();
QFAIL(qPrintable(errorMessage));
}
}
void tst_generatedOutput::runQDocProcess(const QStringList &arguments)
{
QProcess qdocProcess;
qdocProcess.setProgram(m_qdoc);
qdocProcess.setArguments(arguments);
qdocProcess.start();
qdocProcess.waitForFinished();
if (qdocProcess.exitCode() == 0)
return;
QString output = qdocProcess.readAllStandardOutput();
QString errors = qdocProcess.readAllStandardError();
qInfo() << "QDoc exited with exit code" << qdocProcess.exitCode();
if (output.size() > 0)
qInfo() << "Received output:\n" << output;
if (errors.size() > 0)
qInfo() << "Received errors:\n" << errors;
QFAIL("Running QDoc failed. See output above.");
}
void tst_generatedOutput::removeFullPathStrings(QString &str)
{
QRegularExpression re("(location|path|filepath)=\"[^\"]+\"");
QRegularExpressionMatch match = re.match(str);
str.replace(re, match.captured(1) + "=\"REMOVED_BY_TEST\"");
}
void tst_generatedOutput::compareLineByLine(const QStringList &expectedFiles)
{
for (const auto &file : expectedFiles) {
QString expected(QFINDTESTDATA("/expected_output/" + file));
QString actual(m_outputDir->path() + "/" + file);
QFile expectedFile(expected);
if (!expectedFile.open(QIODevice::ReadOnly))
QFAIL("Cannot open expected data file!");
QTextStream expectedIn(&expectedFile);
QFile actualFile(actual);
if (!actualFile.open(QIODevice::ReadOnly))
QFAIL("Cannot open actual data file!");
QTextStream actualIn(&actualFile);
const QLatin1String delim(": ");
int lineNumber = 0;
while (!expectedIn.atEnd() && !actualIn.atEnd()) {
lineNumber++;
QString prefix = file + delim + QString::number(lineNumber) + delim;
QString expectedLine = prefix + expectedIn.readLine();
QString actualLine = prefix + actualIn.readLine();
removeFullPathStrings(actualLine);
removeFullPathStrings(expectedLine);
QCOMPARE(actualLine, expectedLine);
}
}
}
void tst_generatedOutput::testAndCompare(const char *input,
const char *outNames,
const char *extraParams,
const char *outputPathPrefix)
{
QStringList args{ "-outputdir", m_outputDir->path() + "/" + outputPathPrefix,
QFINDTESTDATA(input) };
if (extraParams)
args << QString(QLatin1String(extraParams)).split(QChar(' '));
runQDocProcess(args);
if (QTest::currentTestFailed())
return;
QStringList expectedOuts(QString(QLatin1String(outNames)).split(QChar(' ')));
if (outputPathPrefix)
for (auto &expectedOut : expectedOuts)
expectedOut = QString(outputPathPrefix) + "/" + expectedOut;
compareLineByLine(expectedOuts);
}
void tst_generatedOutput::htmlFromQDocFile()
{
testAndCompare("test.qdocconf",
"qdoctests-qdocfileoutput.html "
"qdoctests-qdocfileoutput-linking.html");
}
void tst_generatedOutput::htmlFromCpp()
{
testAndCompare("testcpp.qdocconf",
"testcpp-module.html "
"testqdoc-test.html "
"testqdoc-test-members.html "
"testqdoc.html");
}
void tst_generatedOutput::htmlFromQml()
{
testAndCompare("testqml.qdocconf",
"test-componentset-example.html "
"uicomponents-qmlmodule.html "
"qdoc-test-qmlmodule.html "
"qml-qdoc-test-abstractparent.html "
"qml-qdoc-test-child.html "
"qml-qdoc-test-doctest.html "
"qml-qdoc-test-type-members.html "
"qml-qdoc-test-type.html "
"qml-uicomponents-progressbar.html "
"qml-uicomponents-switch.html "
"qml-uicomponents-tabwidget.html "
"qml-int.html");
}
void tst_generatedOutput::htmlFromCppBug80259()
{
testAndCompare("bug80259/testmodule.qdocconf",
"first.html "
"second.html "
"third.html "
"index.html");
}
void tst_generatedOutput::webXmlFromQDocFile()
{
testAndCompare("webxml_test.qdocconf",
"html/qdoctests-qdocfileoutput.webxml "
"html/qdoctests-qdocfileoutput-linking.webxml");
}
void tst_generatedOutput::webXmlFromCpp()
{
testAndCompare("webxml_testcpp.qdocconf",
"html/testcpp-module.webxml "
"html/testqdoc-test.webxml "
"html/testqdoc-testderived.webxml");
}
void tst_generatedOutput::webXmlFromQml()
{
testAndCompare("webxml_testqml.qdocconf",
"html/test-componentset-example.webxml "
"html/uicomponents-qmlmodule.webxml");
}
void tst_generatedOutput::webXmlFromCppBug80259()
{
testAndCompare("bug80259/webxml_testmodule.qdocconf",
"html/first.webxml "
"html/second.webxml "
"html/third.webxml "
"html/index.webxml");
}
void tst_generatedOutput::examplesManifestXml()
{
testAndCompare("examples-qhp.qdocconf",
"examples-manifest.xml");
}
QTEST_APPLESS_MAIN(tst_generatedOutput)
#include "tst_generatedoutput.moc"