diff options
Diffstat (limited to 'src/testlib')
44 files changed, 3995 insertions, 236 deletions
diff --git a/src/testlib/3rdparty/cycle_p.h b/src/testlib/3rdparty/cycle_p.h index b4b6876..a292423 100644 --- a/src/testlib/3rdparty/cycle_p.h +++ b/src/testlib/3rdparty/cycle_p.h @@ -190,6 +190,7 @@ INLINE_ELAPSED(__inline__) #endif /* Visual C++ -- thanks to Morten Nissov for his help with this */ +#if defined(_MSC_VER) #if _MSC_VER >= 1200 && (_M_IX86 >= 500 || (defined(_WIN32_WCE) && defined(_X86_))) && !defined(HAVE_TICK_COUNTER) #include <windows.h> typedef LARGE_INTEGER CycleCounterTicks; @@ -215,6 +216,7 @@ static __inline double elapsed(CycleCounterTicks t1, CycleCounterTicks t0) #define HAVE_TICK_COUNTER #define TIME_MIN 5000.0 /* unreliable pentium IV cycle counter */ #endif +#endif #if _MSC_VER >= 1400 && defined(_WIN32_WCE) && !defined(HAVE_TICK_COUNTER) #include <windows.h> @@ -491,4 +493,21 @@ INLINE_ELAPSED(inline) #define HAVE_TICK_COUNTER #endif +/*----------------------------------------------------------------*/ +/* Symbian */ +#if defined(__SYMBIAN32__) && !defined(HAVE_TICK_COUNTER) +#include <e32std.h> + +typedef TUint32 CycleCounterTicks; + +static inline CycleCounterTicks getticks(void) +{ + return User::FastCounter(); +} + +INLINE_ELAPSED(inline) + +#define HAVE_TICK_COUNTER +#endif + #endif // QBENCHLIB_CYCLE_H diff --git a/src/testlib/qabstracttestlogger.cpp b/src/testlib/qabstracttestlogger.cpp index 57c3ca5..9d2c024 100644 --- a/src/testlib/qabstracttestlogger.cpp +++ b/src/testlib/qabstracttestlogger.cpp @@ -43,8 +43,11 @@ #include "QtTest/private/qtestlog_p.h" #include "QtTest/qtestassert.h" +#include "QtCore/qbytearray.h" + #include <stdio.h> #include <stdlib.h> +#include <stdarg.h> #ifndef Q_OS_WIN #include <unistd.h> @@ -77,6 +80,7 @@ bool QAbstractTestLogger::isTtyOutput() #endif } + void QAbstractTestLogger::startLogging() { QTEST_ASSERT(!QTest::stream); @@ -105,4 +109,50 @@ void QAbstractTestLogger::stopLogging() QTest::stream = 0; } +namespace QTest +{ + +extern void filter_unprintable(char *str); + +/*! + \fn int QTest::qt_asprintf(QTestCharBuffer *buf, const char *format, ...); + \internal + */ +int qt_asprintf(QTestCharBuffer *str, const char *format, ...) +{ + static const int MAXSIZE = 1024*1024*2; + + Q_ASSERT(str); + + int size = str->size(); + + va_list ap; + int res = 0; + + for (;;) { + va_start(ap, format); + res = qvsnprintf(str->data(), size, format, ap); + va_end(ap); + str->data()[size - 1] = '\0'; + if (res >= 0 && res < size) { + // We succeeded + break; + } + // buffer wasn't big enough, try again. + // Note, we're assuming that a result of -1 is always due to running out of space. + size *= 2; + if (size > MAXSIZE) { + break; + } + if (!str->reset(size)) + break; // out of memory - take what we have + } + + filter_unprintable(str->data()); + + return res; +} + +} + QT_END_NAMESPACE diff --git a/src/testlib/qabstracttestlogger_p.h b/src/testlib/qabstracttestlogger_p.h index bf3ab8f..cc4e509 100644 --- a/src/testlib/qabstracttestlogger_p.h +++ b/src/testlib/qabstracttestlogger_p.h @@ -99,6 +99,74 @@ public: static bool isTtyOutput(); }; +struct QTestCharBuffer +{ + enum { InitialSize = 512 }; + + inline QTestCharBuffer() + : _size(InitialSize), buf(staticBuf) + { + staticBuf[0] = '\0'; + } + + inline ~QTestCharBuffer() + { + if (buf != staticBuf) + qFree(buf); + } + + inline char *data() + { + return buf; + } + + inline char **buffer() + { + return &buf; + } + + inline const char* constData() const + { + return buf; + } + + inline int size() const + { + return _size; + } + + inline bool reset(int newSize) + { + char *newBuf = 0; + if (buf == staticBuf) { + // if we point to our internal buffer, we need to malloc first + newBuf = reinterpret_cast<char *>(qMalloc(newSize)); + } else { + // if we already malloc'ed, just realloc + newBuf = reinterpret_cast<char *>(qRealloc(buf, newSize)); + } + + // if the allocation went wrong (newBuf == 0), we leave the object as is + if (!newBuf) + return false; + + _size = newSize; + buf = newBuf; + return true; + } + +private: + int _size; + char* buf; + char staticBuf[InitialSize]; +}; + +namespace QTest +{ + int qt_asprintf(QTestCharBuffer *buf, const char *format, ...); +} + + QT_END_NAMESPACE #endif diff --git a/src/testlib/qbenchmark.cpp b/src/testlib/qbenchmark.cpp index 98de7f8..fa5c1cf 100644 --- a/src/testlib/qbenchmark.cpp +++ b/src/testlib/qbenchmark.cpp @@ -1,4 +1,3 @@ - /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). @@ -117,7 +116,7 @@ int QBenchmarkGlobalData::adjustMedianIterationCount() QBenchmarkTestMethodData *QBenchmarkTestMethodData::current; QBenchmarkTestMethodData::QBenchmarkTestMethodData() -:resultAccepted(false), iterationCount(-1) +:resultAccepted(false), runOnce(false), iterationCount(-1) { } @@ -158,6 +157,11 @@ void QBenchmarkTestMethodData::setResult(qint64 value) if (QBenchmarkGlobalData::current->iterationCount != -1) accepted = true; + if (QBenchmarkTestMethodData::current->runOnce) { + iterationCount = 1; + accepted = true; + } + // Test the result directly without calling the measurer if the minimum time // has been specifed on the command line with -minimumvalue. else if (QBenchmarkGlobalData::current->walltimeMinimum != -1) @@ -175,16 +179,31 @@ void QBenchmarkTestMethodData::setResult(qint64 value) QBenchmarkResult(QBenchmarkGlobalData::current->context, value, iterationCount); } -/*! \internal +/*! + \class QTest::QBenchmarkIterationController + \internal + The QBenchmarkIterationController class is used by the QBENCHMARK macro to drive the benchmarking loop. It is repsonsible for starting and stopping the timing measurements as well as calling the result reporting functions. */ -QTest::QBenchmarkIterationController::QBenchmarkIterationController() + +/*! \internal +*/ +QTest::QBenchmarkIterationController::QBenchmarkIterationController(RunMode runMode) { + i = 0; + if (runMode == RunOnce) + QBenchmarkTestMethodData::current->runOnce = true; QTest::beginBenchmarkMeasurement(); +} + +QTest::QBenchmarkIterationController::QBenchmarkIterationController() +{ i = 0; + QTest::beginBenchmarkMeasurement(); } + /*! \internal */ QTest::QBenchmarkIterationController::~QBenchmarkIterationController() @@ -196,6 +215,8 @@ QTest::QBenchmarkIterationController::~QBenchmarkIterationController() */ bool QTest::QBenchmarkIterationController::isDone() { + if (QBenchmarkTestMethodData::current->runOnce) + return i > 0; return i >= QTest::iterationCount(); } @@ -219,6 +240,7 @@ void QTest::setIterationCountHint(int count) { QBenchmarkTestMethodData::current->adjustIterationCount(count); } + /*! \internal */ void QTest::setIterationCount(int count) diff --git a/src/testlib/qbenchmark.h b/src/testlib/qbenchmark.h index 2285f78..1054cbd 100644 --- a/src/testlib/qbenchmark.h +++ b/src/testlib/qbenchmark.h @@ -64,7 +64,9 @@ namespace QTest class Q_TESTLIB_EXPORT QBenchmarkIterationController { public: + enum RunMode { RepeatUntilValidMeasurement, RunOnce }; QBenchmarkIterationController(); + QBenchmarkIterationController(RunMode runMode); ~QBenchmarkIterationController(); bool isDone(); void next(); @@ -74,7 +76,12 @@ public: } #define QBENCHMARK \ - for (QTest::QBenchmarkIterationController __iteration_controller; __iteration_controller.isDone() == false; __iteration_controller.next()) + for (QTest::QBenchmarkIterationController __iteration_controller; \ + __iteration_controller.isDone() == false; __iteration_controller.next()) + +#define QBENCHMARK_ONCE \ + for (QTest::QBenchmarkIterationController __iteration_controller(QTest::QBenchmarkIterationController::RunOnce); \ + __iteration_controller.isDone() == false; __iteration_controller.next()) QT_END_NAMESPACE diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h index 3d40eb1..6bccf7e 100644 --- a/src/testlib/qbenchmark_p.h +++ b/src/testlib/qbenchmark_p.h @@ -55,7 +55,7 @@ #include <QtCore/qglobal.h> -#if defined(Q_OS_LINUX) && !defined(QT_NO_PROCESS) +#if (defined(Q_OS_LINUX) || defined Q_OS_MAC) && !defined(QT_NO_PROCESS) #define QTESTLIB_USE_VALGRIND #else #undef QTESTLIB_USE_VALGRIND @@ -81,7 +81,7 @@ struct QBenchmarkContext QString toString() const { - QString s = QString(QLatin1String("%1,%2,%3")).arg(slotName).arg(tag).arg(checkpointIndex); + QString s = QString::fromLatin1("%1,%2,%3").arg(slotName).arg(tag).arg(checkpointIndex); return s; } @@ -171,6 +171,7 @@ public: QBenchmarkResult result; bool resultAccepted; + bool runOnce; int iterationCount; }; diff --git a/src/testlib/qbenchmarkvalgrind.cpp b/src/testlib/qbenchmarkvalgrind.cpp index c3c2cff..19c5b5a 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() { @@ -132,12 +133,12 @@ QString QBenchmarkValgrindUtils::getNewestFileName() QString base = QBenchmarkGlobalData::current->callgrindOutFileBase; Q_ASSERT(!base.isEmpty()); - nameFilters << QString(QLatin1String("%1.*")).arg(base); + nameFilters << QString::fromLatin1("%1.*").arg(base); QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable); Q_ASSERT(!fiList.empty()); int hiSuffix = -1; QFileInfo lastFileInfo; - const QString pattern = QString(QLatin1String("%1.(\\d+)")).arg(base); + const QString pattern = QString::fromLatin1("%1.(\\d+)").arg(base); const QRegExp rx(pattern); foreach (QFileInfo fileInfo, fiList) { const int index = rx.indexIn(fileInfo.fileName()); @@ -167,8 +168,8 @@ void QBenchmarkValgrindUtils::cleanup() QString base = QBenchmarkGlobalData::current->callgrindOutFileBase; Q_ASSERT(!base.isEmpty()); nameFilters - << QString(QLatin1String("%1")).arg(base) // overall summary - << QString(QLatin1String("%1.*")).arg(base); // individual dumps + << base // overall summary + << QString::fromLatin1("%1.*").arg(base); // individual dumps QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable); foreach (QFileInfo fileInfo, fiList) { const bool removeOk = QFile::remove(fileInfo.fileName()); @@ -179,7 +180,7 @@ void QBenchmarkValgrindUtils::cleanup() QString QBenchmarkValgrindUtils::outFileBase(qint64 pid) { - return QString(QLatin1String("callgrind.out.%1")).arg( + return QString::fromLatin1("callgrind.out.%1").arg( pid != -1 ? pid : QCoreApplication::applicationPid()); } @@ -272,4 +273,6 @@ QString QBenchmarkCallgrindMeasurer::metricText() return QLatin1String("callgrind"); } +QT_END_NAMESPACE + #endif // QTESTLIB_USE_VALGRIND diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp index aa486de..d07c8ef 100644 --- a/src/testlib/qplaintestlogger.cpp +++ b/src/testlib/qplaintestlogger.cpp @@ -54,6 +54,10 @@ #include "windows.h" #endif +#if defined(Q_OS_SYMBIAN) +#include <e32debug.h> +#endif + #ifdef Q_OS_WINCE #include <QtCore/QString> #endif @@ -125,7 +129,11 @@ namespace QTest { static const char *messageType2String(QAbstractTestLogger::MessageTypes type) { +#ifdef Q_OS_WIN static bool colored = (!qgetenv("QTEST_COLORED").isEmpty()); +#else + static bool colored = ::getenv("QTEST_COLORED"); +#endif switch (type) { case QAbstractTestLogger::Skip: return COLORED_MSG(0, 37, "SKIP "); //white @@ -148,17 +156,39 @@ namespace QTest { static void outputMessage(const char *str) { #if defined(Q_OS_WINCE) - int length = strlen(str); - for (int pos = 0; pos < length; pos +=255) { - QString uniText = QString::fromLatin1(str + pos, 255); - OutputDebugStringW((const LPCWSTR) uniText.utf16()); - } + QString strUtf16 = QString::fromLatin1(str); + const int maxOutputLength = 255; + do { + QString tmp = strUtf16.left(maxOutputLength); + OutputDebugString((wchar_t*)tmp.utf16()); + strUtf16.remove(0, maxOutputLength); + } while (!strUtf16.isEmpty()); if (QTestLog::outputFileName()) #elif defined(Q_OS_WIN) EnterCriticalSection(&outputCriticalSection); // OutputDebugString is not threadsafe OutputDebugStringA(str); LeaveCriticalSection(&outputCriticalSection); +#elif defined(Q_OS_SYMBIAN) + // RDebug::Print has a cap of 256 characters so break it up + TPtrC8 ptr(reinterpret_cast<const TUint8*>(str)); + _LIT(format, "[QTestLib] %S"); + const int maxBlockSize = 256 - ((const TDesC &)format).Length(); + HBufC* hbuffer = HBufC::New(maxBlockSize); + if(hbuffer) { + for (int i = 0; i < ptr.Length(); i += maxBlockSize) { + int size = Min(maxBlockSize, ptr.Length() - i); + hbuffer->Des().Copy(ptr.Mid(i, size)); + RDebug::Print(format, hbuffer); + } + } + else { + // fast, no allocations, but truncates silently + RDebug::RawPrint(format); + TPtrC8 ptr(reinterpret_cast<const TUint8*>(str)); + RDebug::RawPrint(ptr); + RDebug::RawPrint(_L8("\n")); + } #endif QAbstractTestLogger::outputString(str); } @@ -168,7 +198,7 @@ namespace QTest { QTEST_ASSERT(type); QTEST_ASSERT(msg); - char buf[1024]; + QTestCharBuffer buf; const char *fn = QTestResult::currentTestFunction() ? QTestResult::currentTestFunction() : "UnknownTestFunc"; @@ -178,7 +208,7 @@ namespace QTest { : ""; const char *filler = (tag[0] && gtag[0]) ? ":" : ""; if (file) { - QTest::qt_snprintf(buf, sizeof(buf), "%s: %s::%s(%s%s%s)%s%s\n" + QTest::qt_asprintf(&buf, "%s: %s::%s(%s%s%s)%s%s\n" #ifdef Q_OS_WIN "%s(%d) : failure location\n" #else @@ -187,12 +217,14 @@ namespace QTest { , type, QTestResult::currentTestObjectName(), fn, gtag, filler, tag, msg[0] ? " " : "", msg, file, line); } else { - QTest::qt_snprintf(buf, sizeof(buf), "%s: %s::%s(%s%s%s)%s%s\n", + QTest::qt_asprintf(&buf, "%s: %s::%s(%s%s%s)%s%s\n", type, QTestResult::currentTestObjectName(), fn, gtag, filler, tag, msg[0] ? " " : "", msg); } - memcpy(buf, type, strlen(type)); - outputMessage(buf); + // In colored mode, printf above stripped our nonprintable control characters. + // Put them back. + memcpy(buf.data(), type, strlen(type)); + outputMessage(buf.data()); } template <typename T> @@ -203,7 +235,7 @@ namespace QTest { int digits = 0; qreal divisor = 1; - + while (num / divisor >= 1) { divisor *= 10; ++digits; @@ -216,17 +248,17 @@ namespace QTest { template <typename T> QString formatResult(T number, int significantDigits) { if (number < T(0)) - return QString(QLatin1String("NAN")); + return QLatin1String("NAN"); if (number == T(0)) - return QString(QLatin1String("0")); + return QLatin1String("0"); QString beforeDecimalPoint = QString::number(qint64(number), 'f', 0); QString afterDecimalPoint = QString::number(number, 'f', 20); afterDecimalPoint.remove(0, beforeDecimalPoint.count() + 1); - + int beforeUse = qMin(beforeDecimalPoint.count(), significantDigits); int beforeRemove = beforeDecimalPoint.count() - beforeUse; - + // Replace insignificant digits before the decimal point with zeros. beforeDecimalPoint.chop(beforeRemove); for (int i = 0; i < beforeRemove; ++i) { @@ -264,10 +296,10 @@ namespace QTest { print = beforeDecimalPoint; if (afterUse > 0) print.append(decimalPoint); - + print += afterDecimalPoint; - + return print; } @@ -288,7 +320,7 @@ namespace QTest { char buf1[1024]; QTest::qt_snprintf( buf1, sizeof(buf1), "%s: %s::%s", - bmtag, + bmtag, QTestResult::currentTestObjectName(), result.context.slotName.toAscii().data()); @@ -299,7 +331,7 @@ namespace QTest { if (tag.isEmpty() == false) { QTest::qt_snprintf(bufTag, sizeof(bufTag), ":\"%s\"", tag.data()); } - + char fillFormat[8]; int fillLength = 5; diff --git a/src/testlib/qsignaldumper.cpp b/src/testlib/qsignaldumper.cpp index c236d55..8fb5688 100644 --- a/src/testlib/qsignaldumper.cpp +++ b/src/testlib/qsignaldumper.cpp @@ -87,7 +87,7 @@ static void qSignalDumperCallback(QObject *caller, int method_index, void **argv str.fill(' ', QTest::iLevel++ * QTest::IndentSpacesCount); str += "Signal: "; str += mo->className(); - str += "("; + str += '('; QString objname = caller->objectName(); str += objname.toLocal8Bit(); @@ -114,15 +114,15 @@ static void qSignalDumperCallback(QObject *caller, int method_index, void **argv str.append(QByteArray::number(addr, 16)); } else if (typeId != QMetaType::Void) { str.append(arg) - .append("(") + .append('(') .append(QVariant(typeId, argv[i + 1]).toString().toLocal8Bit()) - .append(")"); + .append(')'); } str.append(", "); } if (str.endsWith(", ")) str.chop(2); - str.append(")"); + str.append(')'); qPrintMessage(str); } @@ -143,7 +143,7 @@ static void qSignalDumperCallbackSlot(QObject *caller, int method_index, void ** str.fill(' ', QTest::iLevel * QTest::IndentSpacesCount); str += "Slot: "; str += mo->className(); - str += "("; + str += '('; QString objname = caller->objectName(); str += objname.toLocal8Bit(); diff --git a/src/testlib/qsignalspy.qdoc b/src/testlib/qsignalspy.qdoc new file mode 100644 index 0000000..cb388d8 --- /dev/null +++ b/src/testlib/qsignalspy.qdoc @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QSignalSpy + \inmodule QtTest + + \brief The QSignalSpy class enables introspection of signal emission. + + QSignalSpy can connect to any signal of any object and records its emission. + QSignalSpy itself is a list of QVariant lists. Each emission of the signal + will append one item to the list, containing the arguments of the signal. + + The following example records all signal emissions for the \c clicked() signal + of a QCheckBox: + + \snippet doc/src/snippets/code/doc_src_qsignalspy.qdoc 0 + + \c{spy.takeFirst()} returns the arguments for the first emitted signal, as a + list of QVariant objects. The \c clicked() signal has a single bool argument, + which is stored as the first entry in the list of arguments. + + The example below catches a signal from a custom object: + + \snippet doc/src/snippets/code/doc_src_qsignalspy.qdoc 1 + + \bold {Note:} Non-standard data types need to be registered, using + the qRegisterMetaType() function, before you can create a + QSignalSpy. For example: + + \snippet doc/src/snippets/code/doc_src_qsignalspy.qdoc 2 + + To retrieve the \c QModelIndex, you can use qvariant_cast: + + \snippet doc/src/snippets/code/doc_src_qsignalspy.qdoc 3 + */ + +/*! \fn QSignalSpy::QSignalSpy(QObject *object, const char *signal) + + Constructs a new QSignalSpy that listens for emissions of the \a signal + from the QObject \a object. Neither \a signal nor \a object can be null. + + Example: + \snippet doc/src/snippets/code/doc_src_qsignalspy.qdoc 4 +*/ + +/*! \fn QSignalSpy::isValid() const + + Returns true if the signal spy listens to a valid signal, otherwise false. +*/ + +/*! \fn QSignalSpy::signal() const + + Returns the normalized signal the spy is currently listening to. +*/ + +/*! \fn int QSignalSpy::qt_metacall(QMetaObject::Call call, int id, void **a) + \internal +*/ + diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index 9e29e65..42ba996 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -53,6 +53,7 @@ #include <QtCore/qstringlist.h> #include <QtCore/qdatetime.h> #include <QtCore/qobject.h> +#include <QtCore/qvariant.h> #include <QtCore/qurl.h> #include <QtCore/qpoint.h> @@ -146,6 +147,30 @@ template<> inline char *toString(const QUrl &uri) return qstrdup(uri.toEncoded().constData()); } +template<> inline char *toString(const QVariant &v) +{ + QByteArray vstring("QVariant("); + if (v.isValid()) { + QByteArray type(v.typeName()); + if (type.isEmpty()) { + type = QByteArray::number(v.userType()); + } + vstring.append(type); + if (!v.isNull()) { + vstring.append(','); + if (v.canConvert(QVariant::String)) { + vstring.append(qVariantValue<QString>(v).toLatin1()); + } + else { + vstring.append("<value not representable as string>"); + } + } + } + vstring.append(')'); + + return qstrdup(vstring.constData()); +} + #ifndef QTEST_NO_SPECIALIZATIONS template<> #endif @@ -226,10 +251,17 @@ int main(int argc, char *argv[]) \ #include <QtTest/qtest_gui.h> +#ifdef QT_KEYPAD_NAVIGATION +# define QTEST_DISABLE_KEYPAD_NAVIGATION QApplication::setKeypadNavigationEnabled(false); +#else +# define QTEST_DISABLE_KEYPAD_NAVIGATION +#endif + #define QTEST_MAIN(TestObject) \ int main(int argc, char *argv[]) \ { \ QApplication app(argc, argv); \ + QTEST_DISABLE_KEYPAD_NAVIGATION \ TestObject tc; \ return QTest::qExec(&tc, argc, argv); \ } diff --git a/src/testlib/qtest_global.h b/src/testlib/qtest_global.h index 058f8ad..0282fbb 100644 --- a/src/testlib/qtest_global.h +++ b/src/testlib/qtest_global.h @@ -52,7 +52,7 @@ QT_MODULE(Test) #ifdef QTEST_EMBED # define Q_TESTLIB_EXPORT -#elif !defined(QT_SHARED) +#elif !defined(QT_SHARED) && !(defined(Q_OS_SYMBIAN) && defined(Q_CC_RVCT)) # define Q_TESTLIB_EXPORT #else # ifdef QTESTLIB_MAKEDLL @@ -62,10 +62,11 @@ QT_MODULE(Test) # endif #endif -#if (defined (Q_CC_MSVC) && _MSC_VER < 1310) || defined (Q_CC_SUN) || defined (Q_CC_XLC) || (defined (Q_CC_GNU) && (__GNUC__ - 0 < 3)) +#if (defined (Q_CC_MSVC) && _MSC_VER < 1310) || defined (Q_CC_SUN) || defined (Q_CC_XLC) || (defined (Q_CC_GNU) && (__GNUC__ - 0 < 3)) || defined (Q_CC_NOKIAX86) # define QTEST_NO_SPECIALIZATIONS #endif + #if (defined Q_CC_HPACC) && (defined __ia64) # ifdef Q_TESTLIB_EXPORT # undef Q_TESTLIB_EXPORT diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h index 56e66e6..ee2ac5d 100644 --- a/src/testlib/qtest_gui.h +++ b/src/testlib/qtest_gui.h @@ -46,6 +46,7 @@ #include <QtTest/qtest.h> #include <QtTest/qtestevent.h> #include <QtTest/qtestmouse.h> +#include <QtTest/qtesttouch.h> #include <QtTest/qtestkeyboard.h> #include <QtGui/qicon.h> diff --git a/src/testlib/qtestbasicstreamer.cpp b/src/testlib/qtestbasicstreamer.cpp new file mode 100644 index 0000000..1ce1fc0 --- /dev/null +++ b/src/testlib/qtestbasicstreamer.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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, QTestCharBuffer *formatted) const +{ + if(!element || !formatted ) + return; + formatted->data()[0] = '\0'; +} + +void QTestBasicStreamer::formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const +{ + if(!element || !formatted ) + return; + formatted->data()[0] = '\0'; +} + +void QTestBasicStreamer::formatBeforeAttributes(const QTestElement *element, QTestCharBuffer *formatted) const +{ + if(!element || !formatted ) + return; + formatted->data()[0] = '\0'; +} + +void QTestBasicStreamer::formatAfterAttributes(const QTestElement *element, QTestCharBuffer *formatted) const +{ + if(!element || !formatted ) + return; + formatted->data()[0] = '\0'; +} + +void QTestBasicStreamer::formatAttributes(const QTestElement *, const QTestElementAttribute *attribute, QTestCharBuffer *formatted) const +{ + if(!attribute || !formatted ) + return; + formatted->data()[0] = '\0'; +} + +void QTestBasicStreamer::output(QTestElement *element) const +{ + if(!element) + return; + + outputElements(element); +} + +void QTestBasicStreamer::outputElements(QTestElement *element, bool) const +{ + QTestCharBuffer buf; + 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.data()); + + formatBeforeAttributes(element, &buf); + outputString(buf.data()); + + outputElementAttributes(element, element->attributes()); + + formatAfterAttributes(element, &buf); + outputString(buf.data()); + + if(hasChildren) + outputElements(element->childElements(), true); + + formatEnd(element, &buf); + outputString(buf.data()); + + element = element->previousElement(); + } +} + +void QTestBasicStreamer::outputElementAttributes(const QTestElement* element, QTestElementAttribute *attribute) const +{ + QTestCharBuffer buf; + while(attribute){ + formatAttributes(element, attribute, &buf); + outputString(buf.data()); + 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..661db0b --- /dev/null +++ b/src/testlib/qtestbasicstreamer.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTBASICSTREAMER_H +#define QTESTBASICSTREAMER_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +class QTestElement; +class QTestElementAttribute; +class QTestLogger; +struct QTestCharBuffer; + +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, QTestCharBuffer *formatted) const; + virtual void formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const; + virtual void formatBeforeAttributes(const QTestElement *element, QTestCharBuffer *formatted) const; + virtual void formatAfterAttributes(const QTestElement *element, QTestCharBuffer *formatted) const; + virtual void formatAttributes(const QTestElement *element, const QTestElementAttribute *attribute, QTestCharBuffer *formatted) const; + virtual void outputElements(QTestElement *element, bool isChildElement = false) const; + virtual void outputElementAttributes(const QTestElement *element, QTestElementAttribute *attribute) const; + + private: + const QTestLogger *testLogger; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index b1e2794..c655cad 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -54,6 +54,7 @@ #include <QtCore/qdir.h> #include <QtCore/qprocess.h> #include <QtCore/qdebug.h> +#include <QtCore/qlibraryinfo.h> #include "QtTest/private/qtestlog_p.h" #include "QtTest/private/qtesttable_p.h" @@ -71,6 +72,8 @@ #include <windows.h> // for Sleep #endif #ifdef Q_OS_UNIX +#include <errno.h> +#include <signal.h> #include <time.h> #endif @@ -300,10 +303,15 @@ QT_BEGIN_NAMESPACE the \a TestClass, and executes all tests in the order they were defined. Use this macro to build stand-alone executables. + \bold {Note:} On platforms that have keypad navigation enabled by default (eg: Symbian), + this macro will forcfully disable it to simplify the usage of key events when writing + autotests. If you wish to write a test case that uses keypad navigation, you should + enable it either in the \c {initTestCase()} or \c {init()} functions of your test case. + Example: \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 11 - \sa QTEST_APPLESS_MAIN(), QTest::qExec() + \sa QTEST_APPLESS_MAIN(), QTest::qExec(), QApplication::setKeypadNavigationEnabled() */ /*! \macro QTEST_APPLESS_MAIN(TestClass) @@ -348,6 +356,26 @@ QT_BEGIN_NAMESPACE {Chapter 5: Writing a Benchmark}{Writing a Benchmark} */ +/*! + \macro QBENCHMARK_ONCE + \since 4.6 + + \relates QTest + + This macro is used to measure the performance of code within a test. + The code to be benchmarked is contained within a code block following + this macro. + + Unlike QBENCHMARK, the contents of the contained code block is only run + once. The elapsed time will be reported as "0" if it's to short to + be measured by the selected backend. (Use) + + \sa {QTestLib Manual#Creating a Benchmark}{Creating a Benchmark}, + {Chapter 5: Writing a Benchmark}{Writing a Benchmark} +*/ + + + /*! \enum QTest::SkipMode This enum describes the modes for skipping tests during execution @@ -400,7 +428,8 @@ QT_BEGIN_NAMESPACE \overload - Simulates clicking of \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds. + Simulates clicking of \a key with an optional \a modifier on a \a widget. + If \a delay is larger than 0, the test will wait for \a delay milliseconds. Example: \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 13 @@ -413,7 +442,8 @@ QT_BEGIN_NAMESPACE /*! \fn void QTest::keyClick(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) - Simulates clicking of \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds. + Simulates clicking of \a key with an optional \a modifier on a \a widget. + If \a delay is larger than 0, the test will wait for \a delay milliseconds. Examples: \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 14 @@ -428,20 +458,25 @@ QT_BEGIN_NAMESPACE /*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) - Sends a Qt key event to \a widget with the given \a key and an associated \a action. Optionally, a keyboard \a modifier can be specified, as well as a \a delay (in milliseconds) of the test before sending the event. + Sends a Qt key event to \a widget with the given \a key and an associated \a action. + Optionally, a keyboard \a modifier can be specified, as well as a \a delay + (in milliseconds) of the test before sending the event. */ /*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, char ascii, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) \overload - Sends a Qt key event to \a widget with the given key \a ascii and an associated \a action. Optionally, a keyboard \a modifier can be specified, as well as a \a delay (in milliseconds) of the test before sending the event. + Sends a Qt key event to \a widget with the given key \a ascii and an associated \a action. + Optionally, a keyboard \a modifier can be specified, as well as a \a delay + (in milliseconds) of the test before sending the event. */ /*! \fn void QTest::keyPress(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) - Simulates pressing a \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds. + Simulates pressing a \a key with an optional \a modifier on a \a widget. If \a delay + is larger than 0, the test will wait for \a delay milliseconds. \bold {Note:} At some point you should release the key using \l keyRelease(). @@ -452,7 +487,8 @@ QT_BEGIN_NAMESPACE \overload - Simulates pressing a \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds. + Simulates pressing a \a key with an optional \a modifier on a \a widget. + If \a delay is larger than 0, the test will wait for \a delay milliseconds. \bold {Note:} At some point you should release the key using \l keyRelease(). @@ -461,7 +497,8 @@ QT_BEGIN_NAMESPACE /*! \fn void QTest::keyRelease(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) - Simulates releasing a \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds. + Simulates releasing a \a key with an optional \a modifier on a \a widget. + If \a delay is larger than 0, the test will wait for \a delay milliseconds. \sa QTest::keyPress(), QTest::keyClick() */ @@ -470,7 +507,8 @@ QT_BEGIN_NAMESPACE \overload - Simulates releasing a \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds. + Simulates releasing a \a key with an optional \a modifier on a \a widget. + If \a delay is larger than 0, the test will wait for \a delay milliseconds. \sa QTest::keyClick() */ @@ -672,6 +710,13 @@ QT_BEGIN_NAMESPACE Returns a textual representation of the given \a rectangle. */ +/*! + \fn char *QTest::toString(const QVariant &variant) + \overload + + Returns a textual representation of the given \a variant. +*/ + /*! \fn void QTest::qWait(int ms) Waits for \a ms milliseconds. While waiting, events will be processed and @@ -686,16 +731,94 @@ QT_BEGIN_NAMESPACE \sa QTest::qSleep() */ +/*! + \class QTest::QTouchEventSequence + \inmodule QtTest + \since 4.6 + + \brief The QTouchEventSequence class is used to simulate a sequence of touch events. + + To simulate a sequence of touch events on a specific device for a widget, call + QTest::touchEvent to create a QTouchEventSequence instance. Add touch events to + the sequence by calling press(), move(), release() and stationary(), and let the + instance run out of scope to commit the sequence to the event system. +*/ + +/*! + \fn QTest::QTouchEventSequence::~QTouchEventSequence() + + Commits this sequence of touch events and frees allocated resources. +*/ + +/*! + \fn QTouchEventSequence &QTest::QTouchEventSequence::press(int touchId, const QPoint &pt, QWidget *widget) + + Adds a press event for touchpoint \a touchId at position \a pt to this sequence and returns + a reference to this QTouchEventSequence. + + The position \a pt is interpreted as relative to \a widget. If \a widget is the null pointer, then + \a pt is interpreted as relative to the widget provided when instantiating this QTouchEventSequence. + + Simulates that the user pressed the touch screen or pad with the finger identified by \a touchId. +*/ + +/*! + \fn QTouchEventSequence &QTest::QTouchEventSequence::move(int touchId, const QPoint &pt, QWidget *widget) + + Adds a move event for touchpoint \a touchId at position \a pt to this sequence and returns + a reference to this QTouchEventSequence. + + The position \a pt is interpreted as relative to \a widget. If \a widget is the null pointer, then + \a pt is interpreted as relative to the widget provided when instantiating this QTouchEventSequence. + + Simulates that the user moved the finger identified by \a touchId. +*/ + +/*! + \fn QTouchEventSequence &QTest::QTouchEventSequence::release(int touchId, const QPoint &pt, QWidget *widget) + + Adds a release event for touchpoint \a touchId at position \a pt to this sequence and returns + a reference to this QTouchEventSequence. + + The position \a pt is interpreted as relative to \a widget. If \a widget is the null pointer, then + \a pt is interpreted as relative to the widget provided when instantiating this QTouchEventSequence. + + Simulates that the user lifted the finger identified by \a touchId. +*/ + +/*! + \fn QTouchEventSequence &QTest::QTouchEventSequence::stationary(int touchId) + + Adds a stationary event for touchpoint \a touchId to this sequence and returns + a reference to this QTouchEventSequence. + + Simulates that the user did not move the finger identified by \a touchId. +*/ + +/*! + \fn QTouchEventSequence QTest::touchEvent(QWidget *widget, QTouchEvent::DeviceType deviceType) + + Creates and returns a QTouchEventSequence for the device \a deviceType to + simulate events for \a widget. + + When adding touch events to the sequence, \a widget will also be used to translate + the position provided to screen coordinates, unless another widget is provided in the + respective calls to press(), move() etc. + + The touch events are committed to the event system when the destructor of the + QTouchEventSequence is called (ie when the object returned runs out of scope). +*/ + namespace QTest { static QObject *currentTestObject = 0; - struct TestFunction { + static struct TestFunction { TestFunction():function(0), data(0) {} ~TestFunction() { delete [] data; } int function; char *data; - } testFuncs[512]; + } *testFuncs; /** * Contains the count of test functions that was supplied @@ -710,6 +833,16 @@ namespace QTest static int eventDelay = -1; static int keyVerbose = -1; +void filter_unprintable(char *str) +{ + char *idx = str; + while (*idx) { + if (((*idx < 0x20 && *idx != '\n' && *idx != '\t') || *idx > 0x7e)) + *idx = '?'; + ++idx; + } +} + /*! \internal */ int qt_snprintf(char *str, int size, const char *format, ...) @@ -722,12 +855,8 @@ int qt_snprintf(char *str, int size, const char *format, ...) va_end(ap); str[size - 1] = '\0'; - char *idx = str; - while (*idx) { - if (((*idx < 0x20 && *idx != '\n' && *idx != '\t') || *idx > 0x7e)) - *idx = '?'; - ++idx; - } + filter_unprintable(str); + return res; } @@ -818,8 +947,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" @@ -844,9 +975,8 @@ static void qParseArgs(int argc, char *argv[]) " -iterations n : Sets the number of accumulation iterations.\n" " -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. -// " -chart : Runs the chart generator after the test. No output is printed to the console\n" +#if !defined(QT_NO_PROCESS) && !defined(QT_NO_SETTINGS) + " -chart : Create chart based on the benchmark result.\n" #endif "\n" " -help : This help\n"; @@ -861,10 +991,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) { @@ -957,7 +1091,7 @@ static void qParseArgs(int argc, char *argv[]) } else if (strcmp(argv[i], "-vb") == 0) { QBenchmarkGlobalData::current->verboseOutput = true; -#ifndef QT_NO_PROCESS +#if !defined(QT_NO_PROCESS) && !defined(QT_NO_SETTINGS) } else if (strcmp(argv[i], "-chart") == 0) { QBenchmarkGlobalData::current->createChart = true; QTestLog::setLogMode(QTestLog::XML); @@ -991,6 +1125,11 @@ static void qParseArgs(int argc, char *argv[]) exit(1); } ++QTest::lastTestFuncIdx; + if (!QTest::testFuncs) { + struct Cleanup { ~Cleanup() { delete[] QTest::testFuncs; } }; + static Cleanup cleanup; + QTest::testFuncs = new TestFunction[512]; + } QTest::testFuncs[QTest::lastTestFuncIdx].function = idx; QTest::testFuncs[QTest::lastTestFuncIdx].data = data; QTEST_ASSERT(QTest::lastTestFuncIdx < 512); @@ -1006,7 +1145,7 @@ QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container) if (count == 1) return container.at(0); - + QList<QBenchmarkResult> containerCopy = container; qSort(containerCopy); @@ -1056,7 +1195,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 +1216,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 +1347,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 +1412,130 @@ 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(); +} + +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) +class FatalSignalHandler +{ +public: + FatalSignalHandler(); + ~FatalSignalHandler(); + +private: + static void signal(int); + sigset_t handledSignals; +}; + +void FatalSignalHandler::signal(int signum) +{ + qFatal("Received signal %d", signum); +} + +FatalSignalHandler::FatalSignalHandler() +{ + sigemptyset(&handledSignals); + + const int fatalSignals[] = { + SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGFPE, SIGSEGV, SIGPIPE, SIGTERM, 0 }; + + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_handler = FatalSignalHandler::signal; + + // Remove the handler after it is invoked. + act.sa_flags = SA_RESETHAND; + + // Block all fatal signals in our signal handler so we don't try to close + // the testlog twice. + sigemptyset(&act.sa_mask); + for (int i = 0; fatalSignals[i]; ++i) + sigaddset(&act.sa_mask, fatalSignals[i]); + + struct sigaction oldact; + + for (int i = 0; fatalSignals[i]; ++i) { + sigaction(fatalSignals[i], &act, &oldact); + // Don't overwrite any non-default handlers + if (oldact.sa_flags & SA_SIGINFO || oldact.sa_handler != SIG_DFL) { + sigaction(fatalSignals[i], &oldact, 0); + } else { + sigaddset(&handledSignals, fatalSignals[i]); + } + } +} + + +FatalSignalHandler::~FatalSignalHandler() +{ + // Unregister any of our remaining signal handlers + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_handler = SIG_DFL; + + struct sigaction oldact; + + for (int i = 1; i < 32; ++i) { + if (!sigismember(&handledSignals, i)) + continue; + sigaction(i, &act, &oldact); + + // If someone overwrote it in the mean time, put it back + if (oldact.sa_handler != FatalSignalHandler::signal) + sigaction(i, &oldact, 0); + } +} + +#endif + } // namespace @@ -1399,6 +1612,11 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) } #endif +#ifdef Q_OS_SYMBIAN +//### FIX THIS temporary hack to delay execution of symbian os tests. Used to get emulator to stable state before running testcase + qSleep(3000); +#endif + QTestResult::reset(); QTEST_ASSERT(testObject); @@ -1418,16 +1636,16 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) QBenchmarkValgrindUtils::cleanup(); - } else { + } else +#endif + { +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + FatalSignalHandler handler; #endif - qInvokeTestMethods(testObject); - -#ifdef QTESTLIB_USE_VALGRIND } -#endif - #ifndef QT_NO_EXCEPTIONS +#ifndef QT_NO_EXCEPTIONS } catch (...) { QTestResult::addFailure("Caught unhandled exception", __FILE__, __LINE__); if (QTestResult::currentTestFunction()) { @@ -1441,13 +1659,11 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) IOPMAssertionRelease(powerID); } #endif - #ifdef Q_OS_WIN - // rethrow exception to make debugging easier + // Rethrow exception to make debugging easier. throw; - #endif - return -1; + return 1; } - #endif +# endif currentTestObject = 0; #ifdef QT_MAC_USE_COCOA @@ -1457,26 +1673,21 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) #endif -#ifndef QT_NO_PROCESS +#if !defined(QT_NO_PROCESS) && !defined(QT_NO_SETTINGS) if (QBenchmarkGlobalData::current->createChart) { - -#define XSTR(s) STR(s) -#define STR(s) #s + QString chartLocation = QLibraryInfo::location(QLibraryInfo::BinariesPath); #ifdef Q_OS_WIN - const char * path = XSTR(QBENCHLIB_BASE) "/tools/generatereport/generatereport.exe"; + chartLocation += QLatin1String("/../tools/qtestlib/chart/release/chart.exe"); #else - const char * path = XSTR(QBENCHLIB_BASE) "/tools/generatereport/generatereport"; + chartLocation += QLatin1String("/../tools/qtestlib/chart/chart"); #endif -#undef XSTR -#undef STR - - if (QFile::exists(QLatin1String(path))) { + if (QFile::exists(chartLocation)) { QProcess p; p.setProcessChannelMode(QProcess::ForwardedChannels); - p.start(QLatin1String(path), QStringList() << QLatin1String("results.xml")); + p.start(chartLocation, QStringList() << QLatin1String("results.xml")); p.waitForFinished(-1); } else { - qWarning("Could not find %s, please make sure it is compiled.", path); + qDebug() << QLatin1String("Could not find the chart tool in ") + chartLocation + QLatin1String(", please make sure it is compiled."); } } #endif @@ -1755,7 +1966,7 @@ bool QTest::compare_helper(bool success, const char *msg, char *val1, char *val2 \internal */ template <> -bool QTest::qCompare<float>(float const &t1, float const &t2, const char *actual, const char *expected, +Q_TESTLIB_EXPORT bool QTest::qCompare<float>(float const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line) { return qFuzzyCompare(t1, t2) @@ -1768,7 +1979,7 @@ bool QTest::qCompare<float>(float const &t1, float const &t2, const char *actual \internal */ template <> -bool QTest::qCompare<double>(double const &t1, double const &t2, const char *actual, const char *expected, +Q_TESTLIB_EXPORT bool QTest::qCompare<double>(double const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line) { return qFuzzyCompare(t1, t2) @@ -1778,7 +1989,7 @@ bool QTest::qCompare<double>(double const &t1, double const &t2, const char *act } #define COMPARE_IMPL2(TYPE, FORMAT) \ -template <> char *QTest::toString<TYPE >(const TYPE &t) \ +template <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE >(const TYPE &t) \ { \ char *msg = new char[128]; \ qt_snprintf(msg, 128, #FORMAT, t); \ @@ -1800,8 +2011,8 @@ COMPARE_IMPL2(quint64, %llu) #endif COMPARE_IMPL2(bool, %d) COMPARE_IMPL2(char, %c) -COMPARE_IMPL2(float, %g); -COMPARE_IMPL2(double, %lg); +COMPARE_IMPL2(float, %g) +COMPARE_IMPL2(double, %lg) /*! \internal */ @@ -1926,8 +2137,4 @@ bool QTest::compare_string_helper(const char *t1, const char *t2, const char *ac \internal */ -/*! \fn int QTest::qt_snprintf(char *str, int size, const char *format, ...) - \internal -*/ - QT_END_NAMESPACE diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h index 06f66487..0e8a905 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -125,6 +125,7 @@ namespace QTest return 0; } + Q_TESTLIB_EXPORT char *toHexRepresentation(const char *ba, int length); Q_TESTLIB_EXPORT char *toString(const char *); Q_TESTLIB_EXPORT char *toString(const void *); @@ -178,6 +179,7 @@ namespace QTest toString<T>(t1), toString<T>(t2), actual, expected, file, line); } + template <> Q_TESTLIB_EXPORT bool qCompare<float>(float const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line); @@ -233,7 +235,7 @@ namespace QTest return qCompare<qreal>(qreal(t1), t2, actual, expected, file, line); } -#elif defined(QT_COORD_TYPE) || defined(QT_ARCH_ARM) || defined(QT_NO_FPU) || defined(QT_ARCH_WINDOWSCE) +#elif defined(QT_COORD_TYPE) || defined(QT_ARCH_ARM) || defined(QT_NO_FPU) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN) template <> inline bool qCompare<qreal, double>(qreal const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line) @@ -289,6 +291,28 @@ namespace QTest return compare_string_helper(t1, t2, actual, expected, file, line); } #else /* QTEST_NO_SPECIALIZATIONS */ + +// In Symbian we have QTEST_NO_SPECIALIZATIONS defined, but still float related specialization +// should be used. If QTEST_NO_SPECIALIZATIONS is enabled we get ambiguous overload errors. +#if defined(QT_ARCH_SYMBIAN) + template <typename T1, typename T2> + bool qCompare(T1 const &, T2 const &, const char *, const char *, const char *, int); + + template <> + inline bool qCompare<qreal, double>(qreal const &t1, double const &t2, const char *actual, + const char *expected, const char *file, int line) + { + return qCompare<float>(float(t1), float(t2), actual, expected, file, line); + } + + template <> + inline bool qCompare<double, qreal>(double const &t1, qreal const &t2, const char *actual, + const char *expected, const char *file, int line) + { + return qCompare<float>(float(t1), float(t2), actual, expected, file, line); + } +#endif + inline bool qCompare(const char *t1, const char *t2, const char *actual, const char *expected, const char *file, int line) { @@ -322,6 +346,17 @@ namespace QTest return compare_string_helper(t1, t2, actual, expected, file, line); } + // NokiaX86 and RVCT do not like implicitly comparing bool with int +#ifndef QTEST_NO_SPECIALIZATIONS + template <> +#endif + inline bool qCompare(bool const &t1, int const &t2, + const char *actual, const char *expected, const char *file, int line) + { + return qCompare<int>(int(t1), t2, actual, expected, file, line); + } + + template <class T> inline bool qTest(const T& actual, const char *elementName, const char *actualStr, const char *expected, const char *file, int line) diff --git a/src/testlib/qtestcoreelement.h b/src/testlib/qtestcoreelement.h new file mode 100644 index 0000000..b7a1dcd --- /dev/null +++ b/src/testlib/qtestcoreelement.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTCOREELEMENT_H +#define QTESTCOREELEMENT_H + +#include <QtTest/qtestcorelist.h> +#include <QtTest/qtestelementattribute.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +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", + "system-err" + }; + + 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 + +QT_END_HEADER + +#endif diff --git a/src/testlib/qtestcorelist.h b/src/testlib/qtestcorelist.h new file mode 100644 index 0000000..6a40811 --- /dev/null +++ b/src/testlib/qtestcorelist.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTCORELIST_H +#define QTESTCORELIST_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +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 + +QT_END_HEADER + +#endif diff --git a/src/testlib/qtestelement.cpp b/src/testlib/qtestelement.cpp new file mode 100644 index 0000000..9147446 --- /dev/null +++ b/src/testlib/qtestelement.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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..a569ad4 --- /dev/null +++ b/src/testlib/qtestelement.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTELEMENT_H +#define QTESTELEMENT_H + +#include <QtTest/qtestcoreelement.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +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 + +QT_END_HEADER + +#endif diff --git a/src/testlib/qtestelementattribute.cpp b/src/testlib/qtestelementattribute.cpp new file mode 100644 index 0000000..6809059 --- /dev/null +++ b/src/testlib/qtestelementattribute.cpp @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtestelementattribute.h" +#include <QtCore/qbytearray.h> +#include <string.h> +#include <stdlib.h> + +QT_BEGIN_NAMESPACE + +/*! \enum QTest::AttributeIndex + This enum numbers the different tests. + + \value AI_Undefined + + \value AI_Name + + \value AI_Result + + \value AI_Tests + + \value AI_Failures + + \value AI_Errors + + \value AI_Type + + \value AI_Description + + \value AI_PropertyValue + + \value AI_QTestVersion + + \value AI_QtVersion + + \value AI_File + + \value AI_Line + + \value AI_Metric + + \value AI_Tag + + \value AI_Value + + \value AI_Iterations +*/ + +/*! \enum QTest::LogElementType + The enum specifies the kinds of test log messages. + + \value LET_Undefined + + \value LET_Property + + \value LET_Properties + + \value LET_Failure + + \value LET_Error + + \value LET_TestCase + + \value LET_TestSuite + + \value LET_Benchmark + + \value LET_SystemError +*/ + +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..3bb41c0 --- /dev/null +++ b/src/testlib/qtestelementattribute.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTELEMENTATTRIBUTE_H +#define QTESTELEMENTATTRIBUTE_H + +#include <QtTest/qtestcorelist.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +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, + LET_SystemError = 7 + }; +} + +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 + +QT_END_HEADER + +#endif diff --git a/src/testlib/qtestevent.h b/src/testlib/qtestevent.h index d33680c..3f23162 100644 --- a/src/testlib/qtestevent.h +++ b/src/testlib/qtestevent.h @@ -71,6 +71,7 @@ public: virtual ~QTestEvent() {} }; +#ifdef QT_GUI_LIB class QTestKeyEvent: public QTestEvent { public: @@ -135,6 +136,8 @@ private: QPoint _pos; int _delay; }; +#endif //QT_GUI_LIB + class QTestDelayEvent: public QTestEvent { @@ -159,6 +162,7 @@ public: inline void clear() { qDeleteAll(*this); QList<QTestEvent *>::clear(); } +#ifdef QT_GUI_LIB inline void addKeyClick(Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) { addKeyEvent(QTest::Click, qtKey, modifiers, msecs); } inline void addKeyPress(Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) @@ -194,6 +198,7 @@ public: { append(new QTestMouseEvent(QTest::MouseDClick, button, stateKey, pos, delay)); } inline void addMouseMove(QPoint pos = QPoint(), int delay=-1) { append(new QTestMouseEvent(QTest::MouseMove, Qt::NoButton, 0, pos, delay)); } +#endif //QT_GUI_LIB inline void addDelay(int msecs) { append(new QTestDelayEvent(msecs)); } diff --git a/src/testlib/qtestevent.qdoc b/src/testlib/qtestevent.qdoc new file mode 100644 index 0000000..640c90b --- /dev/null +++ b/src/testlib/qtestevent.qdoc @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QTestEventList + \inmodule QtTest + + \brief The QTestEventList class provides a list of GUI events. + + QTestEventList inherits from QList<QTestEvent *>, and provides + convenience functions for populating the list. + + A QTestEventList can be populated with GUI events that can be + stored as test data for later usage, or be replayed on any + QWidget. + + Example: + \snippet doc/src/snippets/code/doc_src_qtestevent.qdoc 0 + + The example above simulates the user entering the character \c a + followed by a backspace, waiting for 200 milliseconds and + repeating it. +*/ + +/*! \fn QTestEventList::QTestEventList() + + Constructs an empty QTestEventList. +*/ + +/*! \fn QTestEventList::QTestEventList(const QTestEventList &other) + + Constructs a new QTestEventList as a copy of \a other. +*/ + +/*! \fn QTestEventList::~QTestEventList() + + Empties the list and destroys all stored events. +*/ + +/*! \fn void QTestEventList::clear() + + Removes all events from the list. +*/ + +/*! \fn void QTestEventList::addKeyClick(Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + + Adds a new key click to the list. The event will simulate the key \a qtKey with the modifier \a modifiers and then wait for \a msecs milliseconds. + + \sa QTest::keyClick() +*/ + +/*! \fn void QTestEventList::addKeyPress(Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + + Adds a new key press to the list. The event will press the key \a qtKey with the modifier \a modifiers and then wait for \a msecs milliseconds. + + \sa QTest::keyPress() +*/ + +/*! \fn void QTestEventList::addKeyRelease(Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + + Adds a new key release to the list. The event will release the key \a qtKey with the modifier \a modifiers and then wait for \a msecs milliseconds. + + \sa QTest::keyRelease() + +*/ + +/*! \fn void QTestEventList::addKeyEvent(QTest::KeyAction action, Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + \internal +*/ + +/*! \fn void QTestEventList::addKeyClick(char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + + \overload + + Adds a new key click to the list. The event will simulate the key \a ascii with the modifier \a modifiers and then wait for \a msecs milliseconds. + + \sa QTest::keyClick() + +*/ + +/*! \fn void QTestEventList::addKeyPress(char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + + \overload + + Adds a new key press to the list. The event will press the key \a ascii with the modifier \a modifiers and then wait for \a msecs milliseconds. + + \sa QTest::keyPress() +*/ + +/*! \fn void QTestEventList::addKeyRelease(char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + + \overload + + Adds a new key release to the list. The event will release the key \a ascii with the modifier \a modifiers and then wait for \a msecs milliseconds. + + \sa QTest::keyRelease() +*/ + +/*! \fn void QTestEventList::addKeyClicks(const QString &keys, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + + Adds new keyboard entries to the list. The event will press the \a keys with the \a modifiers and wait \a msecs milliseconds between each key. + + \sa QTest::keyClicks() +*/ + +/*! \fn void QTestEventList::addKeyEvent(QTest::KeyAction action, char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + \internal +*/ + +/*! \fn void QTestEventList::addDelay(int msecs) + + Adds a \a msecs milliseconds delay. + + \sa QTest::qWait() +*/ + +/*! \fn void QTestEventList::simulate(QWidget *w) + + Simulates the events from the list one by one on the widget \a w. + For an example, please read the \l QTestEventList class documentation. +*/ + +/*! \fn void QTestEventList::addMousePress(Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay=-1) + + Add a mouse press to the list. The event will press the \a button with optional \a modifiers at the position \a pos with an optional \a delay. The default position is the center of the widget. + + \sa QTest::mousePress() +*/ +/*! \fn void QTestEventList::addMouseRelease(Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay=-1) + + Add a mouse release to the list. The event will release the \a button with optional \a modifiers at the position \a pos with an optional \a delay. The default position is the center of the widget. + + \sa QTest::mouseRelease() +*/ +/*! \fn void QTestEventList::addMouseClick(Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay=-1) + + Add a mouse click to the list. The event will click the \a button with optional \a modifiers at the position \a pos with an optional \a delay. The default position is the center of the widget. + + \sa QTest::mouseClick() +*/ +/*! \fn void QTestEventList::addMouseDClick(Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay=-1) + + Add a double mouse click to the list. The event will double click the \a button with optional \a modifiers at the position \a pos with an optional \a delay. The default position is the center of the widget. + + \sa QTest::mousePress() +*/ +/*! \fn void QTestEventList::addMouseMove(QPoint pos = QPoint(), int delay=-1) + + Adds a mouse move to the list. The event will move the mouse to the position \a pos. If a \a delay (in milliseconds) is set, the test will wait after moving the mouse. The default position is the center of the widget. + + \sa QTest::mousePress() +*/ + diff --git a/src/testlib/qtestfilelogger.cpp b/src/testlib/qtestfilelogger.cpp new file mode 100644 index 0000000..59f211c --- /dev/null +++ b/src/testlib/qtestfilelogger.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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()); + + // Keep filenames simple + for (uint i = 0; i < sizeof(filename) && filename[i]; ++i) { + char& c = filename[i]; + if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') || c == '-' || c == '.')) { + c = '_'; + } + } + +#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..d041fe1 --- /dev/null +++ b/src/testlib/qtestfilelogger.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTFILELOGGER_H +#define QTESTFILELOGGER_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +class QTestFileLogger +{ + public: + QTestFileLogger(); + ~QTestFileLogger(); + + void init(); + void flush(const char *msg); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QTESTFILELOGGER_H diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h index 3fbe822..68fd790 100644 --- a/src/testlib/qtestkeyboard.h +++ b/src/testlib/qtestkeyboard.h @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#ifndef QTESTKEYBOARD_H +#if !defined(QTESTKEYBOARD_H) && defined(QT_GUI_LIB) #define QTESTKEYBOARD_H #if 0 diff --git a/src/testlib/qtestlightxmlstreamer.cpp b/src/testlib/qtestlightxmlstreamer.cpp new file mode 100644 index 0000000..a33c7b5 --- /dev/null +++ b/src/testlib/qtestlightxmlstreamer.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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, QTestCharBuffer *formatted) const +{ + if(!element || !formatted) + return; + + switch(element->elementType()){ + case QTest::LET_TestCase: { + QTestCharBuffer quotedTf; + QXmlTestLogger::xmlQuote("edTf, element->attributeValue(QTest::AI_Name)); + + QTest::qt_asprintf(formatted, "<TestFunction name=\"%s\">\n", quotedTf.constData()); + break; + } + case QTest::LET_Failure: { + QTestCharBuffer cdataDesc; + QXmlTestLogger::xmlCdata(&cdataDesc, element->attributeValue(QTest::AI_Description)); + + QTest::qt_asprintf(formatted, " <Description><![CDATA[%s]]></Description>\n", + cdataDesc.constData()); + break; + } + case QTest::LET_Error: { + // assuming type and attribute names don't need quoting + QTestCharBuffer quotedFile; + QTestCharBuffer cdataDesc; + QXmlTestLogger::xmlQuote("edFile, element->attributeValue(QTest::AI_File)); + QXmlTestLogger::xmlCdata(&cdataDesc, element->attributeValue(QTest::AI_Description)); + + QTest::qt_asprintf(formatted, "<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.constData(), + element->attributeName(QTest::AI_Line), + element->attributeValue(QTest::AI_Line), + cdataDesc.constData()); + break; + } + case QTest::LET_Benchmark: { + // assuming value and iterations don't need quoting + QTestCharBuffer quotedMetric; + QTestCharBuffer quotedTag; + QXmlTestLogger::xmlQuote("edMetric, element->attributeValue(QTest::AI_Metric)); + QXmlTestLogger::xmlQuote("edTag, element->attributeValue(QTest::AI_Tag)); + + QTest::qt_asprintf(formatted, "<BenchmarkResult %s=\"%s\" %s=\"%s\" %s=\"%s\" %s=\"%s\" />\n", + element->attributeName(QTest::AI_Metric), + quotedMetric.constData(), + element->attributeName(QTest::AI_Tag), + quotedTag.constData(), + element->attributeName(QTest::AI_Value), + element->attributeValue(QTest::AI_Value), + element->attributeName(QTest::AI_Iterations), + element->attributeValue(QTest::AI_Iterations) ); + break; + } + default: + formatted->data()[0] = '\0'; + } +} + +void QTestLightXmlStreamer::formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const +{ + if(!element || !formatted) + return; + + if (element->elementType() == QTest::LET_TestCase) { + if( element->attribute(QTest::AI_Result) && element->childElements()) + QTest::qt_asprintf(formatted, "</Incident>\n</TestFunction>\n"); + else + QTest::qt_asprintf(formatted, "</TestFunction>\n"); + } else { + formatted->data()[0] = '\0'; + } +} + +void QTestLightXmlStreamer::formatBeforeAttributes(const QTestElement *element, QTestCharBuffer *formatted) const +{ + if(!element || !formatted) + return; + + if (element->elementType() == QTest::LET_TestCase && element->attribute(QTest::AI_Result)) { + QTestCharBuffer buf; + QTestCharBuffer quotedFile; + QXmlTestLogger::xmlQuote("edFile, element->attributeValue(QTest::AI_File)); + + QTest::qt_asprintf(&buf, "%s=\"%s\" %s=\"%s\"", + element->attributeName(QTest::AI_File), + quotedFile.constData(), + element->attributeName(QTest::AI_Line), + element->attributeValue(QTest::AI_Line)); + + if( !element->childElements() ) + QTest::qt_asprintf(formatted, "<Incident type=\"%s\" %s/>\n", + element->attributeValue(QTest::AI_Result), buf.constData()); + else + QTest::qt_asprintf(formatted, "<Incident type=\"%s\" %s>\n", + element->attributeValue(QTest::AI_Result), buf.constData()); + } else { + formatted->data()[0] = '\0'; + } +} + +void QTestLightXmlStreamer::output(QTestElement *element) const +{ + QTestCharBuffer buf; + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", + qVersion(), QTEST_VERSION_STR ); + outputString(buf.constData()); + + QTest::qt_asprintf(&buf, "</Environment>\n"); + outputString(buf.constData()); + + QTestBasicStreamer::output(element); +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestlightxmlstreamer.h b/src/testlib/qtestlightxmlstreamer.h new file mode 100644 index 0000000..6a13b07 --- /dev/null +++ b/src/testlib/qtestlightxmlstreamer.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLIGHTXMLSTREAMER_H +#define QTESTLIGHTXMLSTREAMER_H + +#include <QtTest/qtestbasicstreamer.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +class QTestElement; +class QTestElementAttribute; + +class QTestLightXmlStreamer: public QTestBasicStreamer +{ + public: + QTestLightXmlStreamer(); + ~QTestLightXmlStreamer(); + + void formatStart(const QTestElement *element, QTestCharBuffer *formatted) const; + void formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const; + void formatBeforeAttributes(const QTestElement *element, QTestCharBuffer *formatted) const; + void output(QTestElement *element) const; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 7911343..44e62a7 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; @@ -136,7 +139,7 @@ namespace QTest { if (!counter.deref()) { QTest::testLogger->addMessage(QAbstractTestLogger::QSystem, - "Maximum amount of warnings exceeded."); + "Maximum amount of warnings exceeded. Use -maxwarnings to override."); return; } } @@ -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(); @@ -363,4 +375,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 b5c4bf4..d310910 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..409dde4 --- /dev/null +++ b/src/testlib/qtestlogger.cpp @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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), errorLogElement(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; + delete errorLogElement; + errorLogElement = new QTestElement(QTest::LET_SystemError); + 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(); + } + + currentLogElement->addLogElement(errorLogElement); + + 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: + ++failureCounter; + typeBuf = "xpass"; + break; + case QAbstractTestLogger::Pass: + ++passCounter; + typeBuf = "pass"; + break; + case QAbstractTestLogger::XFail: + ++passCounter; + typeBuf = "xfail"; + break; + case QAbstractTestLogger::Fail: + ++failureCounter; + typeBuf = "fail"; + break; + default: + typeBuf = "??????"; + break; + } + + if (type == QAbstractTestLogger::Fail || type == QAbstractTestLogger::XPass + || ((format != TLF_XunitXml) && (type == QAbstractTestLogger::XFail))) { + QTestElement *failureElement = new QTestElement(QTest::LET_Failure); + failureElement->addAttribute(QTest::AI_Result, typeBuf); + if(file) + failureElement->addAttribute(QTest::AI_File, file); + else + failureElement->addAttribute(QTest::AI_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, "xfail")) { + overwrite = (type == QAbstractTestLogger::XPass || type == QAbstractTestLogger::Fail); + } + else if (!strcmp(oldResult, "xpass")) { + 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); + + /* + Since XFAIL does not add a failure to the testlog in xunitxml, add a message, so we still + have some information about the expected failure. + */ + if (format == TLF_XunitXml && type == QAbstractTestLogger::XFail) { + QTestLogger::addMessage(QAbstractTestLogger::Info, description, file, line); + } +} + +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; + + // Also add the message to the system error log (i.e. stderr), if one exists + if (errorLogElement) { + QTestElement *systemErrorElement = new QTestElement(QTest::LET_Error); + systemErrorElement->addAttribute(QTest::AI_Description, message); + errorLogElement->addLogElement(systemErrorElement); + } +} + +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..9e0b231 --- /dev/null +++ b/src/testlib/qtestlogger_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLOGGER_P_H +#define QTESTLOGGER_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 <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; + QTestElement *errorLogElement; + 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/qtestmouse.h b/src/testlib/qtestmouse.h index b6b88a8..9d23c8b 100644 --- a/src/testlib/qtestmouse.h +++ b/src/testlib/qtestmouse.h @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#ifndef QTESTMOUSE_H +#if !defined(QTESTMOUSE_H) && defined(QT_GUI_LIB) #define QTESTMOUSE_H #if 0 diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp index a42ec3c..ee0251e 100644 --- a/src/testlib/qtestresult.cpp +++ b/src/testlib/qtestresult.cpp @@ -68,7 +68,7 @@ namespace QTest static const char *expectFailComment = 0; static int expectFailMode = 0; -}; +} void QTestResult::reset() { diff --git a/src/testlib/qtesttouch.h b/src/testlib/qtesttouch.h new file mode 100644 index 0000000..3fca394 --- /dev/null +++ b/src/testlib/qtesttouch.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTTOUCH_H +#define QTESTTOUCH_H + +#if 0 +// inform syncqt +#pragma qt_no_master_include +#endif + +#include <QtTest/qtest_global.h> +#include <QtTest/qtestassert.h> +#include <QtTest/qtestsystem.h> +#include <QtTest/qtestspontaneevent.h> + +#include <QtCore/qmap.h> +#include <QtGui/qevent.h> +#include <QtGui/qwidget.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +extern Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window, + QTouchEvent::DeviceType deviceType, + const QList<QTouchEvent::TouchPoint> &touchPoints); + +namespace QTest +{ + + class QTouchEventSequence + { + public: + ~QTouchEventSequence() + { + commit(); + points.clear(); + } + QTouchEventSequence& press(int touchId, const QPoint &pt, QWidget *widget = 0) + { + QTouchEvent::TouchPoint &p = point(touchId); + p.setScreenPos(mapToScreen(widget, pt)); + p.setState(Qt::TouchPointPressed); + return *this; + } + QTouchEventSequence& move(int touchId, const QPoint &pt, QWidget *widget = 0) + { + QTouchEvent::TouchPoint &p = point(touchId); + p.setScreenPos(mapToScreen(widget, pt)); + p.setState(Qt::TouchPointMoved); + return *this; + } + QTouchEventSequence& release(int touchId, const QPoint &pt, QWidget *widget = 0) + { + QTouchEvent::TouchPoint &p = point(touchId); + p.setScreenPos(mapToScreen(widget, pt)); + p.setState(Qt::TouchPointReleased); + return *this; + } + QTouchEventSequence& stationary(int touchId) + { + QTouchEvent::TouchPoint &p = point(touchId); + p.setState(Qt::TouchPointStationary); + return *this; + } + + private: + QTouchEventSequence(QWidget *widget, QTouchEvent::DeviceType deviceType) + : targetWidget(widget), deviceType(deviceType) + { + } + QTouchEventSequence(const QTouchEventSequence &v); + void operator=(const QTouchEventSequence&); + + QTouchEvent::TouchPoint &point(int touchId) + { + if (!points.contains(touchId)) + points[touchId] = QTouchEvent::TouchPoint(touchId); + return points[touchId]; + } + QPoint mapToScreen(QWidget *widget, const QPoint &pt) + { + if (widget) + return widget->mapToGlobal(pt); + return targetWidget ? targetWidget->mapToGlobal(pt) : pt; + } + void commit() + { + qt_translateRawTouchEvent(targetWidget, deviceType, points.values()); + targetWidget = 0; + } + + QMap<int, QTouchEvent::TouchPoint> points; + QWidget *targetWidget; + QTouchEvent::DeviceType deviceType; + friend QTouchEventSequence touchEvent(QWidget *, QTouchEvent::DeviceType); + }; + + inline + QTouchEventSequence touchEvent(QWidget *widget = 0, + QTouchEvent::DeviceType deviceType = QTouchEvent::TouchScreen) + { + return QTouchEventSequence(widget, deviceType); + } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QTESTTOUCH_H diff --git a/src/testlib/qtestxmlstreamer.cpp b/src/testlib/qtestxmlstreamer.cpp new file mode 100644 index 0000000..910e991 --- /dev/null +++ b/src/testlib/qtestxmlstreamer.cpp @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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, QTestCharBuffer *formatted) const +{ + if(!element || !formatted) + return; + + switch(element->elementType()){ + case QTest::LET_TestCase: { + QTestCharBuffer quotedTf; + QXmlTestLogger::xmlQuote("edTf, element->attributeValue(QTest::AI_Name)); + + QTest::qt_asprintf(formatted, "<TestFunction name=\"%s\">\n", quotedTf.constData()); + break; + } + case QTest::LET_Failure: { + QTestCharBuffer cdataDesc; + QXmlTestLogger::xmlCdata(&cdataDesc, element->attributeValue(QTest::AI_Description)); + + QTestCharBuffer location; + QTestCharBuffer quotedFile; + QXmlTestLogger::xmlQuote("edFile, element->attributeValue(QTest::AI_File)); + + QTest::qt_asprintf(&location, "%s=\"%s\" %s=\"%s\"", + element->attributeName(QTest::AI_File), + quotedFile.constData(), + element->attributeName(QTest::AI_Line), + element->attributeValue(QTest::AI_Line)); + + if (element->attribute(QTest::AI_Tag)) { + QTestCharBuffer cdataTag; + QXmlTestLogger::xmlCdata(&cdataTag, element->attributeValue(QTest::AI_Tag)); + QTest::qt_asprintf(formatted, "<Incident type=\"%s\" %s>\n" + " <DataTag><![CDATA[%s]]></DataTag>\n" + " <Description><![CDATA[%s]]></Description>\n" + "</Incident>\n", element->attributeValue(QTest::AI_Result), + location.constData(), cdataTag.constData(), cdataDesc.constData()); + } + else { + QTest::qt_asprintf(formatted, "<Incident type=\"%s\" %s>\n" + " <Description><![CDATA[%s]]></Description>\n" + "</Incident>\n", element->attributeValue(QTest::AI_Result), + location.constData(), cdataDesc.constData()); + } + break; + } + case QTest::LET_Error: { + // assuming type and attribute names don't need quoting + QTestCharBuffer quotedFile; + QTestCharBuffer cdataDesc; + QXmlTestLogger::xmlQuote("edFile, element->attributeValue(QTest::AI_File)); + QXmlTestLogger::xmlCdata(&cdataDesc, element->attributeValue(QTest::AI_Description)); + + QTest::qt_asprintf(formatted, "<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.constData(), + element->attributeName(QTest::AI_Line), + element->attributeValue(QTest::AI_Line), + cdataDesc.constData()); + break; + } + case QTest::LET_Benchmark: { + // assuming value and iterations don't need quoting + QTestCharBuffer quotedMetric; + QTestCharBuffer quotedTag; + QXmlTestLogger::xmlQuote("edMetric, element->attributeValue(QTest::AI_Metric)); + QXmlTestLogger::xmlQuote("edTag, element->attributeValue(QTest::AI_Tag)); + + QTest::qt_asprintf(formatted, "<BenchmarkResult %s=\"%s\" %s=\"%s\" %s=\"%s\" %s=\"%s\" />\n", + element->attributeName(QTest::AI_Metric), + quotedMetric.constData(), + element->attributeName(QTest::AI_Tag), + quotedTag.constData(), + element->attributeName(QTest::AI_Value), + element->attributeValue(QTest::AI_Value), + element->attributeName(QTest::AI_Iterations), + element->attributeValue(QTest::AI_Iterations) ); + break; + } + default: + formatted->data()[0] = '\0'; + } +} + +void QTestXmlStreamer::formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const +{ + if(!element || !formatted) + return; + + if (element->elementType() == QTest::LET_TestCase) { + QTest::qt_asprintf(formatted, "</TestFunction>\n"); + } else { + formatted->data()[0] = '\0'; + } +} + +void QTestXmlStreamer::formatBeforeAttributes(const QTestElement *element, QTestCharBuffer *formatted) const +{ + if(!element || !formatted) + return; + + if (element->elementType() == QTest::LET_TestCase && element->attribute(QTest::AI_Result)){ + QTestCharBuffer buf; + QTestCharBuffer quotedFile; + QXmlTestLogger::xmlQuote("edFile, element->attributeValue(QTest::AI_File)); + + QTest::qt_asprintf(&buf, "%s=\"%s\" %s=\"%s\"", + element->attributeName(QTest::AI_File), + quotedFile.constData(), + element->attributeName(QTest::AI_Line), + element->attributeValue(QTest::AI_Line)); + + if( !element->childElements() ) { + QTest::qt_asprintf(formatted, "<Incident type=\"%s\" %s/>\n", + element->attributeValue(QTest::AI_Result), buf.constData()); + } else { + formatted->data()[0] = '\0'; + } + } else { + formatted->data()[0] = '\0'; + } +} + +void QTestXmlStreamer::output(QTestElement *element) const +{ + QTestCharBuffer buf; + QTestCharBuffer quotedTc; + QXmlTestLogger::xmlQuote("edTc, QTestResult::currentTestObjectName()); + + QTest::qt_asprintf(&buf, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<TestCase name=\"%s\">\n", + quotedTc.constData()); + outputString(buf.constData()); + + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", + qVersion(), QTEST_VERSION_STR ); + outputString(buf.constData()); + + QTest::qt_asprintf(&buf, "</Environment>\n"); + outputString(buf.constData()); + + QTestBasicStreamer::output(element); + + QTest::qt_asprintf(&buf, "</TestCase>\n"); + outputString(buf.constData()); +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestxmlstreamer.h b/src/testlib/qtestxmlstreamer.h new file mode 100644 index 0000000..a113025 --- /dev/null +++ b/src/testlib/qtestxmlstreamer.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTXMLSTREAMER_H +#define QTESXMLSTREAMER_H + +#include <QtTest/qtestbasicstreamer.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +class QTestElement; +class QTestElementAttribute; + +class QTestXmlStreamer: public QTestBasicStreamer +{ + public: + QTestXmlStreamer(); + ~QTestXmlStreamer(); + + void formatStart(const QTestElement *element, QTestCharBuffer *formatted) const; + void formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const; + void formatBeforeAttributes(const QTestElement *element, QTestCharBuffer *formatted) const; + void output(QTestElement *element) const; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/testlib/qtestxunitstreamer.cpp b/src/testlib/qtestxunitstreamer.cpp new file mode 100644 index 0000000..e1834d0 --- /dev/null +++ b/src/testlib/qtestxunitstreamer.cpp @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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, QTestCharBuffer *formatted) const +{ + if(!element || !formatted ) + return; + + char indent[20]; + indentForElement(element, indent, sizeof(indent)); + + // Errors are written as CDATA within system-err, comments elsewhere + if (element->elementType() == QTest::LET_Error) { + if (element->parentElement()->elementType() == QTest::LET_SystemError) { + QTest::qt_asprintf(formatted, "<![CDATA["); + } else { + QTest::qt_asprintf(formatted, "%s<!--", indent); + } + return; + } + + QTest::qt_asprintf(formatted, "%s<%s", indent, element->elementName()); +} + +void QTestXunitStreamer::formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const +{ + if (!element || !formatted ) + return; + + if (!element->childElements()){ + formatted->data()[0] = '\0'; + return; + } + + char indent[20]; + indentForElement(element, indent, sizeof(indent)); + + QTest::qt_asprintf(formatted, "%s</%s>\n", indent, element->elementName()); +} + +void QTestXunitStreamer::formatAttributes(const QTestElement* element, const QTestElementAttribute *attribute, QTestCharBuffer *formatted) const +{ + if(!attribute || !formatted ) + return; + + QTest::AttributeIndex attrindex = attribute->index(); + + // For errors within system-err, we only want to output `message' + if (element && element->elementType() == QTest::LET_Error + && element->parentElement()->elementType() == QTest::LET_SystemError) { + + if (attrindex != QTest::AI_Description) return; + + QXmlTestLogger::xmlCdata(formatted, attribute->value()); + return; + } + + 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) { + QTestCharBuffer quotedValue; + QXmlTestLogger::xmlQuote("edValue, attribute->value()); + QTest::qt_asprintf(formatted, " %s=\"%s\"", key, quotedValue.constData()); + } else { + formatted->data()[0] = '\0'; + } +} + +void QTestXunitStreamer::formatAfterAttributes(const QTestElement *element, QTestCharBuffer *formatted) const +{ + if(!element || !formatted ) + return; + + // Errors are written as CDATA within system-err, comments elsewhere + if (element->elementType() == QTest::LET_Error) { + if (element->parentElement()->elementType() == QTest::LET_SystemError) { + QTest::qt_asprintf(formatted, "]]>\n"); + } else { + QTest::qt_asprintf(formatted, " -->\n"); + } + return; + } + + if(!element->childElements()) + QTest::qt_asprintf(formatted, "/>\n"); + else + QTest::qt_asprintf(formatted, ">\n"); +} + +void QTestXunitStreamer::output(QTestElement *element) const +{ + outputString("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); + QTestBasicStreamer::output(element); +} + +void QTestXunitStreamer::outputElements(QTestElement *element, bool) const +{ + QTestCharBuffer buf; + 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.data()); + + formatBeforeAttributes(element, &buf); + outputString(buf.data()); + + outputElementAttributes(element, element->attributes()); + + formatAfterAttributes(element, &buf); + outputString(buf.data()); + + if(hasChildren) + outputElements(element->childElements(), true); + + formatEnd(element, &buf); + outputString(buf.data()); + } + element = element->previousElement(); + } +} + +QT_END_NAMESPACE + diff --git a/src/testlib/qtestxunitstreamer.h b/src/testlib/qtestxunitstreamer.h new file mode 100644 index 0000000..69ec616 --- /dev/null +++ b/src/testlib/qtestxunitstreamer.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTXUNITSTREAMER_H +#define QTESTXUNITSTREAMER_H + +#include <QtTest/qtestbasicstreamer.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +class QTestLogger; + +class QTestXunitStreamer: public QTestBasicStreamer +{ + public: + QTestXunitStreamer(); + ~QTestXunitStreamer(); + + void formatStart(const QTestElement *element, QTestCharBuffer *formatted) const; + void formatEnd(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 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 + +QT_END_HEADER + +#endif diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp index 546961b..3d989bf 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,36 +91,36 @@ namespace QTest { } -QXmlTestLogger::QXmlTestLogger(XmlMode mode ): - xmlmode(mode) +QXmlTestLogger::QXmlTestLogger(XmlMode mode ) + :xmlmode(mode) { } QXmlTestLogger::~QXmlTestLogger() { - } - void QXmlTestLogger::startLogging() { QAbstractTestLogger::startLogging(); - char buf[1024]; + QTestCharBuffer buf; if (xmlmode == QXmlTestLogger::Complete) { - QTest::qt_snprintf(buf, sizeof(buf), + QTestCharBuffer quotedTc; + xmlQuote("edTc, QTestResult::currentTestObjectName()); + QTest::qt_asprintf(&buf, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" - "<TestCase name=\"%s\">\n", QTestResult::currentTestObjectName()); - outputString(buf); + "<TestCase name=\"%s\">\n", quotedTc.constData()); + outputString(buf.constData()); } - QTest::qt_snprintf(buf, sizeof(buf), + QTest::qt_asprintf(&buf, "<Environment>\n" " <QtVersion>%s</QtVersion>\n" " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n" "</Environment>\n", qVersion()); - outputString(buf); + outputString(buf.constData()); } void QXmlTestLogger::stopLogging() @@ -133,9 +134,11 @@ void QXmlTestLogger::stopLogging() void QXmlTestLogger::enterTestFunction(const char *function) { - char buf[1024]; - QTest::qt_snprintf(buf, sizeof(buf), "<TestFunction name=\"%s\">\n", function); - outputString(buf); + QTestCharBuffer buf; + QTestCharBuffer quotedFunction; + xmlQuote("edFunction, function); + QTest::qt_asprintf(&buf, "<TestFunction name=\"%s\">\n", quotedFunction.constData()); + outputString(buf.constData()); } void QXmlTestLogger::leaveTestFunction() @@ -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,80 +188,256 @@ 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]; + QTestCharBuffer buf; 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(buf, sizeof(buf), + QTestCharBuffer quotedFile; + QTestCharBuffer cdataGtag; + QTestCharBuffer cdataTag; + QTestCharBuffer cdataDescription; + + xmlQuote("edFile, file); + xmlCdata(&cdataGtag, gtag); + xmlCdata(&cdataTag, tag); + xmlCdata(&cdataDescription, description); + + QTest::qt_asprintf(&buf, QTest::incidentFormatString(QTest::isEmpty(description), notag), QTest::xmlIncidentType2String(type), - file ? file : "", line, - gtag ? gtag : "", + quotedFile.constData(), line, + cdataGtag.constData(), filler, - tag ? tag : "", - description ? description : ""); + cdataTag.constData(), + cdataDescription.constData()); - outputString(buf); + outputString(buf.constData()); } void QXmlTestLogger::addBenchmarkResult(const QBenchmarkResult &result) { - char buf[1536]; - QTest::qt_snprintf( - buf, sizeof(buf), + QTestCharBuffer buf; + QTestCharBuffer quotedMetric; + QTestCharBuffer quotedTag; + + xmlQuote("edMetric, + QBenchmarkGlobalData::current->measurer->metricText().toAscii().constData()); + xmlQuote("edTag, result.context.tag.toAscii().constData()); + + QTest::qt_asprintf( + &buf, QTest::benchmarkResultFormatString(), - QBenchmarkGlobalData::current->measurer->metricText().toAscii().data(), - result.context.tag.toAscii().data(), + quotedMetric.constData(), + quotedTag.constData(), QByteArray::number(result.value).constData(), //no 64-bit qt_snprintf support - result.iterations); - outputString(buf); + result.iterations); + outputString(buf.constData()); } void QXmlTestLogger::addMessage(MessageTypes type, const char *message, const char *file, int line) { - char buf[1536]; - char msgbuf[1024]; + QTestCharBuffer buf; 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 : ""); + QTestCharBuffer quotedFile; + QTestCharBuffer cdataGtag; + QTestCharBuffer cdataTag; + QTestCharBuffer cdataDescription; + + xmlQuote("edFile, file); + xmlCdata(&cdataGtag, gtag); + xmlCdata(&cdataTag, tag); + xmlCdata(&cdataDescription, message); - QTest::qt_snprintf(buf, sizeof(buf), + QTest::qt_asprintf(&buf, QTest::messageFormatString(QTest::isEmpty(message), notag), QTest::xmlMessageType2String(type), - file ? file : "", line, - gtag ? gtag : "", + quotedFile.constData(), line, + cdataGtag.constData(), filler, - tag ? tag : "", - msgbuf); + cdataTag.constData(), + cdataDescription.constData()); + + outputString(buf.constData()); +} - 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. +*/ +int QXmlTestLogger::xmlQuote(QTestCharBuffer* destBuf, char const* src, size_t n) +{ + if (n == 0) return 0; + + char *dest = destBuf->data(); + *dest = 0; + if (!src) return 0; + + char* begin = dest; + 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 (dest+sizeof(ent)-begin); \ + } \ + ++src; \ + break; + + MAP_ENTITY('>', ">"); + MAP_ENTITY('<', "<"); + MAP_ENTITY('\'', "'"); + MAP_ENTITY('"', """); + MAP_ENTITY('&', "&"); + + // not strictly necessary, but allows handling of comments without + // having to explicitly look for `--' + MAP_ENTITY('-', "-"); + +#undef MAP_ENTITY + + case 0: + *dest = 0; + return (dest-begin); + + default: + *dest = *src; + ++dest; + ++src; + break; + } + } + + // If we get here, dest was completely filled (dest == end) + *(dest-1) = 0; + return (dest-begin); +} + +/* + 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. +*/ +int QXmlTestLogger::xmlCdata(QTestCharBuffer *destBuf, char const* src, size_t n) +{ + if (!n) return 0; + + char *dest = destBuf->data(); + + if (!src || n == 1) { + *dest = 0; + return 0; + } + + static char const CDATA_END[] = "]]>"; + static char const CDATA_END_ESCAPED[] = "]]]><![CDATA[]>"; + + char* begin = dest; + char* end = dest + n; + while (dest < end) { + if (!*src) { + *dest = 0; + return (dest-begin); + } + + 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 (dest+sizeof(CDATA_END_ESCAPED)-begin); + } + continue; + } + + *dest = *src; + ++src; + ++dest; + } + + // If we get here, dest was completely filled (dest == end) + *(dest-1) = 0; + return (dest-begin); +} + +typedef int (*StringFormatFunction)(QTestCharBuffer*,char const*,size_t); + +/* + A wrapper for string functions written to work with a fixed size buffer so they can be called + with a dynamically allocated buffer. +*/ +int allocateStringFn(QTestCharBuffer* str, char const* src, StringFormatFunction func) +{ + static const int MAXSIZE = 1024*1024*2; + + int size = str->size(); + + int res = 0; + + for (;;) { + res = func(str, src, size); + str->data()[size - 1] = '\0'; + if (res < size) { + // We succeeded or fatally failed + break; + } + // buffer wasn't big enough, try again + size *= 2; + if (size > MAXSIZE) { + break; + } + if (!str->reset(size)) + break; // ran out of memory - bye + } + + return res; +} + +int QXmlTestLogger::xmlQuote(QTestCharBuffer* str, char const* src) +{ + return allocateStringFn(str, src, QXmlTestLogger::xmlQuote); +} + +int QXmlTestLogger::xmlCdata(QTestCharBuffer* str, char const* src) +{ + return allocateStringFn(str, src, QXmlTestLogger::xmlCdata); } QT_END_NAMESPACE diff --git a/src/testlib/qxmltestlogger_p.h b/src/testlib/qxmltestlogger_p.h index b882238..7968ea1 100644 --- a/src/testlib/qxmltestlogger_p.h +++ b/src/testlib/qxmltestlogger_p.h @@ -79,6 +79,11 @@ public: void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0); + static int xmlCdata(QTestCharBuffer *dest, char const* src); + static int xmlQuote(QTestCharBuffer *dest, char const* src); + static int xmlCdata(QTestCharBuffer *dest, char const* src, size_t n); + static int xmlQuote(QTestCharBuffer *dest, char const* src, size_t n); + private: XmlMode xmlmode; }; diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro index 90bd92d..b098c16 100644 --- a/src/testlib/testlib.pro +++ b/src/testlib/testlib.pro @@ -1,27 +1,70 @@ -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 \ + qtesttouch.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 ApplicationServices \ + -framework Security include(../qbase.pri) QMAKE_TARGET_PRODUCT = QTestLib -QMAKE_TARGET_DESCRIPTION = Qt Unit Testing Library +QMAKE_TARGET_DESCRIPTION = Qt \ + Unit \ + Testing \ + Library + +symbian:TARGET.UID3=0x2001B2DF |