testlib: Replace custom QTestCoreList with std::vector
The custom linked list implementation was implemented using recursion, and as a result didn't handle long lists of test cases, exhausting the stack on e.g. Windows where the default stack is only 1MB. This was the case with e.g. the tst_QChar test that produces 20K test cases. Replacing with a std::vector should do nicely for our use-case. No attempt has been made at further reducing the complexity of QTestElement/QTestCoreElement/QTestElementAttribute. Pick-to: 6.2 Change-Id: Ie295f7cf937ec6abdc4606b6120818551ad285c7 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
4e0082a9ca
commit
b8191f41c6
@ -39,7 +39,6 @@ qt_internal_add_module(Test
|
|||||||
qtestblacklist.cpp qtestblacklist_p.h
|
qtestblacklist.cpp qtestblacklist_p.h
|
||||||
qtestcase.cpp qtestcase.h
|
qtestcase.cpp qtestcase.h
|
||||||
qtestcoreelement_p.h
|
qtestcoreelement_p.h
|
||||||
qtestcorelist_p.h
|
|
||||||
qtestdata.cpp qtestdata.h
|
qtestdata.cpp qtestdata.h
|
||||||
qtestelement.cpp qtestelement_p.h
|
qtestelement.cpp qtestelement_p.h
|
||||||
qtestelementattribute.cpp qtestelementattribute_p.h
|
qtestelementattribute.cpp qtestelementattribute_p.h
|
||||||
|
@ -105,19 +105,19 @@ void QJUnitTestLogger::startLogging()
|
|||||||
property = new QTestElement(QTest::LET_Property);
|
property = new QTestElement(QTest::LET_Property);
|
||||||
property->addAttribute(QTest::AI_Name, "QTestVersion");
|
property->addAttribute(QTest::AI_Name, "QTestVersion");
|
||||||
property->addAttribute(QTest::AI_PropertyValue, QTEST_VERSION_STR);
|
property->addAttribute(QTest::AI_PropertyValue, QTEST_VERSION_STR);
|
||||||
properties->addLogElement(property);
|
properties->addChild(property);
|
||||||
|
|
||||||
property = new QTestElement(QTest::LET_Property);
|
property = new QTestElement(QTest::LET_Property);
|
||||||
property->addAttribute(QTest::AI_Name, "QtVersion");
|
property->addAttribute(QTest::AI_Name, "QtVersion");
|
||||||
property->addAttribute(QTest::AI_PropertyValue, qVersion());
|
property->addAttribute(QTest::AI_PropertyValue, qVersion());
|
||||||
properties->addLogElement(property);
|
properties->addChild(property);
|
||||||
|
|
||||||
property = new QTestElement(QTest::LET_Property);
|
property = new QTestElement(QTest::LET_Property);
|
||||||
property->addAttribute(QTest::AI_Name, "QtBuild");
|
property->addAttribute(QTest::AI_Name, "QtBuild");
|
||||||
property->addAttribute(QTest::AI_PropertyValue, QLibraryInfo::build());
|
property->addAttribute(QTest::AI_PropertyValue, QLibraryInfo::build());
|
||||||
properties->addLogElement(property);
|
properties->addChild(property);
|
||||||
|
|
||||||
currentTestSuite->addLogElement(properties);
|
currentTestSuite->addChild(properties);
|
||||||
|
|
||||||
elapsedTestcaseTime.start();
|
elapsedTestcaseTime.start();
|
||||||
}
|
}
|
||||||
@ -141,14 +141,9 @@ void QJUnitTestLogger::stopLogging()
|
|||||||
currentTestSuite->addAttribute(QTest::AI_Time,
|
currentTestSuite->addAttribute(QTest::AI_Time,
|
||||||
toSecondsFormat(QTestLog::msecsTotalTime()).constData());
|
toSecondsFormat(QTestLog::msecsTotalTime()).constData());
|
||||||
|
|
||||||
currentTestSuite->addLogElement(listOfTestcases);
|
for (auto *testCase : listOfTestcases)
|
||||||
|
currentTestSuite->addChild(testCase);
|
||||||
// For correct indenting, make sure every testcase knows its parent
|
listOfTestcases.clear();
|
||||||
QTestElement *testcase = listOfTestcases;
|
|
||||||
while (testcase) {
|
|
||||||
testcase->setParent(currentTestSuite);
|
|
||||||
testcase = testcase->nextElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
logFormatter->output(currentTestSuite);
|
logFormatter->output(currentTestSuite);
|
||||||
|
|
||||||
@ -168,7 +163,7 @@ void QJUnitTestLogger::enterTestCase(const char *name)
|
|||||||
currentTestCase = new QTestElement(QTest::LET_TestCase);
|
currentTestCase = new QTestElement(QTest::LET_TestCase);
|
||||||
currentTestCase->addAttribute(QTest::AI_Name, name);
|
currentTestCase->addAttribute(QTest::AI_Name, name);
|
||||||
currentTestCase->addAttribute(QTest::AI_Classname, QTestResult::currentTestObjectName());
|
currentTestCase->addAttribute(QTest::AI_Classname, QTestResult::currentTestObjectName());
|
||||||
currentTestCase->addToList(&listOfTestcases);
|
listOfTestcases.push_back(currentTestCase);
|
||||||
|
|
||||||
Q_ASSERT(!systemOutputElement && !systemErrorElement);
|
Q_ASSERT(!systemOutputElement && !systemErrorElement);
|
||||||
systemOutputElement = new QTestElement(QTest::LET_SystemOutput);
|
systemOutputElement = new QTestElement(QTest::LET_SystemOutput);
|
||||||
@ -212,13 +207,13 @@ void QJUnitTestLogger::leaveTestCase()
|
|||||||
currentTestCase->addAttribute(QTest::AI_Time,
|
currentTestCase->addAttribute(QTest::AI_Time,
|
||||||
toSecondsFormat(elapsedTestCaseSeconds()).constData());
|
toSecondsFormat(elapsedTestCaseSeconds()).constData());
|
||||||
|
|
||||||
if (systemOutputElement->childElements())
|
if (!systemOutputElement->childElements().empty())
|
||||||
currentTestCase->addLogElement(systemOutputElement);
|
currentTestCase->addChild(systemOutputElement);
|
||||||
else
|
else
|
||||||
delete systemOutputElement;
|
delete systemOutputElement;
|
||||||
|
|
||||||
if (systemErrorElement->childElements())
|
if (!systemErrorElement->childElements().empty())
|
||||||
currentTestCase->addLogElement(systemErrorElement);
|
currentTestCase->addChild(systemErrorElement);
|
||||||
else
|
else
|
||||||
delete systemErrorElement;
|
delete systemErrorElement;
|
||||||
|
|
||||||
@ -252,8 +247,7 @@ void QJUnitTestLogger::addFailure(QTest::LogElementType elementType,
|
|||||||
if (elementType == QTest::LET_Failure) {
|
if (elementType == QTest::LET_Failure) {
|
||||||
// Make sure we're not adding failure when we already have error,
|
// Make sure we're not adding failure when we already have error,
|
||||||
// or adding additional failures when we already have a failure.
|
// or adding additional failures when we already have a failure.
|
||||||
for (auto *childElement = currentTestCase->childElements();
|
for (auto *childElement : currentTestCase->childElements()) {
|
||||||
childElement; childElement = childElement->nextElement()) {
|
|
||||||
if (childElement->elementType() == QTest::LET_Error ||
|
if (childElement->elementType() == QTest::LET_Error ||
|
||||||
childElement->elementType() == QTest::LET_Failure)
|
childElement->elementType() == QTest::LET_Failure)
|
||||||
return;
|
return;
|
||||||
@ -272,10 +266,10 @@ void QJUnitTestLogger::addFailure(QTest::LogElementType elementType,
|
|||||||
if (!details.isEmpty()) {
|
if (!details.isEmpty()) {
|
||||||
auto textNode = new QTestElement(QTest::LET_Text);
|
auto textNode = new QTestElement(QTest::LET_Text);
|
||||||
textNode->addAttribute(QTest::AI_Value, details.toUtf8().constData());
|
textNode->addAttribute(QTest::AI_Value, details.toUtf8().constData());
|
||||||
failureElement->addLogElement(textNode);
|
failureElement->addChild(textNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTestCase->addLogElement(failureElement);
|
currentTestCase->addChild(failureElement);
|
||||||
|
|
||||||
switch (elementType) {
|
switch (elementType) {
|
||||||
case QTest::LET_Failure: ++failureCounter; break;
|
case QTest::LET_Failure: ++failureCounter; break;
|
||||||
@ -292,7 +286,7 @@ void QJUnitTestLogger::addMessage(MessageTypes type, const QString &message, con
|
|||||||
if (type == QAbstractTestLogger::Skip) {
|
if (type == QAbstractTestLogger::Skip) {
|
||||||
auto skippedElement = new QTestElement(QTest::LET_Skipped);
|
auto skippedElement = new QTestElement(QTest::LET_Skipped);
|
||||||
skippedElement->addAttribute(QTest::AI_Message, message.toUtf8().constData());
|
skippedElement->addAttribute(QTest::AI_Message, message.toUtf8().constData());
|
||||||
currentTestCase->addLogElement(skippedElement);
|
currentTestCase->addChild(skippedElement);
|
||||||
return;
|
return;
|
||||||
} else if (type == QAbstractTestLogger::QFatal) {
|
} else if (type == QAbstractTestLogger::QFatal) {
|
||||||
addFailure(QTest::LET_Error, "qfatal", message);
|
addFailure(QTest::LET_Error, "qfatal", message);
|
||||||
@ -316,7 +310,7 @@ void QJUnitTestLogger::addMessage(MessageTypes type, const QString &message, con
|
|||||||
|
|
||||||
auto textNode = new QTestElement(QTest::LET_Text);
|
auto textNode = new QTestElement(QTest::LET_Text);
|
||||||
textNode->addAttribute(QTest::AI_Value, message.toUtf8().constData());
|
textNode->addAttribute(QTest::AI_Value, message.toUtf8().constData());
|
||||||
systemLogElement->addLogElement(textNode);
|
systemLogElement->addChild(textNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -51,9 +51,13 @@
|
|||||||
// We mean it.
|
// We mean it.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <QtTest/qttestglobal.h>
|
||||||
|
|
||||||
#include <QtTest/private/qabstracttestlogger_p.h>
|
#include <QtTest/private/qabstracttestlogger_p.h>
|
||||||
#include <QtTest/private/qtestelementattribute_p.h>
|
#include <QtTest/private/qtestelementattribute_p.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QTestJUnitStreamer;
|
class QTestJUnitStreamer;
|
||||||
@ -88,7 +92,7 @@ class QJUnitTestLogger : public QAbstractTestLogger
|
|||||||
const char *failureType, const QString &failureDescription);
|
const char *failureType, const QString &failureDescription);
|
||||||
|
|
||||||
QTestElement *currentTestSuite = nullptr;
|
QTestElement *currentTestSuite = nullptr;
|
||||||
QTestElement *listOfTestcases = nullptr;
|
std::vector<QTestElement*> listOfTestcases;
|
||||||
QTestElement *currentTestCase = nullptr;
|
QTestElement *currentTestCase = nullptr;
|
||||||
QTestElement *systemOutputElement = nullptr;
|
QTestElement *systemOutputElement = nullptr;
|
||||||
QTestElement *systemErrorElement = nullptr;
|
QTestElement *systemErrorElement = nullptr;
|
||||||
|
@ -51,21 +51,23 @@
|
|||||||
// We mean it.
|
// We mean it.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <QtTest/private/qtestcorelist_p.h>
|
#include <QtTest/qttestglobal.h>
|
||||||
#include <QtTest/private/qtestelementattribute_p.h>
|
#include <QtTest/private/qtestelementattribute_p.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
template <class ElementType>
|
template <class ElementType>
|
||||||
class QTestCoreElement: public QTestCoreList<ElementType>
|
class QTestCoreElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QTestCoreElement( int type = -1 );
|
QTestCoreElement( int type = -1 );
|
||||||
virtual ~QTestCoreElement();
|
virtual ~QTestCoreElement();
|
||||||
|
|
||||||
void addAttribute(const QTest::AttributeIndex index, const char *value);
|
void addAttribute(const QTest::AttributeIndex index, const char *value);
|
||||||
QTestElementAttribute *attributes() const;
|
const std::vector<QTestElementAttribute*> &attributes() const;
|
||||||
const char *attributeValue(QTest::AttributeIndex index) const;
|
const char *attributeValue(QTest::AttributeIndex index) const;
|
||||||
const char *attributeName(QTest::AttributeIndex index) const;
|
const char *attributeName(QTest::AttributeIndex index) const;
|
||||||
const QTestElementAttribute *attribute(QTest::AttributeIndex index) const;
|
const QTestElementAttribute *attribute(QTest::AttributeIndex index) const;
|
||||||
@ -74,7 +76,7 @@ class QTestCoreElement: public QTestCoreList<ElementType>
|
|||||||
QTest::LogElementType elementType() const;
|
QTest::LogElementType elementType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTestElementAttribute *listOfAttributes = nullptr;
|
std::vector<QTestElementAttribute*> listOfAttributes;
|
||||||
QTest::LogElementType type;
|
QTest::LogElementType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,7 +89,8 @@ QTestCoreElement<ElementType>::QTestCoreElement(int t)
|
|||||||
template<class ElementType>
|
template<class ElementType>
|
||||||
QTestCoreElement<ElementType>::~QTestCoreElement()
|
QTestCoreElement<ElementType>::~QTestCoreElement()
|
||||||
{
|
{
|
||||||
delete listOfAttributes;
|
for (auto *attribute : listOfAttributes)
|
||||||
|
delete attribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ElementType>
|
template <class ElementType>
|
||||||
@ -98,11 +101,11 @@ void QTestCoreElement<ElementType>::addAttribute(const QTest::AttributeIndex att
|
|||||||
|
|
||||||
QTestElementAttribute *testAttribute = new QTestElementAttribute;
|
QTestElementAttribute *testAttribute = new QTestElementAttribute;
|
||||||
testAttribute->setPair(attributeIndex, value);
|
testAttribute->setPair(attributeIndex, value);
|
||||||
testAttribute->addToList(&listOfAttributes);
|
listOfAttributes.push_back(testAttribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ElementType>
|
template <class ElementType>
|
||||||
QTestElementAttribute *QTestCoreElement<ElementType>::attributes() const
|
const std::vector<QTestElementAttribute*> &QTestCoreElement<ElementType>::attributes() const
|
||||||
{
|
{
|
||||||
return listOfAttributes;
|
return listOfAttributes;
|
||||||
}
|
}
|
||||||
@ -159,12 +162,9 @@ QTest::LogElementType QTestCoreElement<ElementType>::elementType() const
|
|||||||
template <class ElementType>
|
template <class ElementType>
|
||||||
const QTestElementAttribute *QTestCoreElement<ElementType>::attribute(QTest::AttributeIndex index) const
|
const QTestElementAttribute *QTestCoreElement<ElementType>::attribute(QTest::AttributeIndex index) const
|
||||||
{
|
{
|
||||||
QTestElementAttribute *iterator = listOfAttributes;
|
for (auto *attribute : listOfAttributes) {
|
||||||
while (iterator) {
|
if (attribute->index() == index)
|
||||||
if (iterator->index() == index)
|
return attribute;
|
||||||
return iterator;
|
|
||||||
|
|
||||||
iterator = iterator->nextElement();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of the QtTest module of the Qt Toolkit.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:LGPL$
|
|
||||||
** 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 Lesser General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
||||||
** packaging of this file. Please review the following information to
|
|
||||||
** ensure the GNU Lesser General Public License version 3 requirements
|
|
||||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 2.0 or (at your option) the GNU General
|
|
||||||
** Public license version 3 or any later version approved by the KDE Free
|
|
||||||
** Qt Foundation. The licenses are as published by the Free Software
|
|
||||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
||||||
** 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-2.0.html and
|
|
||||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QTESTCORELIST_P_H
|
|
||||||
#define QTESTCORELIST_P_H
|
|
||||||
|
|
||||||
//
|
|
||||||
// W A R N I N G
|
|
||||||
// -------------
|
|
||||||
//
|
|
||||||
// This file is not part of the Qt API. It exists purely as an
|
|
||||||
// implementation detail. This header file may change from version to
|
|
||||||
// version without notice, or even be removed.
|
|
||||||
//
|
|
||||||
// We mean it.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <QtCore/qglobal.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class QTestCoreList
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QTestCoreList();
|
|
||||||
virtual ~QTestCoreList();
|
|
||||||
|
|
||||||
void addToList(T **list);
|
|
||||||
T *nextElement();
|
|
||||||
T *previousElement();
|
|
||||||
private:
|
|
||||||
T *next;
|
|
||||||
T *prev;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
QTestCoreList<T>::QTestCoreList()
|
|
||||||
: next(nullptr)
|
|
||||||
, prev(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
QTestCoreList<T>::~QTestCoreList()
|
|
||||||
{
|
|
||||||
if (prev) {
|
|
||||||
prev->next = nullptr;
|
|
||||||
}
|
|
||||||
delete prev;
|
|
||||||
|
|
||||||
if (next) {
|
|
||||||
next->prev = nullptr;
|
|
||||||
}
|
|
||||||
delete next;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void QTestCoreList<T>::addToList(T **list)
|
|
||||||
{
|
|
||||||
if (next)
|
|
||||||
next->addToList(list);
|
|
||||||
else {
|
|
||||||
next = *list;
|
|
||||||
if (next)
|
|
||||||
next->prev = static_cast<T*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
*list = static_cast<T*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
T *QTestCoreList<T>::nextElement()
|
|
||||||
{
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
T *QTestCoreList<T>::previousElement()
|
|
||||||
{
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif
|
|
@ -48,16 +48,17 @@ QTestElement::QTestElement(int type)
|
|||||||
|
|
||||||
QTestElement::~QTestElement()
|
QTestElement::~QTestElement()
|
||||||
{
|
{
|
||||||
delete listOfChildren;
|
for (auto *child : listOfChildren)
|
||||||
|
delete child;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QTestElement::addLogElement(QTestElement *element)
|
bool QTestElement::addChild(QTestElement *element)
|
||||||
{
|
{
|
||||||
if (!element)
|
if (!element)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (element->elementType() != QTest::LET_Undefined) {
|
if (element->elementType() != QTest::LET_Undefined) {
|
||||||
element->addToList(&listOfChildren);
|
listOfChildren.push_back(element);
|
||||||
element->setParent(this);
|
element->setParent(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -65,7 +66,7 @@ bool QTestElement::addLogElement(QTestElement *element)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTestElement *QTestElement::childElements() const
|
const std::vector<QTestElement*> &QTestElement::childElements() const
|
||||||
{
|
{
|
||||||
return listOfChildren;
|
return listOfChildren;
|
||||||
}
|
}
|
||||||
|
@ -51,26 +51,27 @@
|
|||||||
// We mean it.
|
// We mean it.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <QtTest/qttestglobal.h>
|
||||||
#include <QtTest/private/qtestcoreelement_p.h>
|
#include <QtTest/private/qtestcoreelement_p.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
class QTestElement: public QTestCoreElement<QTestElement>
|
class QTestElement : public QTestCoreElement<QTestElement>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QTestElement(int type = -1);
|
QTestElement(int type = -1);
|
||||||
~QTestElement();
|
~QTestElement();
|
||||||
|
|
||||||
bool addLogElement(QTestElement *element);
|
bool addChild(QTestElement *element);
|
||||||
QTestElement *childElements() const;
|
const std::vector<QTestElement*> &childElements() const;
|
||||||
|
|
||||||
const QTestElement *parentElement() const;
|
const QTestElement *parentElement() const;
|
||||||
void setParent(const QTestElement *p);
|
void setParent(const QTestElement *p);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTestElement *listOfChildren = nullptr;
|
std::vector<QTestElement*> listOfChildren;
|
||||||
const QTestElement * parent = nullptr;
|
const QTestElement *parent = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
// We mean it.
|
// We mean it.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <QtTest/private/qtestcorelist_p.h>
|
#include <QtTest/qttestglobal.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ namespace QTest {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class QTestElementAttribute: public QTestCoreList<QTestElementAttribute>
|
class QTestElementAttribute
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QTestElementAttribute();
|
QTestElementAttribute();
|
||||||
|
@ -95,7 +95,7 @@ void QTestJUnitStreamer::formatEnd(const QTestElement *element, QTestCharBuffer
|
|||||||
if (!element || !formatted )
|
if (!element || !formatted )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!element->childElements()) {
|
if (element->childElements().empty()) {
|
||||||
formatted->data()[0] = '\0';
|
formatted->data()[0] = '\0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ void QTestJUnitStreamer::formatAfterAttributes(const QTestElement *element, QTes
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!element->childElements())
|
if (element->childElements().empty())
|
||||||
QTest::qt_asprintf(formatted, "/>\n");
|
QTest::qt_asprintf(formatted, "/>\n");
|
||||||
else
|
else
|
||||||
QTest::qt_asprintf(formatted, ">\n");
|
QTest::qt_asprintf(formatted, ">\n");
|
||||||
@ -145,54 +145,39 @@ void QTestJUnitStreamer::output(QTestElement *element) const
|
|||||||
{
|
{
|
||||||
QTEST_ASSERT(element);
|
QTEST_ASSERT(element);
|
||||||
|
|
||||||
outputString("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
|
if (!element->parentElement())
|
||||||
outputElements(element);
|
outputString("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
|
||||||
}
|
|
||||||
|
|
||||||
void QTestJUnitStreamer::outputElements(QTestElement *element, bool) const
|
|
||||||
{
|
|
||||||
QTestCharBuffer buf;
|
QTestCharBuffer buf;
|
||||||
bool hasChildren;
|
|
||||||
|
|
||||||
// Elements are in reverse order of occurrence, so
|
formatStart(element, &buf);
|
||||||
// start from the end and work our way backwards.
|
outputString(buf.data());
|
||||||
while (element && element->nextElement())
|
|
||||||
element = element->nextElement();
|
|
||||||
|
|
||||||
while (element) {
|
outputElementAttributes(element, element->attributes());
|
||||||
hasChildren = element->childElements();
|
|
||||||
|
|
||||||
formatStart(element, &buf);
|
formatAfterAttributes(element, &buf);
|
||||||
outputString(buf.data());
|
outputString(buf.data());
|
||||||
|
|
||||||
outputElementAttributes(element, element->attributes());
|
if (!element->childElements().empty())
|
||||||
|
outputElements(element->childElements());
|
||||||
|
|
||||||
formatAfterAttributes(element, &buf);
|
formatEnd(element, &buf);
|
||||||
outputString(buf.data());
|
outputString(buf.data());
|
||||||
|
|
||||||
if (hasChildren)
|
|
||||||
outputElements(element->childElements(), true);
|
|
||||||
|
|
||||||
formatEnd(element, &buf);
|
|
||||||
outputString(buf.data());
|
|
||||||
|
|
||||||
element = element->previousElement();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QTestJUnitStreamer::outputElementAttributes(const QTestElement* element, QTestElementAttribute *attribute) const
|
void QTestJUnitStreamer::outputElements(const std::vector<QTestElement*> &elements) const
|
||||||
|
{
|
||||||
|
for (auto *element : elements)
|
||||||
|
output(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QTestJUnitStreamer::outputElementAttributes(const QTestElement* element, const std::vector<QTestElementAttribute*> &attributes) const
|
||||||
{
|
{
|
||||||
QTestCharBuffer buf;
|
QTestCharBuffer buf;
|
||||||
|
|
||||||
// Attributes are in reverse order of occurrence, so
|
for (auto *attribute : attributes) {
|
||||||
// start from the end and work our way backwards.
|
|
||||||
while (attribute && attribute->nextElement())
|
|
||||||
attribute = attribute->nextElement();
|
|
||||||
|
|
||||||
while (attribute) {
|
|
||||||
formatAttributes(element, attribute, &buf);
|
formatAttributes(element, attribute, &buf);
|
||||||
outputString(buf.data());
|
outputString(buf.data());
|
||||||
attribute = attribute->previousElement();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,8 +72,8 @@ class QTestJUnitStreamer
|
|||||||
void formatAfterAttributes(const QTestElement *element, QTestCharBuffer *formatted) const;
|
void formatAfterAttributes(const QTestElement *element, QTestCharBuffer *formatted) const;
|
||||||
void formatAttributes(const QTestElement *element, const QTestElementAttribute *attribute, QTestCharBuffer *formatted) const;
|
void formatAttributes(const QTestElement *element, const QTestElementAttribute *attribute, QTestCharBuffer *formatted) const;
|
||||||
void output(QTestElement *element) const;
|
void output(QTestElement *element) const;
|
||||||
void outputElements(QTestElement *element, bool isChildElement = false) const;
|
void outputElements(const std::vector<QTestElement*> &) const;
|
||||||
void outputElementAttributes(const QTestElement *element, QTestElementAttribute *attribute) const;
|
void outputElementAttributes(const QTestElement *element, const std::vector<QTestElementAttribute*> &attributes) const;
|
||||||
|
|
||||||
void outputString(const char *msg) const;
|
void outputString(const char *msg) const;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user