diff options
Diffstat (limited to 'src/testlib')
27 files changed, 2006 insertions, 127 deletions
diff --git a/src/testlib/qabstracttestlogger.cpp b/src/testlib/qabstracttestlogger.cpp index e5d5d59..a884641 100644 --- a/src/testlib/qabstracttestlogger.cpp +++ b/src/testlib/qabstracttestlogger.cpp @@ -77,6 +77,7 @@ bool QAbstractTestLogger::isTtyOutput() #endif } + void QAbstractTestLogger::startLogging() { QTEST_ASSERT(!QTest::stream); diff --git a/src/testlib/qabstracttestlogger_p.h b/src/testlib/qabstracttestlogger_p.h index 298fbad..a550b3c 100644 --- a/src/testlib/qabstracttestlogger_p.h +++ b/src/testlib/qabstracttestlogger_p.h @@ -1,4 +1,4 @@ -/**************************************************************************** + /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) diff --git a/src/testlib/qbenchmarkvalgrind.cpp b/src/testlib/qbenchmarkvalgrind.cpp index 4b4ccd7..bcce147 100644 --- a/src/testlib/qbenchmarkvalgrind.cpp +++ b/src/testlib/qbenchmarkvalgrind.cpp @@ -1,4 +1,3 @@ - /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). @@ -52,6 +51,8 @@ #include <QtCore/qset.h> #include "3rdparty/callgrind_p.h" +QT_BEGIN_NAMESPACE + // Returns true iff a sufficiently recent valgrind is available. bool QBenchmarkValgrindUtils::haveValgrind() { @@ -272,4 +273,6 @@ QString QBenchmarkCallgrindMeasurer::metricText() return QLatin1String("callgrind"); } +QT_END_NAMESPACE + #endif // QTESTLIB_USE_VALGRIND diff --git a/src/testlib/qtestbasicstreamer.cpp b/src/testlib/qtestbasicstreamer.cpp new file mode 100644 index 0000000..b133aae --- /dev/null +++ b/src/testlib/qtestbasicstreamer.cpp @@ -0,0 +1,178 @@ +#include "qtestbasicstreamer.h" +#include "qtestlogger_p.h" +#include "qtestelement.h" +#include "qtestelementattribute.h" +#include "QtTest/private/qtestlog_p.h" +#include "qtestassert.h" + +#include <stdio.h> +#include <stdlib.h> + +#ifndef Q_OS_WIN +#include <unistd.h> +#endif + +QT_BEGIN_NAMESPACE + +namespace QTest +{ + static FILE *stream = 0; +} + +QTestBasicStreamer::QTestBasicStreamer() + :testLogger(0) +{ +} + +QTestBasicStreamer::~QTestBasicStreamer() +{} + +void QTestBasicStreamer::formatStart(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted ) + return; + QTest::qt_snprintf(formatted, 10, ""); +} + +void QTestBasicStreamer::formatEnd(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted ) + return; + QTest::qt_snprintf(formatted, 10, ""); +} + +void QTestBasicStreamer::formatBeforeAttributes(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted ) + return; + QTest::qt_snprintf(formatted, 10, ""); +} + +void QTestBasicStreamer::formatAfterAttributes(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted ) + return; + QTest::qt_snprintf(formatted, 10, ""); +} + +void QTestBasicStreamer::formatAttributes(const QTestElementAttribute *attribute, char *formatted) const +{ + if(!attribute || !formatted ) + return; + QTest::qt_snprintf(formatted, 10, ""); +} + +void QTestBasicStreamer::output(QTestElement *element) const +{ + if(!element) + return; + + outputElements(element); +} + +void QTestBasicStreamer::outputElements(QTestElement *element, bool) const +{ + char buf[1024]; + bool hasChildren; + /* + Elements are in reverse order of occurrence, so start from the end and work + our way backwards. + */ + while (element && element->nextElement()) { + element = element->nextElement(); + } + while (element) { + hasChildren = element->childElements(); + + formatStart(element, buf); + outputString(buf); + + formatBeforeAttributes(element, buf); + outputString(buf); + + outputElementAttributes(element->attributes()); + + formatAfterAttributes(element, buf); + outputString(buf); + + if(hasChildren) + outputElements(element->childElements(), true); + + formatEnd(element, buf); + outputString(buf); + + element = element->previousElement(); + } +} + +void QTestBasicStreamer::outputElementAttributes(QTestElementAttribute *attribute) const +{ + char buf[1024]; + while(attribute){ + formatAttributes(attribute, buf); + outputString(buf); + attribute = attribute->nextElement(); + } +} + +void QTestBasicStreamer::outputString(const char *msg) const +{ + QTEST_ASSERT(QTest::stream); + + ::fputs(msg, QTest::stream); + ::fflush(QTest::stream); +} + +void QTestBasicStreamer::startStreaming() +{ + QTEST_ASSERT(!QTest::stream); + + const char *out = QTestLog::outputFileName(); + if (!out) { + QTest::stream = stdout; + return; + } + #if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_OS_WINCE) + if (::fopen_s(&QTest::stream, out, "wt")) { + #else + QTest::stream = ::fopen(out, "wt"); + if (!QTest::stream) { + #endif + printf("Unable to open file for logging: %s", out); + ::exit(1); + } +} + +bool QTestBasicStreamer::isTtyOutput() +{ + QTEST_ASSERT(QTest::stream); + +#if defined(Q_OS_WIN) || defined(Q_OS_INTEGRITY) + return true; +#else + static bool ttyoutput = isatty(fileno(QTest::stream)); + return ttyoutput; +#endif +} + +void QTestBasicStreamer::stopStreaming() +{ + QTEST_ASSERT(QTest::stream); + if (QTest::stream != stdout) + fclose(QTest::stream); + + QTest::stream = 0; +} + +void QTestBasicStreamer::setLogger(const QTestLogger *tstLogger) +{ + testLogger = tstLogger; +} + +const QTestLogger *QTestBasicStreamer::logger() const +{ + return testLogger; +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestbasicstreamer.h b/src/testlib/qtestbasicstreamer.h new file mode 100644 index 0000000..cfd6b94 --- /dev/null +++ b/src/testlib/qtestbasicstreamer.h @@ -0,0 +1,43 @@ +#ifndef QTESTBASICSTREAMER_H +#define QTESTBASICSTREAMER_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +class QTestElement; +class QTestElementAttribute; +class QTestLogger; + +class QTestBasicStreamer +{ + public: + QTestBasicStreamer(); + virtual ~QTestBasicStreamer(); + + virtual void output(QTestElement *element) const; + + void outputString(const char *msg) const; + bool isTtyOutput(); + void startStreaming(); + void stopStreaming(); + + void setLogger(const QTestLogger *tstLogger); + const QTestLogger *logger() const; + + protected: + virtual void formatStart(const QTestElement *element = 0, char *formatted = 0) const; + virtual void formatEnd(const QTestElement *element = 0, char *formatted = 0) const; + virtual void formatBeforeAttributes(const QTestElement *element = 0, char *formatted = 0) const; + virtual void formatAfterAttributes(const QTestElement *element = 0, char *formatted = 0) const; + virtual void formatAttributes(const QTestElementAttribute *attribute = 0, char *formatted = 0) const; + virtual void outputElements(QTestElement *element, bool isChildElement = false) const; + virtual void outputElementAttributes(QTestElementAttribute *attribute) const; + + private: + const QTestLogger *testLogger; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index b5200dc..936b936 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -818,8 +818,10 @@ static void qParseArgs(int argc, char *argv[]) const char *testOptions = " options:\n" " -functions : Returns a list of current testfunctions\n" + " -xunitxml : Outputs results as XML XUnit document\n" " -xml : Outputs results as XML document\n" " -lightxml : Outputs results as stream of XML tags\n" + " -flush : Flushes the resutls\n" " -o filename: Writes all output into a file\n" " -silent : Only outputs warnings and failures\n" " -v1 : Print enter messages for each testfunction\n" @@ -845,7 +847,7 @@ static void qParseArgs(int argc, char *argv[]) " -median n : Sets the number of median iterations.\n" " -vb : Print out verbose benchmarking information.\n" #ifndef QT_NO_PROCESS -// Will be enabled when tools are integrated. +// Will be enabled when tools are integrated. // " -chart : Runs the chart generator after the test. No output is printed to the console\n" #endif "\n" @@ -861,10 +863,14 @@ static void qParseArgs(int argc, char *argv[]) } else if (strcmp(argv[i], "-functions") == 0) { qPrintTestSlots(); exit(0); + } else if(strcmp(argv[i], "-xunitxml") == 0){ + QTestLog::setLogMode(QTestLog::XunitXML); } else if (strcmp(argv[i], "-xml") == 0) { QTestLog::setLogMode(QTestLog::XML); } else if (strcmp(argv[i], "-lightxml") == 0) { QTestLog::setLogMode(QTestLog::LightXML); + }else if(strcmp(argv[i], "-flush") == 0){ + QTestLog::setFlushMode(QTestLog::FLushOn); } else if (strcmp(argv[i], "-silent") == 0) { QTestLog::setVerboseLevel(-1); } else if (strcmp(argv[i], "-v1") == 0) { @@ -1006,7 +1012,7 @@ QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container) if (count == 1) return container.at(0); - + QList<QBenchmarkResult> containerCopy = container; qSort(containerCopy); @@ -1056,7 +1062,7 @@ static void qInvokeTestMethodDataEntry(char *slot) QTestResult::currentDataTag() ? QTestResult::currentDataTag() : ""); - invokeOk = QMetaObject::invokeMethod(QTest::currentTestObject, slot, + invokeOk = QMetaObject::invokeMethod(QTest::currentTestObject, slot, Qt::DirectConnection); if (!invokeOk) QTestResult::addFailure("Unable to execute slot", __FILE__, __LINE__); @@ -1077,7 +1083,7 @@ static void qInvokeTestMethodDataEntry(char *slot) if (i > -1) // iteration -1 is the warmup iteration. results.append(QBenchmarkTestMethodData::current->result); - if (QBenchmarkTestMethodData::current->isBenchmark() && + if (QBenchmarkTestMethodData::current->isBenchmark() && QBenchmarkGlobalData::current->verboseOutput) { if (i == -1) { qDebug() << "warmup stage result :" << QBenchmarkTestMethodData::current->result.value; @@ -1208,13 +1214,13 @@ void *fetchData(QTestData *data, const char *tagName, int typeId) /*! \fn char* QTest::toHexRepresentation(const char *ba, int length) - + Returns a pointer to a string that is the string \a ba represented as a space-separated sequence of hex characters. If the input is considered too long, it is truncated. A trucation is indicated in the returned string as an ellipsis at the end. - \a length is the length of the string \a ba. + \a length is the length of the string \a ba. */ char *toHexRepresentation(const char *ba, int length) { @@ -1273,56 +1279,56 @@ char *toHexRepresentation(const char *ba, int length) return result; } -static void qInvokeTestMethods(QObject *testObject) -{ - const QMetaObject *metaObject = testObject->metaObject(); - QTEST_ASSERT(metaObject); - - QTestLog::startLogging(); - - QTestResult::setCurrentTestFunction("initTestCase"); - QTestResult::setCurrentTestLocation(QTestResult::DataFunc); - QTestTable::globalTestTable(); - QMetaObject::invokeMethod(testObject, "initTestCase_data", Qt::DirectConnection); - - if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) { - QTestResult::setCurrentTestLocation(QTestResult::InitFunc); - QMetaObject::invokeMethod(testObject, "initTestCase"); - - // finishedCurrentTestFunction() resets QTestResult::testFailed(), so use a local copy. - const bool previousFailed = QTestResult::testFailed(); - QTestResult::finishedCurrentTestFunction(); - - if(!QTestResult::skipCurrentTest() && !previousFailed) { - - if (lastTestFuncIdx >= 0) { - for (int i = 0; i <= lastTestFuncIdx; ++i) { - if (!qInvokeTestMethod(metaObject->method(testFuncs[i].function).signature(), - testFuncs[i].data)) - break; - } - } else { - int methodCount = metaObject->methodCount(); - for (int i = 0; i < methodCount; ++i) { - QMetaMethod slotMethod = metaObject->method(i); - if (!isValidSlot(slotMethod)) - continue; - if (!qInvokeTestMethod(slotMethod.signature())) - break; - } - } - } - - QTestResult::setSkipCurrentTest(false); - QTestResult::setCurrentTestFunction("cleanupTestCase"); - QMetaObject::invokeMethod(testObject, "cleanupTestCase"); - } - QTestResult::finishedCurrentTestFunction(); - QTestResult::setCurrentTestFunction(0); - QTestTable::clearGlobalTestTable(); - - QTestLog::stopLogging(); -} +static void qInvokeTestMethods(QObject *testObject) +{ + const QMetaObject *metaObject = testObject->metaObject(); + QTEST_ASSERT(metaObject); + + QTestLog::startLogging(); + + QTestResult::setCurrentTestFunction("initTestCase"); + QTestResult::setCurrentTestLocation(QTestResult::DataFunc); + QTestTable::globalTestTable(); + QMetaObject::invokeMethod(testObject, "initTestCase_data", Qt::DirectConnection); + + if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) { + QTestResult::setCurrentTestLocation(QTestResult::InitFunc); + QMetaObject::invokeMethod(testObject, "initTestCase"); + + // finishedCurrentTestFunction() resets QTestResult::testFailed(), so use a local copy. + const bool previousFailed = QTestResult::testFailed(); + QTestResult::finishedCurrentTestFunction(); + + if(!QTestResult::skipCurrentTest() && !previousFailed) { + + if (lastTestFuncIdx >= 0) { + for (int i = 0; i <= lastTestFuncIdx; ++i) { + if (!qInvokeTestMethod(metaObject->method(testFuncs[i].function).signature(), + testFuncs[i].data)) + break; + } + } else { + int methodCount = metaObject->methodCount(); + for (int i = 0; i < methodCount; ++i) { + QMetaMethod slotMethod = metaObject->method(i); + if (!isValidSlot(slotMethod)) + continue; + if (!qInvokeTestMethod(slotMethod.signature())) + break; + } + } + } + + QTestResult::setSkipCurrentTest(false); + QTestResult::setCurrentTestFunction("cleanupTestCase"); + QMetaObject::invokeMethod(testObject, "cleanupTestCase"); + } + QTestResult::finishedCurrentTestFunction(); + QTestResult::setCurrentTestFunction(0); + QTestTable::clearGlobalTestTable(); + + QTestLog::stopLogging(); +} } // namespace diff --git a/src/testlib/qtestcoreelement.h b/src/testlib/qtestcoreelement.h new file mode 100644 index 0000000..ea05c19 --- /dev/null +++ b/src/testlib/qtestcoreelement.h @@ -0,0 +1,124 @@ +#ifndef QTESTCOREELEMENT_H +#define QTESTCOREELEMENT_H + +#include "qtestcorelist.h" +#include "qtestelementattribute.h" + +QT_BEGIN_NAMESPACE + +template <class ElementType> +class QTestCoreElement: public QTestCoreList<ElementType> +{ + public: + QTestCoreElement( int type = -1 ); + virtual ~QTestCoreElement(); + + void addAttribute(const QTest::AttributeIndex index, const char *value); + QTestElementAttribute *attributes() const; + const char *attributeValue(QTest::AttributeIndex index) const; + const char *attributeName(QTest::AttributeIndex index) const; + const QTestElementAttribute *attribute(QTest::AttributeIndex index) const; + + const char *elementName() const; + QTest::LogElementType elementType() const; + + private: + QTestElementAttribute *listOfAttributes; + QTest::LogElementType type; +}; + +template<class ElementType> +QTestCoreElement<ElementType>::QTestCoreElement(int t) +:listOfAttributes(0), type((QTest::LogElementType)t) +{ +} + +template<class ElementType> +QTestCoreElement<ElementType>::~QTestCoreElement() +{ + delete listOfAttributes; +} + +template <class ElementType> +void QTestCoreElement<ElementType>::addAttribute(const QTest::AttributeIndex attributeIndex, const char *value) +{ + if(attributeIndex == -1) + return; + + if (attribute(attributeIndex)) + return; + + QTestElementAttribute *attribute = new QTestElementAttribute; + attribute->setPair(attributeIndex, value); + attribute->addToList(&listOfAttributes); +} + +template <class ElementType> +QTestElementAttribute *QTestCoreElement<ElementType>::attributes() const +{ + return listOfAttributes; +} + +template <class ElementType> +const char *QTestCoreElement<ElementType>::attributeValue(QTest::AttributeIndex index) const +{ + const QTestElementAttribute *attrb = attribute(index); + if(attrb) + return attrb->value(); + + return 0; +} + +template <class ElementType> +const char *QTestCoreElement<ElementType>::attributeName(QTest::AttributeIndex index) const +{ + const QTestElementAttribute *attrb = attribute(index); + if(attrb) + return attrb->name(); + + return 0; +} + +template <class ElementType> +const char *QTestCoreElement<ElementType>::elementName() const +{ + const char *xmlElementNames[] = + { + "property", + "properties", + "failure", + "error", + "testcase", + "testsuite", + "benchmark" + }; + + if(type != QTest::LET_Undefined) + return xmlElementNames[type]; + + return 0; +} + +template <class ElementType> +QTest::LogElementType QTestCoreElement<ElementType>::elementType() const +{ + return type; +} + +template <class ElementType> +const QTestElementAttribute *QTestCoreElement<ElementType>::attribute(QTest::AttributeIndex index) const +{ + QTestElementAttribute *iterator = listOfAttributes; + while(iterator){ + if(iterator->index() == index) + return iterator; + + iterator = iterator->nextElement(); + } + + return 0; +} + +QT_END_NAMESPACE + +#endif diff --git a/src/testlib/qtestcorelist.h b/src/testlib/qtestcorelist.h new file mode 100644 index 0000000..8e008a4 --- /dev/null +++ b/src/testlib/qtestcorelist.h @@ -0,0 +1,89 @@ +#ifndef QTESTCORELIST_H +#define QTESTCORELIST_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +template <class T> +class QTestCoreList +{ + public: + QTestCoreList(); + virtual ~QTestCoreList(); + + void addToList(T **list); + T *nextElement(); + T *previousElement(); + int count(T *list); + int count(); + + private: + T *next; + T *prev; +}; + +template <class T> +QTestCoreList<T>::QTestCoreList() +:next(0) +,prev(0) +{ +} + +template <class T> +QTestCoreList<T>::~QTestCoreList() +{ + if (prev) { + prev->next = 0; + } + delete prev; + + if (next) { + next->prev = 0; + } + 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; +} + +template <class T> +int QTestCoreList<T>::count() +{ + int numOfElements = 0; + T *it = next; + + while(it){ + ++numOfElements; + it = it->nextElement(); + } + + return numOfElements; +} + +QT_END_NAMESPACE + +#endif diff --git a/src/testlib/qtestelement.cpp b/src/testlib/qtestelement.cpp new file mode 100644 index 0000000..55341d4 --- /dev/null +++ b/src/testlib/qtestelement.cpp @@ -0,0 +1,47 @@ +#include "qtestelement.h" + +QT_BEGIN_NAMESPACE + +QTestElement::QTestElement(int type) + :QTestCoreElement<QTestElement>(type), + listOfChildren(0), + parent(0) +{ +} + +QTestElement::~QTestElement() +{ + delete listOfChildren; +} + +bool QTestElement::addLogElement(QTestElement *element) +{ + if(!element) + return false; + + if(element->elementType() != QTest::LET_Undefined){ + element->addToList(&listOfChildren); + element->setParent(this); + return true; + } + + return false; +} + +QTestElement *QTestElement::childElements() const +{ + return listOfChildren; +} + +const QTestElement *QTestElement::parentElement() const +{ + return parent; +} + +void QTestElement::setParent(const QTestElement *p) +{ + parent = p; +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestelement.h b/src/testlib/qtestelement.h new file mode 100644 index 0000000..f5d7466 --- /dev/null +++ b/src/testlib/qtestelement.h @@ -0,0 +1,28 @@ +#ifndef QTESTELEMENT_H +#define QTESTELEMENT_H + +#include "qtestcoreelement.h" + +QT_BEGIN_NAMESPACE + +class QTestElement: public QTestCoreElement<QTestElement> +{ + public: + QTestElement(int type = -1); + ~QTestElement(); + + bool addLogElement(QTestElement *element); + QTestElement *childElements() const; + + const QTestElement *parentElement() const; + void setParent(const QTestElement *p); + + private: + QTestElement *listOfChildren; + const QTestElement * parent; + +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/testlib/qtestelementattribute.cpp b/src/testlib/qtestelementattribute.cpp new file mode 100644 index 0000000..64f9da5 --- /dev/null +++ b/src/testlib/qtestelementattribute.cpp @@ -0,0 +1,76 @@ +#include "qtestelementattribute.h" +#include <QtCore/qbytearray.h> +#include <string.h> +#include <stdlib.h> + +QT_BEGIN_NAMESPACE + +QTestElementAttribute::QTestElementAttribute() + :attributeValue(0), + attributeIndex(QTest::AI_Undefined) +{ +} + +QTestElementAttribute::~QTestElementAttribute() +{ + delete[] attributeValue; +} + +const char *QTestElementAttribute::value() const +{ + return attributeValue; +} + +const char *QTestElementAttribute::name() const +{ + const char *AttributeNames[] = + { + "name", + "result", + "tests", + "failures", + "errors", + "type", + "description", + "value", + "qtestversion", + "qtversion", + "file", + "line", + "metric", + "tag", + "value", + "iterations" + }; + + if(attributeIndex != QTest::AI_Undefined) + return AttributeNames[attributeIndex]; + + return 0; +} + +QTest::AttributeIndex QTestElementAttribute::index() const +{ + return attributeIndex; +} + +bool QTestElementAttribute::isNull() const +{ + return attributeIndex == QTest::AI_Undefined; +} + +bool QTestElementAttribute::setPair(QTest::AttributeIndex index, const char *value) +{ + if(!value) + return false; + + delete[] attributeValue; + + attributeIndex = index; + attributeValue = qstrdup(value); + + return (attributeValue!=0) ? true:false; +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestelementattribute.h b/src/testlib/qtestelementattribute.h new file mode 100644 index 0000000..2e23cd9 --- /dev/null +++ b/src/testlib/qtestelementattribute.h @@ -0,0 +1,63 @@ +#ifndef QTESTELEMENTATTRIBUTE_H +#define QTESTELEMENTATTRIBUTE_H + +#include "qtestcorelist.h" + +QT_BEGIN_NAMESPACE + +namespace QTest { + + enum AttributeIndex + { + AI_Undefined = -1, + AI_Name = 0, + AI_Result = 1, + AI_Tests = 2, + AI_Failures = 3, + AI_Errors = 4, + AI_Type = 5, + AI_Description = 6, + AI_PropertyValue = 7, + AI_QTestVersion = 8, + AI_QtVersion = 9, + AI_File = 10, + AI_Line = 11, + AI_Metric = 12, + AI_Tag = 13, + AI_Value = 14, + AI_Iterations = 15 + }; + + enum LogElementType + { + LET_Undefined = -1, + LET_Property = 0, + LET_Properties = 1, + LET_Failure = 2, + LET_Error = 3, + LET_TestCase = 4, + LET_TestSuite = 5, + LET_Benchmark = 6 + }; +} + +class QTestElementAttribute: public QTestCoreList<QTestElementAttribute> +{ + public: + QTestElementAttribute(); + ~QTestElementAttribute(); + + const char *value() const; + const char *name() const; + QTest::AttributeIndex index() const; + bool isNull() const; + bool setPair(QTest::AttributeIndex attributeIndex, const char *value); + + private: + char *attributeValue; + QTest::AttributeIndex attributeIndex; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/testlib/qtestfilelogger.cpp b/src/testlib/qtestfilelogger.cpp new file mode 100644 index 0000000..f753b83 --- /dev/null +++ b/src/testlib/qtestfilelogger.cpp @@ -0,0 +1,54 @@ +#include "qtestfilelogger.h" +#include "qtestassert.h" +#include "QtTest/private/qtestlog_p.h" +#include "QtTest/private/qtestresult_p.h" + +#include <stdlib.h> +#include <stdio.h> + +QT_BEGIN_NAMESPACE + +namespace QTest +{ + static FILE *stream = 0; +} + +QTestFileLogger::QTestFileLogger() +{ +} + +QTestFileLogger::~QTestFileLogger() +{ + if(QTest::stream) + fclose(QTest::stream); + + QTest::stream = 0; +} + +void QTestFileLogger::init() +{ + char filename[100]; + QTest::qt_snprintf(filename, sizeof(filename), "%s.log", + QTestResult::currentTestObjectName()); + + #if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_OS_WINCE) + if (::fopen_s(&QTest::stream, filename, "wt")) { + #else + QTest::stream = ::fopen(filename, "wt"); + if (!QTest::stream) { + #endif + printf("Unable to open file for simple logging: %s", filename); + ::exit(1); + } +} + +void QTestFileLogger::flush(const char *msg) +{ + QTEST_ASSERT(QTest::stream); + + ::fputs(msg, QTest::stream); + ::fflush(QTest::stream); +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestfilelogger.h b/src/testlib/qtestfilelogger.h new file mode 100644 index 0000000..4dca090 --- /dev/null +++ b/src/testlib/qtestfilelogger.h @@ -0,0 +1,20 @@ +#ifndef QTESTFILELOGGER_H +#define QTESTFILELOGGER_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +class QTestFileLogger +{ + public: + QTestFileLogger(); + ~QTestFileLogger(); + + void init(); + void flush(const char *msg); +}; + +QT_END_NAMESPACE + +#endif // QTESTFILELOGGER_H diff --git a/src/testlib/qtestlightxmlstreamer.cpp b/src/testlib/qtestlightxmlstreamer.cpp new file mode 100644 index 0000000..73b33ef --- /dev/null +++ b/src/testlib/qtestlightxmlstreamer.cpp @@ -0,0 +1,144 @@ +#include "qtestlightxmlstreamer.h" +#include "qtestelement.h" +#include "qtestelementattribute.h" + +#include "QtTest/private/qtestlog_p.h" +#include "QtTest/private/qtestresult_p.h" +#include "QtTest/private/qxmltestlogger_p.h" + +#include <string.h> + +QT_BEGIN_NAMESPACE + +QTestLightXmlStreamer::QTestLightXmlStreamer() + :QTestBasicStreamer() +{ +} + +QTestLightXmlStreamer::~QTestLightXmlStreamer() +{} + +void QTestLightXmlStreamer::formatStart(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted) + return; + + switch(element->elementType()){ + case QTest::LET_TestCase: { + char quotedTf[950]; + QXmlTestLogger::xmlQuote(quotedTf, element->attributeValue(QTest::AI_Name), + sizeof(quotedTf)); + + QTest::qt_snprintf(formatted, 1024, "<TestFunction name=\"%s\">\n", quotedTf); + break; + } + case QTest::LET_Failure: { + char cdataDesc[900]; + QXmlTestLogger::xmlCdata(cdataDesc, element->attributeValue(QTest::AI_Description), + sizeof(cdataDesc)); + + QTest::qt_snprintf(formatted, 1024, " <Description><![CDATA[%s]]></Description>\n", + cdataDesc); + break; + } + case QTest::LET_Error: { + // assuming type and attribute names don't need quoting + char quotedFile[128]; + char cdataDesc[700]; + QXmlTestLogger::xmlQuote(quotedFile, element->attributeValue(QTest::AI_File), + sizeof(quotedFile)); + QXmlTestLogger::xmlCdata(cdataDesc, element->attributeValue(QTest::AI_Description), + sizeof(cdataDesc)); + + QTest::qt_snprintf(formatted, 1024, "<Message type=\"%s\" %s=\"%s\" %s=\"%s\">\n <Description><![CDATA[%s]]></Description>\n</Message>\n", + element->attributeValue(QTest::AI_Type), + element->attributeName(QTest::AI_File), + quotedFile, + element->attributeName(QTest::AI_Line), + element->attributeValue(QTest::AI_Line), + cdataDesc); + break; + } + case QTest::LET_Benchmark: { + // assuming value and iterations don't need quoting + char quotedMetric[256]; + char quotedTag[256]; + QXmlTestLogger::xmlQuote(quotedMetric, element->attributeValue(QTest::AI_Metric), + sizeof(quotedMetric)); + QXmlTestLogger::xmlQuote(quotedTag, element->attributeValue(QTest::AI_Tag), + sizeof(quotedTag)); + + QTest::qt_snprintf(formatted, 1024, "<BenchmarkResult %s=\"%s\" %s=\"%s\" %s=\"%s\" %s=\"%s\" />\n", + element->attributeName(QTest::AI_Metric), + quotedMetric, + element->attributeName(QTest::AI_Tag), + quotedTag, + element->attributeName(QTest::AI_Value), + element->attributeValue(QTest::AI_Value), + element->attributeName(QTest::AI_Iterations), + element->attributeValue(QTest::AI_Iterations) ); + break; + } + default: + QTest::qt_snprintf(formatted, 10, ""); + } +} + +void QTestLightXmlStreamer::formatEnd(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted) + return; + + if (element->elementType() == QTest::LET_TestCase) { + if( element->attribute(QTest::AI_Result) && element->childElements()) + QTest::qt_snprintf(formatted, 1024, "</Incident>\n</TestFunction>\n"); + else + QTest::qt_snprintf(formatted, 1024, "</TestFunction>\n"); + } + else + QTest::qt_snprintf(formatted, 10, ""); +} + +void QTestLightXmlStreamer::formatBeforeAttributes(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted) + return; + + if (element->elementType() == QTest::LET_TestCase && element->attribute(QTest::AI_Result)){ + char buf[900]; + char quotedFile[700]; + QXmlTestLogger::xmlQuote(quotedFile, element->attributeValue(QTest::AI_File), + sizeof(quotedFile)); + + QTest::qt_snprintf(buf, sizeof(buf), "%s=\"%s\" %s=\"%s\"", + element->attributeName(QTest::AI_File), + quotedFile, + element->attributeName(QTest::AI_Line), + element->attributeValue(QTest::AI_Line)); + + if( !element->childElements() ) + QTest::qt_snprintf(formatted, 1024, "<Incident type=\"%s\" %s/>\n", + element->attributeValue(QTest::AI_Result), buf); + else + QTest::qt_snprintf(formatted, 1024, "<Incident type=\"%s\" %s>\n", + element->attributeValue(QTest::AI_Result), buf); + }else{ + QTest::qt_snprintf(formatted, 10, ""); + } +} + +void QTestLightXmlStreamer::output(QTestElement *element) const +{ + char buf[1024]; + QTest::qt_snprintf(buf, sizeof(buf), "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", + qVersion(), QTEST_VERSION_STR ); + outputString(buf); + + QTest::qt_snprintf(buf, sizeof(buf), "</Environment>\n"); + outputString(buf); + + QTestBasicStreamer::output(element); +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestlightxmlstreamer.h b/src/testlib/qtestlightxmlstreamer.h new file mode 100644 index 0000000..872eed2 --- /dev/null +++ b/src/testlib/qtestlightxmlstreamer.h @@ -0,0 +1,25 @@ +#ifndef QTESTLIGHTXMLSTREAMER_H +#define QTESTLIGHTXMLSTREAMER_H + +#include "qtestbasicstreamer.h" + +QT_BEGIN_NAMESPACE + +class QTestElement; +class QTestElementAttribute; + +class QTestLightXmlStreamer: public QTestBasicStreamer +{ + public: + QTestLightXmlStreamer(); + ~QTestLightXmlStreamer(); + + void formatStart(const QTestElement *element = 0, char *formatted = 0) const; + void formatEnd(const QTestElement *element = 0, char *formatted = 0) const; + void formatBeforeAttributes(const QTestElement *element = 0, char *formatted = 0) const; + void output(QTestElement *element) const; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index aa56e6c..bcb1c1b 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -46,7 +46,6 @@ #include "QtTest/private/qabstracttestlogger_p.h" #include "QtTest/private/qplaintestlogger_p.h" #include "QtTest/private/qxmltestlogger_p.h" - #include <QtCore/qatomic.h> #include <QtCore/qbytearray.h> @@ -54,6 +53,9 @@ #include <string.h> #include <limits.h> + +#include "qtestlogger_p.h" + QT_BEGIN_NAMESPACE namespace QTest { @@ -83,6 +85,7 @@ namespace QTest { static IgnoreResultList *ignoreResultList = 0; static QTestLog::LogMode logMode = QTestLog::Plain; + static QTestLog::FlushMode flushMode = QTestLog::NoFlush; static int verbosity = 0; static int maxWarnings = 2002; @@ -270,15 +273,24 @@ void QTestLog::startLogging() QTEST_ASSERT(!QTest::testLogger); switch (QTest::logMode) { - case QTestLog::Plain: - QTest::testLogger = new QPlainTestLogger(); - break; - case QTestLog::XML: - QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Complete); - break; - case QTestLog::LightXML: - QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Light); - } + case QTestLog::Plain: + QTest::testLogger = new QPlainTestLogger; + break; + case QTestLog::XML:{ + if(QTest::flushMode == QTestLog::FLushOn) + QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Complete); + else + QTest::testLogger = new QTestLogger(QTestLogger::TLF_XML); + break; + }case QTestLog::LightXML:{ + if(QTest::flushMode == QTestLog::FLushOn) + QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Light); + else + QTest::testLogger = new QTestLogger(QTestLogger::TLF_LightXml); + break; + }case QTestLog::XunitXML: + QTest::testLogger = new QTestLogger(QTestLogger::TLF_XunitXml); + } QTest::testLogger->startLogging(); @@ -361,4 +373,9 @@ void QTestLog::setMaxWarnings(int m) QTest::maxWarnings = m <= 0 ? INT_MAX : m + 2; } +void QTestLog::setFlushMode(FlushMode mode) +{ + QTest::flushMode = mode; +} + QT_END_NAMESPACE diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index fa49a38..0d761e3 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -62,7 +62,8 @@ class QBenchmarkResult; class QTestLog { public: - enum LogMode { Plain = 0, XML, LightXML }; + enum LogMode { Plain = 0, XML, LightXML, XunitXML }; + enum FlushMode { NoFlush = 0, FLushOn }; static void enterTestFunction(const char* function); static void leaveTestFunction(); @@ -95,6 +96,8 @@ public: static void setMaxWarnings(int max); + static void setFlushMode(FlushMode mode); + private: QTestLog(); ~QTestLog(); diff --git a/src/testlib/qtestlogger.cpp b/src/testlib/qtestlogger.cpp new file mode 100644 index 0000000..c053c30 --- /dev/null +++ b/src/testlib/qtestlogger.cpp @@ -0,0 +1,339 @@ +#include "qtestlogger_p.h" +#include "qtestelement.h" +#include "qtestxunitstreamer.h" +#include "qtestxmlstreamer.h" +#include "qtestlightxmlstreamer.h" +#include "qtestfilelogger.h" + +#include "QtTest/qtestcase.h" +#include "QtTest/private/qtestresult_p.h" +#include "QtTest/private/qbenchmark_p.h" + +#include <string.h> + +QT_BEGIN_NAMESPACE + +QTestLogger::QTestLogger(int fm) + :listOfTestcases(0), currentLogElement(0), + logFormatter(0), format( (TestLoggerFormat)fm ), filelogger(new QTestFileLogger), + testCounter(0), passCounter(0), + failureCounter(0), errorCounter(0), + warningCounter(0), skipCounter(0), + systemCounter(0), qdebugCounter(0), + qwarnCounter(0), qfatalCounter(0), + infoCounter(0) +{ +} + +QTestLogger::~QTestLogger() +{ + if(format == TLF_XunitXml) + delete currentLogElement; + else + delete listOfTestcases; + + delete logFormatter; + delete filelogger; +} + +void QTestLogger::startLogging() +{ + switch(format){ + case TLF_LightXml:{ + logFormatter = new QTestLightXmlStreamer; + filelogger->init(); + break; + }case TLF_XML:{ + logFormatter = new QTestXmlStreamer; + filelogger->init(); + break; + }case TLF_XunitXml:{ + logFormatter = new QTestXunitStreamer; + filelogger->init(); + break; + } + } + + logFormatter->setLogger(this); + logFormatter->startStreaming(); +} + +void QTestLogger::stopLogging() +{ + QTestElement *iterator = listOfTestcases; + + if(format == TLF_XunitXml ){ + char buf[10]; + + currentLogElement = new QTestElement(QTest::LET_TestSuite); + currentLogElement->addAttribute(QTest::AI_Name, QTestResult::currentTestObjectName()); + + QTest::qt_snprintf(buf, sizeof(buf), "%i", testCounter); + currentLogElement->addAttribute(QTest::AI_Tests, buf); + + QTest::qt_snprintf(buf, sizeof(buf), "%i", failureCounter); + currentLogElement->addAttribute(QTest::AI_Failures, buf); + + QTest::qt_snprintf(buf, sizeof(buf), "%i", errorCounter); + currentLogElement->addAttribute(QTest::AI_Errors, buf); + + QTestElement *property; + QTestElement *properties = new QTestElement(QTest::LET_Properties); + + property = new QTestElement(QTest::LET_Property); + property->addAttribute(QTest::AI_Name, "QTestVersion"); + property->addAttribute(QTest::AI_PropertyValue, QTEST_VERSION_STR); + properties->addLogElement(property); + + property = new QTestElement(QTest::LET_Property); + property->addAttribute(QTest::AI_Name, "QtVersion"); + property->addAttribute(QTest::AI_PropertyValue, qVersion()); + properties->addLogElement(property); + + currentLogElement->addLogElement(properties); + + currentLogElement->addLogElement(iterator); + + /* For correct indenting, make sure every testcase knows its parent */ + QTestElement* testcase = iterator; + while (testcase) { + testcase->setParent(currentLogElement); + testcase = testcase->nextElement(); + } + + QTestElement *it = currentLogElement; + logFormatter->output(it); + }else{ + logFormatter->output(iterator); + } + + logFormatter->stopStreaming(); +} + +void QTestLogger::enterTestFunction(const char *function) +{ + char buf[1024]; + QTest::qt_snprintf(buf, sizeof(buf), "Entered test-function: %s\n", function); + filelogger->flush(buf); + + currentLogElement = new QTestElement(QTest::LET_TestCase); + currentLogElement->addAttribute(QTest::AI_Name, function); + currentLogElement->addToList(&listOfTestcases); + + ++testCounter; +} + +void QTestLogger::leaveTestFunction() +{ +} + +void QTestLogger::addIncident(IncidentTypes type, const char *description, + const char *file, int line) +{ + const char *typeBuf = 0; + char buf[100]; + + switch (type) { + case QAbstractTestLogger::XPass: + ++passCounter; + typeBuf = "xpass"; + break; + case QAbstractTestLogger::Pass: + ++passCounter; + typeBuf = "pass"; + break; + case QAbstractTestLogger::XFail: + ++failureCounter; + typeBuf = "xfail"; + break; + case QAbstractTestLogger::Fail: + ++failureCounter; + typeBuf = "fail"; + break; + default: + typeBuf = "??????"; + break; + } + + if (type == QAbstractTestLogger::Fail || type == QAbstractTestLogger::XFail) { + QTestElement *failureElement = new QTestElement(QTest::LET_Failure); + failureElement->addAttribute(QTest::AI_Result, typeBuf); + failureElement->addAttribute(QTest::AI_File, file); + QTest::qt_snprintf(buf, sizeof(buf), "%i", line); + failureElement->addAttribute(QTest::AI_Line, buf); + failureElement->addAttribute(QTest::AI_Description, description); + const char* tag = QTestResult::currentDataTag(); + if (tag) { + failureElement->addAttribute(QTest::AI_Tag, tag); + } + currentLogElement->addLogElement(failureElement); + } + + /* + Only one result can be shown for the whole testfunction. + Check if we currently have a result, and if so, overwrite it + iff the new result is worse. + */ + QTestElementAttribute* resultAttr = + const_cast<QTestElementAttribute*>(currentLogElement->attribute(QTest::AI_Result)); + if (resultAttr) { + const char* oldResult = resultAttr->value(); + bool overwrite = false; + if (!strcmp(oldResult, "pass")) { + overwrite = true; + } + else if (!strcmp(oldResult, "xpass")) { + overwrite = (type == QAbstractTestLogger::XFail || type == QAbstractTestLogger::Fail); + } + else if (!strcmp(oldResult, "xfail")) { + overwrite = (type == QAbstractTestLogger::Fail); + } + if (overwrite) { + resultAttr->setPair(QTest::AI_Result, typeBuf); + } + } + else { + currentLogElement->addAttribute(QTest::AI_Result, typeBuf); + } + + if(file) + currentLogElement->addAttribute(QTest::AI_File, file); + else + currentLogElement->addAttribute(QTest::AI_File, ""); + + QTest::qt_snprintf(buf, sizeof(buf), "%i", line); + currentLogElement->addAttribute(QTest::AI_Line, buf); +} + +void QTestLogger::addBenchmarkResult(const QBenchmarkResult &result) +{ + QTestElement *benchmarkElement = new QTestElement(QTest::LET_Benchmark); +// printf("element %i", benchmarkElement->elementType()); + + benchmarkElement->addAttribute(QTest::AI_Metric, QBenchmarkGlobalData::current->measurer->metricText().toAscii().data()); + benchmarkElement->addAttribute(QTest::AI_Tag, result.context.tag.toAscii().data()); + benchmarkElement->addAttribute(QTest::AI_Value, QByteArray::number(result.value).constData()); + + char buf[100]; + QTest::qt_snprintf(buf, sizeof(buf), "%i", result.iterations); + benchmarkElement->addAttribute(QTest::AI_Iterations, buf); + currentLogElement->addLogElement(benchmarkElement); +} + +void QTestLogger::addMessage(MessageTypes type, const char *message, const char *file, int line) +{ + QTestElement *errorElement = new QTestElement(QTest::LET_Error); + const char *typeBuf = 0; + + switch (type) { + case QAbstractTestLogger::Warn: + ++warningCounter; + typeBuf = "warn"; + break; + case QAbstractTestLogger::QSystem: + ++systemCounter; + typeBuf = "system"; + break; + case QAbstractTestLogger::QDebug: + ++qdebugCounter; + typeBuf = "qdebug"; + break; + case QAbstractTestLogger::QWarning: + ++qwarnCounter; + typeBuf = "qwarning"; + break; + case QAbstractTestLogger::QFatal: + ++qfatalCounter; + typeBuf = "qfatal"; + break; + case QAbstractTestLogger::Skip: + ++skipCounter; + typeBuf = "skip"; + break; + case QAbstractTestLogger::Info: + ++infoCounter; + typeBuf = "info"; + break; + default: + typeBuf = "??????"; + break; + } + + errorElement->addAttribute(QTest::AI_Type, typeBuf); + errorElement->addAttribute(QTest::AI_Description, message); + + if(file) + errorElement->addAttribute(QTest::AI_File, file); + else + errorElement->addAttribute(QTest::AI_File, ""); + + char buf[100]; + QTest::qt_snprintf(buf, sizeof(buf), "%i", line); + errorElement->addAttribute(QTest::AI_Line, buf); + + currentLogElement->addLogElement(errorElement); + ++errorCounter; +} + +void QTestLogger::setLogFormat(TestLoggerFormat fm) +{ + format = fm; +} + +QTestLogger::TestLoggerFormat QTestLogger::logFormat() +{ + return format; +} + +int QTestLogger::passCount() const +{ + return passCounter; +} + +int QTestLogger::failureCount() const +{ + return failureCounter; +} + +int QTestLogger::errorCount() const +{ + return errorCounter; +} + +int QTestLogger::warningCount() const +{ + return warningCounter; +} + +int QTestLogger::skipCount() const +{ + return skipCounter; +} + +int QTestLogger::systemCount() const +{ + return systemCounter; +} + +int QTestLogger::qdebugCount() const +{ + return qdebugCounter; +} + +int QTestLogger::qwarnCount() const +{ + return qwarnCounter; +} + +int QTestLogger::qfatalCount() const +{ + return qfatalCounter; +} + +int QTestLogger::infoCount() const +{ + return infoCounter; +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestlogger_p.h b/src/testlib/qtestlogger_p.h new file mode 100644 index 0000000..3badb1d --- /dev/null +++ b/src/testlib/qtestlogger_p.h @@ -0,0 +1,74 @@ +#ifndef QTESTLOGGER_P_H +#define QTESTLOGGER_P_H + +#include <QtTest/private/qabstracttestlogger_p.h> + +QT_BEGIN_NAMESPACE + +class QTestBasicStreamer; +class QTestElement; +class QTestFileLogger; + +class QTestLogger : public QAbstractTestLogger +{ + public: + QTestLogger(int fm = 0); + ~QTestLogger(); + + enum TestLoggerFormat + { + TLF_XML = 0, + TLF_LightXml = 1, + TLF_XunitXml = 2 + }; + + void startLogging(); + void stopLogging(); + + void enterTestFunction(const char *function); + void leaveTestFunction(); + + void addIncident(IncidentTypes type, const char *description, + const char *file = 0, int line = 0); + void addBenchmarkResult(const QBenchmarkResult &result); + + void addMessage(MessageTypes type, const char *message, + const char *file = 0, int line = 0); + + void setLogFormat(TestLoggerFormat fm); + TestLoggerFormat logFormat(); + + int passCount() const; + int failureCount() const; + int errorCount() const; + int warningCount() const; + int skipCount() const; + int systemCount() const; + int qdebugCount() const; + int qwarnCount() const; + int qfatalCount() const; + int infoCount() const; + + private: + QTestElement *listOfTestcases; + QTestElement *currentLogElement; + QTestBasicStreamer *logFormatter; + TestLoggerFormat format; + QTestFileLogger *filelogger; + + int testCounter; + int passCounter; + int failureCounter; + int errorCounter; + int warningCounter; + int skipCounter; + int systemCounter; + int qdebugCounter; + int qwarnCounter; + int qfatalCounter; + int infoCounter; +}; + +QT_END_NAMESPACE + +#endif // QTESTLOGGER_P_H diff --git a/src/testlib/qtestxmlstreamer.cpp b/src/testlib/qtestxmlstreamer.cpp new file mode 100644 index 0000000..cf99b96 --- /dev/null +++ b/src/testlib/qtestxmlstreamer.cpp @@ -0,0 +1,178 @@ +#include "qtestxmlstreamer.h" +#include "qtestelement.h" +#include "qtestelementattribute.h" + +#include "QtTest/private/qtestlog_p.h" +#include "QtTest/private/qtestresult_p.h" +#include "QtTest/private/qxmltestlogger_p.h" + +#include <string.h> +#include <stdio.h> + +QT_BEGIN_NAMESPACE + +QTestXmlStreamer::QTestXmlStreamer() + :QTestBasicStreamer() +{ +} + +QTestXmlStreamer::~QTestXmlStreamer() +{} + +void QTestXmlStreamer::formatStart(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted) + return; + + switch(element->elementType()){ + case QTest::LET_TestCase: { + char quotedTf[950]; + QXmlTestLogger::xmlQuote(quotedTf, element->attributeValue(QTest::AI_Name), + sizeof(quotedTf)); + + QTest::qt_snprintf(formatted, 1024, "<TestFunction name=\"%s\">\n", quotedTf); + break; + } + case QTest::LET_Failure: { + char cdataDesc[800]; + QXmlTestLogger::xmlCdata(cdataDesc, element->attributeValue(QTest::AI_Description), + sizeof(cdataDesc)); + + char location[100]; + char quotedFile[70]; + QXmlTestLogger::xmlQuote(quotedFile, element->attributeValue(QTest::AI_File), + sizeof(quotedFile)); + + QTest::qt_snprintf(location, sizeof(location), "%s=\"%s\" %s=\"%s\"", + element->attributeName(QTest::AI_File), + quotedFile, + element->attributeName(QTest::AI_Line), + element->attributeValue(QTest::AI_Line)); + + if (element->attribute(QTest::AI_Tag)) { + char cdataTag[100]; + QXmlTestLogger::xmlCdata(cdataTag, element->attributeValue(QTest::AI_Tag), + sizeof(cdataTag)); + QTest::qt_snprintf(formatted, 1024, "<Incident type=\"%s\" %s>\n" + " <DataTag><![CDATA[%s]]></Description>\n" + " <Description><![CDATA[%s]]></Description>\n" + "</Incident>\n", element->attributeValue(QTest::AI_Result), + location, cdataTag, cdataDesc); + } + else { + QTest::qt_snprintf(formatted, 1024, "<Incident type=\"%s\" %s>\n" + " <Description><![CDATA[%s]]></Description>\n" + "</Incident>\n", element->attributeValue(QTest::AI_Result), + location, cdataDesc); + } + break; + } + case QTest::LET_Error: { + // assuming type and attribute names don't need quoting + char quotedFile[128]; + char cdataDesc[700]; + QXmlTestLogger::xmlQuote(quotedFile, element->attributeValue(QTest::AI_File), + sizeof(quotedFile)); + QXmlTestLogger::xmlCdata(cdataDesc, element->attributeValue(QTest::AI_Description), + sizeof(cdataDesc)); + + QTest::qt_snprintf(formatted, 1024, "<Message type=\"%s\" %s=\"%s\" %s=\"%s\">\n <Description><![CDATA[%s]]></Description>\n</Message>\n", + element->attributeValue(QTest::AI_Type), + element->attributeName(QTest::AI_File), + quotedFile, + element->attributeName(QTest::AI_Line), + element->attributeValue(QTest::AI_Line), + cdataDesc); + break; + } + case QTest::LET_Benchmark: { + // assuming value and iterations don't need quoting + char quotedMetric[256]; + char quotedTag[256]; + QXmlTestLogger::xmlQuote(quotedMetric, element->attributeValue(QTest::AI_Metric), + sizeof(quotedMetric)); + QXmlTestLogger::xmlQuote(quotedTag, element->attributeValue(QTest::AI_Tag), + sizeof(quotedTag)); + + QTest::qt_snprintf(formatted, 1024, "<BenchmarkResult %s=\"%s\" %s=\"%s\" %s=\"%s\" %s=\"%s\" />\n", + element->attributeName(QTest::AI_Metric), + quotedMetric, + element->attributeName(QTest::AI_Tag), + quotedTag, + element->attributeName(QTest::AI_Value), + element->attributeValue(QTest::AI_Value), + element->attributeName(QTest::AI_Iterations), + element->attributeValue(QTest::AI_Iterations) ); + break; + } + default: + QTest::qt_snprintf(formatted, 10, ""); + } +} + +void QTestXmlStreamer::formatEnd(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted) + return; + + if (element->elementType() == QTest::LET_TestCase) { + QTest::qt_snprintf(formatted, 1024, "</TestFunction>\n"); + } + else + QTest::qt_snprintf(formatted, 10, ""); +} + +void QTestXmlStreamer::formatBeforeAttributes(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted) + return; + + if (element->elementType() == QTest::LET_TestCase && element->attribute(QTest::AI_Result)){ + char buf[900]; + char quotedFile[700]; + QXmlTestLogger::xmlQuote(quotedFile, element->attributeValue(QTest::AI_File), + sizeof(quotedFile)); + + QTest::qt_snprintf(buf, sizeof(buf), "%s=\"%s\" %s=\"%s\"", + element->attributeName(QTest::AI_File), + quotedFile, + element->attributeName(QTest::AI_Line), + element->attributeValue(QTest::AI_Line)); + + if( !element->childElements() ) { + QTest::qt_snprintf(formatted, 1024, "<Incident type=\"%s\" %s/>\n", + element->attributeValue(QTest::AI_Result), buf); + } + else { + QTest::qt_snprintf(formatted, 10, ""); + } + }else{ + QTest::qt_snprintf(formatted, 10, ""); + } +} + +void QTestXmlStreamer::output(QTestElement *element) const +{ + char buf[1024]; + char quotedTc[800]; + QXmlTestLogger::xmlQuote(quotedTc, QTestResult::currentTestObjectName(), sizeof(quotedTc)); + + QTest::qt_snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<TestCase name=\"%s\">\n", + quotedTc); + outputString(buf); + + QTest::qt_snprintf(buf, sizeof(buf), "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", + qVersion(), QTEST_VERSION_STR ); + outputString(buf); + + QTest::qt_snprintf(buf, sizeof(buf), "</Environment>\n"); + outputString(buf); + + QTestBasicStreamer::output(element); + + QTest::qt_snprintf(buf, sizeof(buf), "</TestCase>\n"); + outputString(buf); +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestxmlstreamer.h b/src/testlib/qtestxmlstreamer.h new file mode 100644 index 0000000..e6858c6 --- /dev/null +++ b/src/testlib/qtestxmlstreamer.h @@ -0,0 +1,25 @@ +#ifndef QTESTXMLSTREAMER_H +#define QTESXMLSTREAMER_H + +#include "qtestbasicstreamer.h" + +QT_BEGIN_NAMESPACE + +class QTestElement; +class QTestElementAttribute; + +class QTestXmlStreamer: public QTestBasicStreamer +{ + public: + QTestXmlStreamer(); + ~QTestXmlStreamer(); + + void formatStart(const QTestElement *element = 0, char *formatted = 0) const; + void formatEnd(const QTestElement *element = 0, char *formatted = 0) const; + void formatBeforeAttributes(const QTestElement *element = 0, char *formatted = 0) const; + void output(QTestElement *element) const; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/testlib/qtestxunitstreamer.cpp b/src/testlib/qtestxunitstreamer.cpp new file mode 100644 index 0000000..2d8b7c4 --- /dev/null +++ b/src/testlib/qtestxunitstreamer.cpp @@ -0,0 +1,141 @@ +#include "qtestxunitstreamer.h" +#include "qtestelement.h" + +#include "QtTest/private/qtestlog_p.h" +#include "QtTest/private/qtestresult_p.h" +#include "QtTest/private/qxmltestlogger_p.h" + +QT_BEGIN_NAMESPACE + +QTestXunitStreamer::QTestXunitStreamer() + :QTestBasicStreamer() +{} + +QTestXunitStreamer::~QTestXunitStreamer() +{} + +void QTestXunitStreamer::indentForElement(const QTestElement* element, char* buf, int size) +{ + if (size == 0) return; + + buf[0] = 0; + + if (!element) return; + + char* endbuf = buf + size; + element = element->parentElement(); + while (element && buf+2 < endbuf) { + *(buf++) = ' '; + *(buf++) = ' '; + *buf = 0; + element = element->parentElement(); + } +} + +void QTestXunitStreamer::formatStart(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted ) + return; + + char indent[20]; + indentForElement(element, indent, sizeof(indent)); + + QTest::qt_snprintf(formatted, 1024, "%s<%s", indent, element->elementName()); +} + +void QTestXunitStreamer::formatEnd(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted ) + return; + + if(!element->childElements()){ + QTest::qt_snprintf(formatted, 10, ""); + return; + } + + char indent[20]; + indentForElement(element, indent, sizeof(indent)); + + QTest::qt_snprintf(formatted, 1024, "%s</%s>\n", indent, element->elementName()); +} + +void QTestXunitStreamer::formatAttributes(const QTestElementAttribute *attribute, char *formatted) const +{ + if(!attribute || !formatted ) + return; + + QTest::AttributeIndex attrindex = attribute->index(); + + char const* key = 0; + if (attrindex == QTest::AI_Description) + key = "message"; + else if (attrindex != QTest::AI_File && attrindex != QTest::AI_Line) + key = attribute->name(); + + if (key) { + char quotedValue[900]; + QXmlTestLogger::xmlQuote(quotedValue, attribute->value(), sizeof(quotedValue)); + QTest::qt_snprintf(formatted, 1024, " %s=\"%s\"", key, quotedValue); + } + else { + QTest::qt_snprintf(formatted, 10, ""); + } +} + +void QTestXunitStreamer::formatAfterAttributes(const QTestElement *element, char *formatted) const +{ + if(!element || !formatted ) + return; + + if(!element->childElements()) + QTest::qt_snprintf(formatted, 10, "/>\n"); + else + QTest::qt_snprintf(formatted, 10, ">\n"); +} + +void QTestXunitStreamer::output(QTestElement *element) const +{ + char buf[1024]; + QTest::qt_snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); + outputString(buf); + QTestBasicStreamer::output(element); +} + +void QTestXunitStreamer::outputElements(QTestElement *element, bool) const +{ + char buf[1024]; + bool hasChildren; + /* + Elements are in reverse order of occurrence, so start from the end and work + our way backwards. + */ + while (element && element->nextElement()) { + element = element->nextElement(); + } + while (element) { + hasChildren = element->childElements(); + + if(element->elementType() != QTest::LET_Benchmark){ + formatStart(element, buf); + outputString(buf); + + formatBeforeAttributes(element, buf); + outputString(buf); + + outputElementAttributes(element->attributes()); + + formatAfterAttributes(element, buf); + outputString(buf); + + if(hasChildren) + outputElements(element->childElements(), true); + + formatEnd(element, buf); + outputString(buf); + } + element = element->previousElement(); + } +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestxunitstreamer.h b/src/testlib/qtestxunitstreamer.h new file mode 100644 index 0000000..1ce9576 --- /dev/null +++ b/src/testlib/qtestxunitstreamer.h @@ -0,0 +1,30 @@ +#ifndef QTESTXUNITSTREAMER_H +#define QTESTXUNITSTREAMER_H + +#include "qtestbasicstreamer.h" + +QT_BEGIN_NAMESPACE + +class QTestLogger; + +class QTestXunitStreamer: public QTestBasicStreamer +{ + public: + QTestXunitStreamer(); + ~QTestXunitStreamer(); + + void formatStart(const QTestElement *element = 0, char *formatted = 0) const; + void formatEnd(const QTestElement *element = 0, char *formatted = 0) const; + void formatAfterAttributes(const QTestElement *element = 0, char *formatted = 0) const; + void formatAttributes(const QTestElementAttribute *attribute = 0, char *formatted = 0) const; + void output(QTestElement *element) const; + void outputElements(QTestElement *element, bool isChildElement = false) const; + + private: + void displayXunitXmlHeader() const; + static void indentForElement(const QTestElement* element, char* buf, int size); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp index bba98da..ec9a5d2 100644 --- a/src/testlib/qxmltestlogger.cpp +++ b/src/testlib/qxmltestlogger.cpp @@ -46,6 +46,7 @@ #include "QtTest/private/qxmltestlogger_p.h" #include "QtTest/private/qtestresult_p.h" #include "QtTest/private/qbenchmark_p.h" +#include "QtTest/qtestcase.h" QT_BEGIN_NAMESPACE @@ -90,27 +91,27 @@ namespace QTest { } -QXmlTestLogger::QXmlTestLogger(XmlMode mode ): - xmlmode(mode) +QXmlTestLogger::QXmlTestLogger(XmlMode mode ) + :xmlmode(mode) { } QXmlTestLogger::~QXmlTestLogger() { - } - void QXmlTestLogger::startLogging() { QAbstractTestLogger::startLogging(); char buf[1024]; if (xmlmode == QXmlTestLogger::Complete) { + char quotedTc[900]; + xmlQuote(quotedTc, QTestResult::currentTestObjectName(), sizeof(quotedTc)); QTest::qt_snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" - "<TestCase name=\"%s\">\n", QTestResult::currentTestObjectName()); + "<TestCase name=\"%s\">\n", quotedTc); outputString(buf); } @@ -134,7 +135,9 @@ void QXmlTestLogger::stopLogging() void QXmlTestLogger::enterTestFunction(const char *function) { char buf[1024]; - QTest::qt_snprintf(buf, sizeof(buf), "<TestFunction name=\"%s\">\n", function); + char quotedFunction[950]; + xmlQuote(quotedFunction, function, sizeof(quotedFunction)); + QTest::qt_snprintf(buf, sizeof(buf), "<TestFunction name=\"%s\">\n", quotedFunction); outputString(buf); } @@ -158,18 +161,18 @@ static const char *incidentFormatString(bool noDescription, bool noTag) return "<Incident type=\"%s\" file=\"%s\" line=\"%d\" />\n"; else return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n" - "</Incident>\n"; + " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n" + "</Incident>\n"; } else { if (noTag) return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <Description><![CDATA[%s%s%s%s]]></Description>\n" - "</Incident>\n"; + " <Description><![CDATA[%s%s%s%s]]></Description>\n" + "</Incident>\n"; else return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <DataTag><![CDATA[%s%s%s]]></DataTag>\n" - " <Description><![CDATA[%s]]></Description>\n" - "</Incident>\n"; + " <DataTag><![CDATA[%s%s%s]]></DataTag>\n" + " <Description><![CDATA[%s]]></Description>\n" + "</Incident>\n"; } } @@ -185,40 +188,51 @@ static const char *messageFormatString(bool noDescription, bool noTag) return "<Message type=\"%s\" file=\"%s\" line=\"%d\" />\n"; else return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n" - "</Message>\n"; + " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n" + "</Message>\n"; } else { if (noTag) return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <Description><![CDATA[%s%s%s%s]]></Description>\n" - "</Message>\n"; + " <Description><![CDATA[%s%s%s%s]]></Description>\n" + "</Message>\n"; else return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <DataTag><![CDATA[%s%s%s]]></DataTag>\n" - " <Description><![CDATA[%s]]></Description>\n" - "</Message>\n"; + " <DataTag><![CDATA[%s%s%s]]></DataTag>\n" + " <Description><![CDATA[%s]]></Description>\n" + "</Message>\n"; } } } // namespace void QXmlTestLogger::addIncident(IncidentTypes type, const char *description, - const char *file, int line) + const char *file, int line) { - char buf[1536]; + // buffer must be large enough to hold all quoted/cdata buffers plus the format string itself + char buf[5000]; const char *tag = QTestResult::currentDataTag(); const char *gtag = QTestResult::currentGlobalDataTag(); const char *filler = (tag && gtag) ? ":" : ""; const bool notag = QTest::isEmpty(tag) && QTest::isEmpty(gtag); + char quotedFile[1024]; + char cdataGtag[1024]; + char cdataTag[1024]; + char cdataDescription[1024]; + + xmlQuote(quotedFile, file, sizeof(quotedFile)); + xmlCdata(cdataGtag, gtag, sizeof(cdataGtag)); + xmlCdata(cdataTag, tag, sizeof(cdataTag)); + xmlCdata(cdataDescription, description, sizeof(cdataDescription)); + QTest::qt_snprintf(buf, sizeof(buf), QTest::incidentFormatString(QTest::isEmpty(description), notag), QTest::xmlIncidentType2String(type), - file ? file : "", line, - gtag ? gtag : "", + quotedFile, line, + cdataGtag, filler, - tag ? tag : "", - description ? description : ""); + cdataTag, + cdataDescription); outputString(buf); } @@ -226,39 +240,152 @@ void QXmlTestLogger::addIncident(IncidentTypes type, const char *description, void QXmlTestLogger::addBenchmarkResult(const QBenchmarkResult &result) { char buf[1536]; + char quotedMetric[64]; + char quotedTag[1024]; + + xmlQuote(quotedMetric, + QBenchmarkGlobalData::current->measurer->metricText().toAscii().constData(), + sizeof(quotedMetric)); + xmlQuote(quotedTag, result.context.tag.toAscii().constData(), sizeof(quotedTag)); + QTest::qt_snprintf( buf, sizeof(buf), QTest::benchmarkResultFormatString(), - QBenchmarkGlobalData::current->measurer->metricText().toAscii().data(), - result.context.tag.toAscii().data(), + quotedMetric, + quotedTag, QByteArray::number(result.value).constData(), //no 64-bit qt_snprintf support - result.iterations); + result.iterations); outputString(buf); } void QXmlTestLogger::addMessage(MessageTypes type, const char *message, const char *file, int line) { - char buf[1536]; - char msgbuf[1024]; + char buf[5000]; const char *tag = QTestResult::currentDataTag(); const char *gtag = QTestResult::currentGlobalDataTag(); const char *filler = (tag && gtag) ? ":" : ""; const bool notag = QTest::isEmpty(tag) && QTest::isEmpty(gtag); - QTest::qt_snprintf(msgbuf, sizeof(msgbuf), "%s", - message ? message : ""); + char quotedFile[1024]; + char cdataGtag[1024]; + char cdataTag[1024]; + char cdataDescription[1024]; + + xmlQuote(quotedFile, file, sizeof(quotedFile)); + xmlCdata(cdataGtag, gtag, sizeof(cdataGtag)); + xmlCdata(cdataTag, tag, sizeof(cdataTag)); + xmlCdata(cdataDescription, message, sizeof(cdataDescription)); QTest::qt_snprintf(buf, sizeof(buf), QTest::messageFormatString(QTest::isEmpty(message), notag), QTest::xmlMessageType2String(type), - file ? file : "", line, - gtag ? gtag : "", + quotedFile, line, + cdataGtag, filler, - tag ? tag : "", - msgbuf); + cdataTag, + cdataDescription); outputString(buf); } +/* + Copy up to n characters from the src string into dest, escaping any special + XML characters as necessary so that dest is suitable for use in an XML + quoted attribute string. +*/ +void QXmlTestLogger::xmlQuote(char* dest, char const* src, size_t n) +{ + if (n == 0) return; + + *dest = 0; + if (!src) return; + + char* end = dest + n; + + while (dest < end) { + switch (*src) { + +#define MAP_ENTITY(chr, ent) \ + case chr: \ + if (dest + sizeof(ent) < end) { \ + strcpy(dest, ent); \ + dest += sizeof(ent) - 1; \ + } \ + else { \ + *dest = 0; \ + return; \ + } \ + ++src; \ + break; + + MAP_ENTITY('>', ">"); + MAP_ENTITY('<', "<"); + MAP_ENTITY('\'', "'"); + MAP_ENTITY('"', """); + MAP_ENTITY('&', "&"); + +#undef MAP_ENTITY + + case 0: + *dest = 0; + return; + + default: + *dest = *src; + ++dest; + ++src; + break; + } + } + + // If we get here, dest was completely filled (dest == end) + *(dest-1) = 0; +} + +/* + Copy up to n characters from the src string into dest, escaping any + special strings such that dest is suitable for use in an XML CDATA section. +*/ +void QXmlTestLogger::xmlCdata(char* dest, char const* src, size_t n) +{ + if (!n) return; + + if (!src || n == 1) { + *dest = 0; + return; + } + + char const CDATA_END[] = "]]>"; + char const CDATA_END_ESCAPED[] = "]]]><![CDATA[]>"; + + char* end = dest + n; + while (dest < end) { + if (!*src) { + *dest = 0; + return; + } + + if (!strncmp(src, CDATA_END, sizeof(CDATA_END)-1)) { + if (dest + sizeof(CDATA_END_ESCAPED) < end) { + strcpy(dest, CDATA_END_ESCAPED); + src += sizeof(CDATA_END)-1; + dest += sizeof(CDATA_END_ESCAPED) - 1; + } + else { + *dest = 0; + return; + } + continue; + } + + *dest = *src; + ++src; + ++dest; + } + + // If we get here, dest was completely filled (dest == end) + *(dest-1) = 0; +} + QT_END_NAMESPACE diff --git a/src/testlib/qxmltestlogger_p.h b/src/testlib/qxmltestlogger_p.h index 3e78969..79e34ff 100644 --- a/src/testlib/qxmltestlogger_p.h +++ b/src/testlib/qxmltestlogger_p.h @@ -79,6 +79,9 @@ public: void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0); + static void xmlCdata(char* dest, char const* src, size_t n); + static void xmlQuote(char* dest, char const* src, size_t n); + private: XmlMode xmlmode; }; diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro index 90bd92d..ae4f182 100644 --- a/src/testlib/testlib.pro +++ b/src/testlib/testlib.pro @@ -1,27 +1,68 @@ -TARGET = QtTest +TARGET = QtTest QPRO_PWD = $$PWD -QT = core +QT = core INCLUDEPATH += . - -unix:!embedded { - QMAKE_PKGCONFIG_DESCRIPTION = Qt Unit Testing Library - QMAKE_PKGCONFIG_REQUIRES = QtCore -} +unix:!embedded:QMAKE_PKGCONFIG_DESCRIPTION = Qt \ + Unit \ + Testing \ + Library # Input -HEADERS = qtest_global.h qtestcase.h qtestdata.h qtesteventloop.h -SOURCES = qtestcase.cpp qtestlog.cpp qtesttable.cpp qtestdata.cpp qtestresult.cpp qasciikey.cpp qplaintestlogger.cpp qxmltestlogger.cpp qsignaldumper.cpp qabstracttestlogger.cpp qbenchmark.cpp qbenchmarkmeasurement.cpp qbenchmarkvalgrind.cpp qbenchmarkevent.cpp - -DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII QTESTLIB_MAKEDLL QT_NO_DATASTREAM - -wince*:{ - LIBS += libcmt.lib corelibc.lib ole32.lib oleaut32.lib uuid.lib commctrl.lib coredll.lib winsock.lib -} - -mac { - LIBS += -framework IOKit -framework Security -} - +HEADERS = qtest_global.h \ + qtestcase.h \ + qtestdata.h \ + qtesteventloop.h \ + qtestcorelist.h \ + qtestcoreelement.h \ + qtestelement.h \ + qtestelementattribute.h \ + qtestbasicstreamer.h \ + qtestxunitstreamer.h \ + qtestxmlstreamer.h \ + qtestlightxmlstreamer.h \ + qtestfilelogger.h +SOURCES = qtestcase.cpp \ + qtestlog.cpp \ + qtesttable.cpp \ + qtestdata.cpp \ + qtestresult.cpp \ + qasciikey.cpp \ + qplaintestlogger.cpp \ + qxmltestlogger.cpp \ + qsignaldumper.cpp \ + qabstracttestlogger.cpp \ + qbenchmark.cpp \ + qbenchmarkmeasurement.cpp \ + qbenchmarkvalgrind.cpp \ + qbenchmarkevent.cpp \ + qtestelement.cpp \ + qtestelementattribute.cpp \ + qtestbasicstreamer.cpp \ + qtestxunitstreamer.cpp \ + qtestxmlstreamer.cpp \ + qtestlightxmlstreamer.cpp \ + qtestlogger.cpp \ + qtestfilelogger.cpp +DEFINES += QT_NO_CAST_TO_ASCII \ + QT_NO_CAST_FROM_ASCII \ + QTESTLIB_MAKEDLL \ + QT_NO_DATASTREAM +embedded:QMAKE_CXXFLAGS += -fno-rtti +wince*::LIBS += libcmt.lib \ + corelibc.lib \ + ole32.lib \ + oleaut32.lib \ + uuid.lib \ + commctrl.lib \ + coredll.lib \ + winsock.lib +mac:LIBS += -framework \ + IOKit \ + -framework \ + Security include(../qbase.pri) QMAKE_TARGET_PRODUCT = QTestLib -QMAKE_TARGET_DESCRIPTION = Qt Unit Testing Library +QMAKE_TARGET_DESCRIPTION = Qt \ + Unit \ + Testing \ + Library |