forked from qt-creator/qt-creator
AutoTest: Refactor output handling
Handle getting output from application's process inside base class and just process output inside the sub classes. Additionally this is a preparation for being able to process output for debugging tests as well. Change-Id: I8a2289dc7faab25afe08530b5021a0318f3ba6a6 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -133,10 +133,8 @@ QtTestOutputReader::QtTestOutputReader(const QFutureInterface<TestResultPtr> &fu
|
||||
{
|
||||
}
|
||||
|
||||
void QtTestOutputReader::processOutput()
|
||||
void QtTestOutputReader::processOutput(const QByteArray &outputLine)
|
||||
{
|
||||
if (!m_testApplication || m_testApplication->state() != QProcess::Running)
|
||||
return;
|
||||
static QStringList validEndTags = { QStringLiteral("Incident"),
|
||||
QStringLiteral("Message"),
|
||||
QStringLiteral("BenchmarkResult"),
|
||||
@@ -144,142 +142,140 @@ void QtTestOutputReader::processOutput()
|
||||
QStringLiteral("QtBuild"),
|
||||
QStringLiteral("QTestVersion") };
|
||||
|
||||
while (m_testApplication->canReadLine()) {
|
||||
m_xmlReader.addData(m_testApplication->readLine());
|
||||
while (!m_xmlReader.atEnd()) {
|
||||
if (m_futureInterface.isCanceled())
|
||||
return;
|
||||
QXmlStreamReader::TokenType token = m_xmlReader.readNext();
|
||||
switch (token) {
|
||||
case QXmlStreamReader::StartDocument:
|
||||
m_className.clear();
|
||||
break;
|
||||
case QXmlStreamReader::EndDocument:
|
||||
m_xmlReader.clear();
|
||||
return;
|
||||
case QXmlStreamReader::StartElement: {
|
||||
const QString currentTag = m_xmlReader.name().toString();
|
||||
if (currentTag == QStringLiteral("TestCase")) {
|
||||
m_className = m_xmlReader.attributes().value(QStringLiteral("name")).toString();
|
||||
QTC_ASSERT(!m_className.isEmpty(), continue);
|
||||
TestResultPtr testResult = TestResultPtr(new QtTestResult(m_className));
|
||||
testResult->setResult(Result::MessageTestCaseStart);
|
||||
testResult->setDescription(tr("Executing test case %1").arg(m_className));
|
||||
m_futureInterface.reportResult(testResult);
|
||||
} else if (currentTag == QStringLiteral("TestFunction")) {
|
||||
m_testCase = m_xmlReader.attributes().value(QStringLiteral("name")).toString();
|
||||
QTC_ASSERT(!m_testCase.isEmpty(), continue);
|
||||
TestResultPtr testResult = TestResultPtr(new QtTestResult());
|
||||
testResult->setResult(Result::MessageCurrentTest);
|
||||
testResult->setDescription(tr("Entering test function %1::%2").arg(m_className,
|
||||
m_testCase));
|
||||
m_futureInterface.reportResult(testResult);
|
||||
} else if (currentTag == QStringLiteral("Duration")) {
|
||||
m_duration = m_xmlReader.attributes().value(QStringLiteral("msecs")).toString();
|
||||
QTC_ASSERT(!m_duration.isEmpty(), continue);
|
||||
} else if (currentTag == QStringLiteral("Message")
|
||||
|| currentTag == QStringLiteral("Incident")) {
|
||||
m_dataTag.clear();
|
||||
m_description.clear();
|
||||
m_duration.clear();
|
||||
m_file.clear();
|
||||
m_result = Result::Invalid;
|
||||
m_lineNumber = 0;
|
||||
const QXmlStreamAttributes &attributes = m_xmlReader.attributes();
|
||||
m_result = TestResult::resultFromString(
|
||||
attributes.value(QStringLiteral("type")).toString());
|
||||
m_file = decode(attributes.value(QStringLiteral("file")).toString());
|
||||
if (!m_file.isEmpty()) {
|
||||
m_file = constructSourceFilePath(m_buildDir, m_file);
|
||||
}
|
||||
m_lineNumber = attributes.value(QStringLiteral("line")).toInt();
|
||||
} else if (currentTag == QStringLiteral("BenchmarkResult")) {
|
||||
const QXmlStreamAttributes &attributes = m_xmlReader.attributes();
|
||||
const QString metric = attributes.value(QStringLiteral("metrics")).toString();
|
||||
const double value = attributes.value(QStringLiteral("value")).toDouble();
|
||||
const int iterations = attributes.value(QStringLiteral("iterations")).toInt();
|
||||
m_description = constructBenchmarkInformation(metric, value, iterations);
|
||||
m_result = Result::Benchmark;
|
||||
} else if (currentTag == QStringLiteral("DataTag")) {
|
||||
m_cdataMode = DataTag;
|
||||
} else if (currentTag == QStringLiteral("Description")) {
|
||||
m_cdataMode = Description;
|
||||
} else if (currentTag == QStringLiteral("QtVersion")) {
|
||||
m_result = Result::MessageInternal;
|
||||
m_cdataMode = QtVersion;
|
||||
} else if (currentTag == QStringLiteral("QtBuild")) {
|
||||
m_result = Result::MessageInternal;
|
||||
m_cdataMode = QtBuild;
|
||||
} else if (currentTag == QStringLiteral("QTestVersion")) {
|
||||
m_result = Result::MessageInternal;
|
||||
m_cdataMode = QTestVersion;
|
||||
m_xmlReader.addData(outputLine);
|
||||
while (!m_xmlReader.atEnd()) {
|
||||
if (m_futureInterface.isCanceled())
|
||||
return;
|
||||
QXmlStreamReader::TokenType token = m_xmlReader.readNext();
|
||||
switch (token) {
|
||||
case QXmlStreamReader::StartDocument:
|
||||
m_className.clear();
|
||||
break;
|
||||
case QXmlStreamReader::EndDocument:
|
||||
m_xmlReader.clear();
|
||||
return;
|
||||
case QXmlStreamReader::StartElement: {
|
||||
const QString currentTag = m_xmlReader.name().toString();
|
||||
if (currentTag == QStringLiteral("TestCase")) {
|
||||
m_className = m_xmlReader.attributes().value(QStringLiteral("name")).toString();
|
||||
QTC_ASSERT(!m_className.isEmpty(), continue);
|
||||
TestResultPtr testResult = TestResultPtr(new QtTestResult(m_className));
|
||||
testResult->setResult(Result::MessageTestCaseStart);
|
||||
testResult->setDescription(tr("Executing test case %1").arg(m_className));
|
||||
m_futureInterface.reportResult(testResult);
|
||||
} else if (currentTag == QStringLiteral("TestFunction")) {
|
||||
m_testCase = m_xmlReader.attributes().value(QStringLiteral("name")).toString();
|
||||
QTC_ASSERT(!m_testCase.isEmpty(), continue);
|
||||
TestResultPtr testResult = TestResultPtr(new QtTestResult());
|
||||
testResult->setResult(Result::MessageCurrentTest);
|
||||
testResult->setDescription(tr("Entering test function %1::%2").arg(m_className,
|
||||
m_testCase));
|
||||
m_futureInterface.reportResult(testResult);
|
||||
} else if (currentTag == QStringLiteral("Duration")) {
|
||||
m_duration = m_xmlReader.attributes().value(QStringLiteral("msecs")).toString();
|
||||
QTC_ASSERT(!m_duration.isEmpty(), continue);
|
||||
} else if (currentTag == QStringLiteral("Message")
|
||||
|| currentTag == QStringLiteral("Incident")) {
|
||||
m_dataTag.clear();
|
||||
m_description.clear();
|
||||
m_duration.clear();
|
||||
m_file.clear();
|
||||
m_result = Result::Invalid;
|
||||
m_lineNumber = 0;
|
||||
const QXmlStreamAttributes &attributes = m_xmlReader.attributes();
|
||||
m_result = TestResult::resultFromString(
|
||||
attributes.value(QStringLiteral("type")).toString());
|
||||
m_file = decode(attributes.value(QStringLiteral("file")).toString());
|
||||
if (!m_file.isEmpty()) {
|
||||
m_file = constructSourceFilePath(m_buildDir, m_file);
|
||||
}
|
||||
break;
|
||||
m_lineNumber = attributes.value(QStringLiteral("line")).toInt();
|
||||
} else if (currentTag == QStringLiteral("BenchmarkResult")) {
|
||||
const QXmlStreamAttributes &attributes = m_xmlReader.attributes();
|
||||
const QString metric = attributes.value(QStringLiteral("metrics")).toString();
|
||||
const double value = attributes.value(QStringLiteral("value")).toDouble();
|
||||
const int iterations = attributes.value(QStringLiteral("iterations")).toInt();
|
||||
m_description = constructBenchmarkInformation(metric, value, iterations);
|
||||
m_result = Result::Benchmark;
|
||||
} else if (currentTag == QStringLiteral("DataTag")) {
|
||||
m_cdataMode = DataTag;
|
||||
} else if (currentTag == QStringLiteral("Description")) {
|
||||
m_cdataMode = Description;
|
||||
} else if (currentTag == QStringLiteral("QtVersion")) {
|
||||
m_result = Result::MessageInternal;
|
||||
m_cdataMode = QtVersion;
|
||||
} else if (currentTag == QStringLiteral("QtBuild")) {
|
||||
m_result = Result::MessageInternal;
|
||||
m_cdataMode = QtBuild;
|
||||
} else if (currentTag == QStringLiteral("QTestVersion")) {
|
||||
m_result = Result::MessageInternal;
|
||||
m_cdataMode = QTestVersion;
|
||||
}
|
||||
case QXmlStreamReader::Characters: {
|
||||
QStringRef text = m_xmlReader.text().trimmed();
|
||||
if (text.isEmpty())
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case QXmlStreamReader::Characters: {
|
||||
QStringRef text = m_xmlReader.text().trimmed();
|
||||
if (text.isEmpty())
|
||||
break;
|
||||
|
||||
switch (m_cdataMode) {
|
||||
case DataTag:
|
||||
m_dataTag = text.toString();
|
||||
break;
|
||||
case Description:
|
||||
if (!m_description.isEmpty())
|
||||
m_description.append(QLatin1Char('\n'));
|
||||
m_description.append(text);
|
||||
break;
|
||||
case QtVersion:
|
||||
m_description = tr("Qt version: %1").arg(text.toString());
|
||||
break;
|
||||
case QtBuild:
|
||||
m_description = tr("Qt build: %1").arg(text.toString());
|
||||
break;
|
||||
case QTestVersion:
|
||||
m_description = tr("QTest version: %1").arg(text.toString());
|
||||
break;
|
||||
default:
|
||||
// this must come from plain printf() calls - but this will be ignored anyhow
|
||||
qWarning() << "AutoTest.Run: Ignored plain output:" << text.toString();
|
||||
break;
|
||||
}
|
||||
switch (m_cdataMode) {
|
||||
case DataTag:
|
||||
m_dataTag = text.toString();
|
||||
break;
|
||||
case Description:
|
||||
if (!m_description.isEmpty())
|
||||
m_description.append(QLatin1Char('\n'));
|
||||
m_description.append(text);
|
||||
break;
|
||||
case QtVersion:
|
||||
m_description = tr("Qt version: %1").arg(text.toString());
|
||||
break;
|
||||
case QtBuild:
|
||||
m_description = tr("Qt build: %1").arg(text.toString());
|
||||
break;
|
||||
case QTestVersion:
|
||||
m_description = tr("QTest version: %1").arg(text.toString());
|
||||
break;
|
||||
default:
|
||||
// this must come from plain printf() calls - but this will be ignored anyhow
|
||||
qWarning() << "AutoTest.Run: Ignored plain output:" << text.toString();
|
||||
break;
|
||||
}
|
||||
case QXmlStreamReader::EndElement: {
|
||||
m_cdataMode = None;
|
||||
const QStringRef currentTag = m_xmlReader.name();
|
||||
if (currentTag == QStringLiteral("TestFunction")) {
|
||||
if (!m_duration.isEmpty()) {
|
||||
QtTestResult *testResult = new QtTestResult(m_className);
|
||||
testResult->setFunctionName(m_testCase);
|
||||
testResult->setResult(Result::MessageInternal);
|
||||
testResult->setDescription(tr("Execution took %1 ms.").arg(m_duration));
|
||||
m_futureInterface.reportResult(TestResultPtr(testResult));
|
||||
}
|
||||
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
|
||||
} else if (currentTag == QStringLiteral("TestCase")) {
|
||||
QtTestResult *testResult = new QtTestResult(m_className);
|
||||
testResult->setResult(Result::MessageTestCaseEnd);
|
||||
testResult->setDescription(
|
||||
m_duration.isEmpty() ? tr("Test finished.")
|
||||
: tr("Test execution took %1 ms.").arg(m_duration));
|
||||
m_futureInterface.reportResult(TestResultPtr(testResult));
|
||||
} else if (validEndTags.contains(currentTag.toString())) {
|
||||
break;
|
||||
}
|
||||
case QXmlStreamReader::EndElement: {
|
||||
m_cdataMode = None;
|
||||
const QStringRef currentTag = m_xmlReader.name();
|
||||
if (currentTag == QStringLiteral("TestFunction")) {
|
||||
if (!m_duration.isEmpty()) {
|
||||
QtTestResult *testResult = new QtTestResult(m_className);
|
||||
testResult->setFunctionName(m_testCase);
|
||||
testResult->setDataTag(m_dataTag);
|
||||
testResult->setResult(m_result);
|
||||
testResult->setFileName(m_file);
|
||||
testResult->setLine(m_lineNumber);
|
||||
testResult->setDescription(m_description);
|
||||
testResult->setResult(Result::MessageInternal);
|
||||
testResult->setDescription(tr("Execution took %1 ms.").arg(m_duration));
|
||||
m_futureInterface.reportResult(TestResultPtr(testResult));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
|
||||
} else if (currentTag == QStringLiteral("TestCase")) {
|
||||
QtTestResult *testResult = new QtTestResult(m_className);
|
||||
testResult->setResult(Result::MessageTestCaseEnd);
|
||||
testResult->setDescription(
|
||||
m_duration.isEmpty() ? tr("Test finished.")
|
||||
: tr("Test execution took %1 ms.").arg(m_duration));
|
||||
m_futureInterface.reportResult(TestResultPtr(testResult));
|
||||
} else if (validEndTags.contains(currentTag.toString())) {
|
||||
QtTestResult *testResult = new QtTestResult(m_className);
|
||||
testResult->setFunctionName(m_testCase);
|
||||
testResult->setDataTag(m_dataTag);
|
||||
testResult->setResult(m_result);
|
||||
testResult->setFileName(m_file);
|
||||
testResult->setLine(m_lineNumber);
|
||||
testResult->setDescription(m_description);
|
||||
m_futureInterface.reportResult(TestResultPtr(testResult));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user