diff options
Diffstat (limited to 'src/qmltest')
-rw-r--r-- | src/qmltest/qmltest.pro | 48 | ||||
-rw-r--r-- | src/qmltest/qtestoptions_p.h | 67 | ||||
-rw-r--r-- | src/qmltest/quicktest.cpp | 315 | ||||
-rw-r--r-- | src/qmltest/quicktest.h | 97 | ||||
-rw-r--r-- | src/qmltest/quicktestevent.cpp | 258 | ||||
-rw-r--r-- | src/qmltest/quicktestevent_p.h | 78 | ||||
-rw-r--r-- | src/qmltest/quicktestglobal.h | 73 | ||||
-rw-r--r-- | src/qmltest/quicktestresult.cpp | 630 | ||||
-rw-r--r-- | src/qmltest/quicktestresult_p.h | 179 |
9 files changed, 1745 insertions, 0 deletions
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro new file mode 100644 index 0000000000..0c3b7c825d --- /dev/null +++ b/src/qmltest/qmltest.pro @@ -0,0 +1,48 @@ +load(qt_module) + +TARGET = QtQuickTest +QPRO_PWD = $$PWD + +CONFIG += module +CONFIG += dll warn_on +MODULE_PRI += ../../modules/qt_qmltest.pri + +QT += testlib-private declarative script testlib +DEFINES += QT_BUILD_QUICK_TEST_LIB QT_NO_URL_CAST_FROM_STRING + + +include($$QT_SOURCE_TREE/src/qbase.pri) + +# Install qmltestcase.prf into the Qt mkspecs so that "CONFIG += qmltestcase" +# can be used in customer applications to build against QtQuickTest. +feature.path = $$[QT_INSTALL_DATA]/mkspecs/features +feature.files = $$PWD/features/qmltestcase.prf +INSTALLS += feature + +symbian { + DEFINES += QT_MAKEDLL + CONFIG += epocallowdlldata + contains(QT_EDITION, OpenSource) { + TARGET.CAPABILITY = LocalServices NetworkServices ReadUserData UserEnvironment WriteUserData + } else { + TARGET.CAPABILITY = All -Tcb + } +} + +INCLUDEPATH += $$PWD/QtQuickTest +INCLUDEPATH += $$PWD + +SOURCES += \ + $$PWD/quicktest.cpp \ + $$PWD/quicktestevent.cpp \ + $$PWD/quicktestresult.cpp +HEADERS += \ + $$PWD/quicktestglobal.h \ + $$PWD/quicktest.h \ + $$PWD/quicktestevent_p.h \ + $$PWD/quicktestresult_p.h \ + $$PWD/qtestoptions_p.h + + +DEFINES += QT_BUILD_QUICK_TEST_LIB + diff --git a/src/qmltest/qtestoptions_p.h b/src/qmltest/qtestoptions_p.h new file mode 100644 index 0000000000..167f906645 --- /dev/null +++ b/src/qmltest/qtestoptions_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** 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 QTESTOPTIONS_P_H +#define QTESTOPTIONS_P_H + +#include <QtTest/qtest_global.h> + +#include <QtCore/qstring.h> +#include <QtCore/qstringlist.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Test) + +namespace QTest +{ + extern Q_TESTLIB_EXPORT bool printAvailableFunctions; + extern Q_TESTLIB_EXPORT QStringList testFunctions; + extern Q_TESTLIB_EXPORT QStringList testTags; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp new file mode 100644 index 0000000000..19e15f2e5f --- /dev/null +++ b/src/qmltest/quicktest.cpp @@ -0,0 +1,315 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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 "quicktest.h" +#include "quicktestresult_p.h" +#include <QtTest/qtestsystem.h> +#include "qtestoptions_p.h" +#include <QApplication> +#include <QtDeclarative/qdeclarative.h> +#include <QtDeclarative/qdeclarativeview.h> +#include <QtDeclarative/qdeclarativeengine.h> +#include <QtDeclarative/qdeclarativecontext.h> +#if defined(QML_VERSION) && QML_VERSION >= 0x020000 +#include <QtDeclarative/qsgview.h> +#define QUICK_TEST_SCENEGRAPH 1 +#endif +#include <QtScript/qscriptvalue.h> +#include <QtScript/qscriptcontext.h> +#include <QtScript/qscriptengine.h> +#include <QtOpenGL/qgl.h> +#include <QtCore/qurl.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qdir.h> +#include <QtCore/qdiriterator.h> +#include <QtCore/qfile.h> +#include <QtCore/qdebug.h> +#include <QtCore/qeventloop.h> +#include <QtGui/qtextdocument.h> +#include <stdio.h> + +QT_BEGIN_NAMESPACE + +// Copied from qdeclarativedebughelper_p.h in Qt, to avoid a dependency +// on a private header from Qt. +class Q_DECLARATIVE_EXPORT QDeclarativeDebugHelper +{ +public: + static QScriptEngine *getScriptEngine(QDeclarativeEngine *engine); + static void setAnimationSlowDownFactor(qreal factor); + static void enableDebugging(); +}; + +class QTestRootObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool windowShown READ windowShown NOTIFY windowShownChanged) +public: + QTestRootObject(QObject *parent = 0) + : QObject(parent), hasQuit(false), m_windowShown(false) {} + + bool hasQuit; + + bool windowShown() const { return m_windowShown; } + void setWindowShown(bool value) { m_windowShown = value; emit windowShownChanged(); } + +Q_SIGNALS: + void windowShownChanged(); + +private Q_SLOTS: + void quit() { hasQuit = true; } + +private: + bool m_windowShown; +}; + +static inline QString stripQuotes(const QString &s) +{ + if (s.length() >= 2 && s.startsWith(QLatin1Char('"')) && s.endsWith(QLatin1Char('"'))) + return s.mid(1, s.length() - 2); + else + return s; +} + +int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport_create createViewport, const char *sourceDir) +{ + QApplication app(argc, argv); + + // Look for QML-specific command-line options. + // -import dir Specify an import directory. + // -input dir Specify the input directory for test cases. + // -qtquick1 Run with QtQuick 1 rather than QtQuick 2. + QStringList imports; + QString testPath; + bool qtQuick2 = true; + int outargc = 1; + int index = 1; + while (index < argc) { + if (strcmp(argv[index], "-import") == 0 && (index + 1) < argc) { + imports += stripQuotes(QString::fromLocal8Bit(argv[index + 1])); + index += 2; + } else if (strcmp(argv[index], "-input") == 0 && (index + 1) < argc) { + testPath = stripQuotes(QString::fromLocal8Bit(argv[index + 1])); + index += 2; + } else if (strcmp(argv[index], "-opengl") == 0) { + ++index; + } else if (strcmp(argv[index], "-qtquick1") == 0) { + qtQuick2 = false; + ++index; + } else if (outargc != index) { + argv[outargc++] = argv[index++]; + } else { + ++outargc; + ++index; + } + } + argv[outargc] = 0; + argc = outargc; + + // Determine where to look for the test data. + if (testPath.isEmpty() && sourceDir) + testPath = QString::fromLocal8Bit(sourceDir); + if (testPath.isEmpty()) + testPath = QLatin1String("."); + + // Scan the test data directory recursively, looking for "tst_*.qml" files. + QStringList filters; + filters += QLatin1String("tst_*.qml"); + QStringList files; + QDirIterator iter(testPath, filters, QDir::Files, + QDirIterator::Subdirectories | + QDirIterator::FollowSymlinks); + while (iter.hasNext()) + files += iter.next(); + files.sort(); + + // Bail out if we didn't find any test cases. + if (files.isEmpty()) { + qWarning() << argv[0] << ": could not find any test cases under" + << testPath; + return 1; + } + + // Parse the command-line arguments. + QuickTestResult::parseArgs(argc, argv); + QuickTestResult::setProgramName(name); + + // Scan through all of the "tst_*.qml" files and run each of them + // in turn with a QDeclarativeView. +#ifdef QUICK_TEST_SCENEGRAPH + if (qtQuick2) { + foreach (QString file, files) { + QFileInfo fi(file); + if (!fi.exists()) + continue; + QSGView view; + QTestRootObject rootobj; + QEventLoop eventLoop; + QObject::connect(view.engine(), SIGNAL(quit()), + &rootobj, SLOT(quit())); + QObject::connect(view.engine(), SIGNAL(quit()), + &eventLoop, SLOT(quit())); + view.rootContext()->setContextProperty + (QLatin1String("qtest"), &rootobj); + QScriptEngine *engine; + engine = QDeclarativeDebugHelper::getScriptEngine(view.engine()); + QScriptValue qtObject + = engine->globalObject().property(QLatin1String("Qt")); + qtObject.setProperty + (QLatin1String("qtest_wrapper"), QScriptValue(true)); + qtObject.setProperty + (QLatin1String("qtest_printAvailableFunctions"), + QScriptValue(QTest::printAvailableFunctions)); + foreach (QString path, imports) + view.engine()->addImportPath(path); + QString path = fi.absoluteFilePath(); + if (path.startsWith(QLatin1String(":/"))) + view.setSource(QUrl(QLatin1String("qrc:") + path.mid(2))); + else + view.setSource(QUrl::fromLocalFile(path)); + if (QTest::printAvailableFunctions) + continue; + if (view.status() == QSGView::Error) { + // Error compiling the test - flag failure in the log and continue. + QList<QDeclarativeError> errors = view.errors(); + QuickTestResult results; + results.setTestCaseName(fi.baseName()); + results.startLogging(); + results.setFunctionName(QLatin1String("compile")); + results.setFunctionType(QuickTestResult::Func); + results.fail(errors.at(0).description(), + errors.at(0).url().toString(), + errors.at(0).line()); + results.finishTestFunction(); + results.setFunctionName(QString()); + results.setFunctionType(QuickTestResult::NoWhere); + results.stopLogging(); + continue; + } + if (!rootobj.hasQuit) { + // If the test already quit, then it was performed + // synchronously during setSource(). Otherwise it is + // an asynchronous test and we need to show the window + // and wait for the quit indication. + view.show(); + QTest::qWaitForWindowShown(&view); + rootobj.setWindowShown(true); + if (!rootobj.hasQuit) + eventLoop.exec(); + } + } + } else +#endif + { + foreach (QString file, files) { + QFileInfo fi(file); + if (!fi.exists()) + continue; + QDeclarativeView view; + QTestRootObject rootobj; + QEventLoop eventLoop; + QObject::connect(view.engine(), SIGNAL(quit()), + &rootobj, SLOT(quit())); + QObject::connect(view.engine(), SIGNAL(quit()), + &eventLoop, SLOT(quit())); + if (createViewport) + view.setViewport((*createViewport)()); + view.rootContext()->setContextProperty + (QLatin1String("qtest"), &rootobj); + QScriptEngine *engine; + engine = QDeclarativeDebugHelper::getScriptEngine(view.engine()); + QScriptValue qtObject + = engine->globalObject().property(QLatin1String("Qt")); + qtObject.setProperty + (QLatin1String("qtest_wrapper"), QScriptValue(true)); + qtObject.setProperty + (QLatin1String("qtest_printAvailableFunctions"), + QScriptValue(QTest::printAvailableFunctions)); + foreach (QString path, imports) + view.engine()->addImportPath(path); + QString path = fi.absoluteFilePath(); + if (path.startsWith(QLatin1String(":/"))) + view.setSource(QUrl(QLatin1String("qrc:") + path.mid(2))); + else + view.setSource(QUrl::fromLocalFile(path)); + if (QTest::printAvailableFunctions) + continue; + if (view.status() == QDeclarativeView::Error) { + // Error compiling the test - flag failure in the log and continue. + QList<QDeclarativeError> errors = view.errors(); + QuickTestResult results; + results.setTestCaseName(fi.baseName()); + results.startLogging(); + results.setFunctionName(QLatin1String("compile")); + results.setFunctionType(QuickTestResult::Func); + results.fail(errors.at(0).description(), + errors.at(0).url().toString(), + errors.at(0).line()); + results.finishTestFunction(); + results.setFunctionName(QString()); + results.setFunctionType(QuickTestResult::NoWhere); + results.stopLogging(); + continue; + } + if (!rootobj.hasQuit) { + // If the test already quit, then it was performed + // synchronously during setSource(). Otherwise it is + // an asynchronous test and we need to show the window + // and wait for the quit indication. + view.show(); + QTest::qWaitForWindowShown(&view); + rootobj.setWindowShown(true); + if (!rootobj.hasQuit) + eventLoop.exec(); + } + } + } + + // Flush the current logging stream. + QuickTestResult::setProgramName(0); + + // Return the number of failures as the exit code. + return QuickTestResult::exitCode(); +} + +QT_END_NAMESPACE + +#include "quicktest.moc" diff --git a/src/qmltest/quicktest.h b/src/qmltest/quicktest.h new file mode 100644 index 0000000000..60c25ec3fb --- /dev/null +++ b/src/qmltest/quicktest.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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 QUICKTEST_H +#define QUICKTEST_H + +#include <QtQuickTest/quicktestglobal.h> +#include <QtGui/qwidget.h> +#ifdef QT_OPENGL_LIB +#include <QtOpenGL/qgl.h> +#endif + +QT_BEGIN_NAMESPACE + +typedef QWidget *(*quick_test_viewport_create)(); + +Q_QUICK_TEST_EXPORT int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport_create createViewport, const char *sourceDir); + +#ifdef QUICK_TEST_SOURCE_DIR + +#define QUICK_TEST_MAIN(name) \ + int main(int argc, char **argv) \ + { \ + return quick_test_main(argc, argv, #name, 0, QUICK_TEST_SOURCE_DIR); \ + } + +#define QUICK_TEST_OPENGL_MAIN(name) \ + static QWidget *name##_create_viewport() \ + { \ + return new QGLWidget(); \ + } \ + int main(int argc, char **argv) \ + { \ + return quick_test_main(argc, argv, #name, name##_create_viewport, QUICK_TEST_SOURCE_DIR); \ + } + +#else + +#define QUICK_TEST_MAIN(name) \ + int main(int argc, char **argv) \ + { \ + return quick_test_main(argc, argv, #name, 0, 0); \ + } + +#define QUICK_TEST_OPENGL_MAIN(name) \ + static QWidget *name##_create_viewport() \ + { \ + return new QGLWidget(); \ + } \ + int main(int argc, char **argv) \ + { \ + return quick_test_main(argc, argv, #name, name##_create_viewport, 0); \ + } + +#endif + +QT_END_NAMESPACE + +#endif diff --git a/src/qmltest/quicktestevent.cpp b/src/qmltest/quicktestevent.cpp new file mode 100644 index 0000000000..894e29efc3 --- /dev/null +++ b/src/qmltest/quicktestevent.cpp @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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 "quicktestevent_p.h" +#include <QtTest/qtestkeyboard.h> +#include <QtDeclarative/qdeclarative.h> +#include <QtDeclarative/qdeclarativeitem.h> +#include <QtDeclarative/qdeclarativeview.h> +#if defined(QML_VERSION) && QML_VERSION >= 0x020000 +#include <QtDeclarative/qsgitem.h> +#include <QtDeclarative/qsgcanvas.h> +#define QUICK_TEST_SCENEGRAPH 1 +#endif +#include <QtGui/qgraphicsscene.h> + +QT_BEGIN_NAMESPACE + +QuickTestEvent::QuickTestEvent(QObject *parent) + : QObject(parent) +{ +} + +QuickTestEvent::~QuickTestEvent() +{ +} + +bool QuickTestEvent::keyPress(int key, int modifiers, int delay) +{ + QWidget *widget = eventWidget(); + if (!widget) + return false; + QTest::keyPress(widget, Qt::Key(key), Qt::KeyboardModifiers(modifiers), delay); + return true; +} + +bool QuickTestEvent::keyRelease(int key, int modifiers, int delay) +{ + QWidget *widget = eventWidget(); + if (!widget) + return false; + QTest::keyRelease(widget, Qt::Key(key), Qt::KeyboardModifiers(modifiers), delay); + return true; +} + +bool QuickTestEvent::keyClick(int key, int modifiers, int delay) +{ + QWidget *widget = eventWidget(); + if (!widget) + return false; + QTest::keyClick(widget, Qt::Key(key), Qt::KeyboardModifiers(modifiers), delay); + return true; +} + +namespace QTest { + extern int Q_TESTLIB_EXPORT defaultMouseDelay(); +}; + +namespace QtQuickTest +{ + enum MouseAction { MousePress, MouseRelease, MouseClick, MouseDoubleClick, MouseMove }; + + static void mouseEvent(MouseAction action, QWidget *widget, + QObject *item, Qt::MouseButton button, + Qt::KeyboardModifiers stateKey, QPointF _pos, int delay=-1) + { + QTEST_ASSERT(widget); + QTEST_ASSERT(item); + + if (delay == -1 || delay < QTest::defaultMouseDelay()) + delay = QTest::defaultMouseDelay(); + if (delay > 0) + QTest::qWait(delay); + + if (action == MouseClick) { + mouseEvent(MousePress, widget, item, button, stateKey, _pos); + mouseEvent(MouseRelease, widget, item, button, stateKey, _pos); + return; + } + + QPoint pos; + QDeclarativeView *view = qobject_cast<QDeclarativeView *>(widget); + QWidget *eventWidget = widget; +#ifdef QUICK_TEST_SCENEGRAPH + QSGItem *sgitem = qobject_cast<QSGItem *>(item); + if (sgitem) { + pos = sgitem->mapToScene(_pos).toPoint(); + } else +#endif + { + QDeclarativeItem *ditem = qobject_cast<QDeclarativeItem *>(item); + if (!ditem) { + qWarning("Mouse event target is not an Item"); + return; + } + pos = view->mapFromScene(ditem->mapToScene(_pos)); + eventWidget = view->viewport(); + } + + QTEST_ASSERT(button == Qt::NoButton || button & Qt::MouseButtonMask); + QTEST_ASSERT(stateKey == 0 || stateKey & Qt::KeyboardModifierMask); + + stateKey &= static_cast<unsigned int>(Qt::KeyboardModifierMask); + + QMouseEvent me(QEvent::User, QPoint(), Qt::LeftButton, button, stateKey); + switch (action) + { + case MousePress: + me = QMouseEvent(QEvent::MouseButtonPress, pos, widget->mapToGlobal(pos), button, button, stateKey); + break; + case MouseRelease: + me = QMouseEvent(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, 0, stateKey); + break; + case MouseDoubleClick: + me = QMouseEvent(QEvent::MouseButtonDblClick, pos, widget->mapToGlobal(pos), button, button, stateKey); + break; + case MouseMove: + QCursor::setPos(widget->mapToGlobal(pos)); + qApp->processEvents(); + return; + default: + QTEST_ASSERT(false); + } + QSpontaneKeyEvent::setSpontaneous(&me); + if (!qApp->notify(eventWidget, &me)) { + static const char *mouseActionNames[] = + { "MousePress", "MouseRelease", "MouseClick", "MouseDoubleClick", "MouseMove" }; + QString warning = QString::fromLatin1("Mouse event \"%1\" not accepted by receiving widget"); + QTest::qWarn(warning.arg(QString::fromLatin1(mouseActionNames[static_cast<int>(action)])).toAscii().data()); + } + } +}; + +bool QuickTestEvent::mousePress + (QObject *item, qreal x, qreal y, int button, + int modifiers, int delay) +{ + QWidget *view = eventWidget(); + if (!view) + return false; + QtQuickTest::mouseEvent(QtQuickTest::MousePress, view, item, + Qt::MouseButton(button), + Qt::KeyboardModifiers(modifiers), + QPointF(x, y), delay); + return true; +} + +bool QuickTestEvent::mouseRelease + (QObject *item, qreal x, qreal y, int button, + int modifiers, int delay) +{ + QWidget *view = eventWidget(); + if (!view) + return false; + QtQuickTest::mouseEvent(QtQuickTest::MouseRelease, view, item, + Qt::MouseButton(button), + Qt::KeyboardModifiers(modifiers), + QPointF(x, y), delay); + return true; +} + +bool QuickTestEvent::mouseClick + (QObject *item, qreal x, qreal y, int button, + int modifiers, int delay) +{ + QWidget *view = eventWidget(); + if (!view) + return false; + QtQuickTest::mouseEvent(QtQuickTest::MouseClick, view, item, + Qt::MouseButton(button), + Qt::KeyboardModifiers(modifiers), + QPointF(x, y), delay); + return true; +} + +bool QuickTestEvent::mouseDoubleClick + (QObject *item, qreal x, qreal y, int button, + int modifiers, int delay) +{ + QWidget *view = eventWidget(); + if (!view) + return false; + QtQuickTest::mouseEvent(QtQuickTest::MouseDoubleClick, view, item, + Qt::MouseButton(button), + Qt::KeyboardModifiers(modifiers), + QPointF(x, y), delay); + return true; +} + +bool QuickTestEvent::mouseMove + (QObject *item, qreal x, qreal y, int delay) +{ + QWidget *view = eventWidget(); + if (!view) + return false; + QtQuickTest::mouseEvent(QtQuickTest::MouseMove, view, item, + Qt::NoButton, Qt::NoModifier, + QPointF(x, y), delay); + return true; +} + +QWidget *QuickTestEvent::eventWidget() +{ +#ifdef QUICK_TEST_SCENEGRAPH + QSGItem *sgitem = qobject_cast<QSGItem *>(parent()); + if (sgitem) + return sgitem->canvas(); +#endif + QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(parent()); + if (!item) + return 0; + QGraphicsScene *s = item->scene(); + if (!s) + return 0; + QList<QGraphicsView *> views = s->views(); + if (views.isEmpty()) + return 0; + return views.at(0); +} + +QT_END_NAMESPACE diff --git a/src/qmltest/quicktestevent_p.h b/src/qmltest/quicktestevent_p.h new file mode 100644 index 0000000000..1f5926f051 --- /dev/null +++ b/src/qmltest/quicktestevent_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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 QUICKTESTEVENT_P_H +#define QUICKTESTEVENT_P_H + +#include <QtQuickTest/quicktestglobal.h> +#include <QtCore/qobject.h> + +QT_BEGIN_NAMESPACE + +class Q_QUICK_TEST_EXPORT QuickTestEvent : public QObject +{ + Q_OBJECT +public: + QuickTestEvent(QObject *parent = 0); + ~QuickTestEvent(); + +public Q_SLOTS: + bool keyPress(int key, int modifiers, int delay); + bool keyRelease(int key, int modifiers, int delay); + bool keyClick(int key, int modifiers, int delay); + + bool mousePress(QObject *item, qreal x, qreal y, int button, + int modifiers, int delay); + bool mouseRelease(QObject *item, qreal x, qreal y, int button, + int modifiers, int delay); + bool mouseClick(QObject *item, qreal x, qreal y, int button, + int modifiers, int delay); + bool mouseDoubleClick(QObject *item, qreal x, qreal y, int button, + int modifiers, int delay); + bool mouseMove(QObject *item, qreal x, qreal y, int delay); + +private: + QWidget *eventWidget(); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/qmltest/quicktestglobal.h b/src/qmltest/quicktestglobal.h new file mode 100644 index 0000000000..0c71b5ce8e --- /dev/null +++ b/src/qmltest/quicktestglobal.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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 TESTQUICKGLOBAL_H +#define TESTQUICKGLOBAL_H + +#include <QtCore/qglobal.h> + +QT_LICENSED_MODULE(QtQuickTest) +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) +# if defined(QT_NODLL) +# undef QT_MAKEDLL +# undef QT_DLL +# elif defined(QT_MAKEDLL) /* create a Qt DLL library */ +# if defined(QT_DLL) +# undef QT_DLL +# endif +# if defined(QT_BUILD_QUICK_TEST_LIB) +# define Q_QUICK_TEST_EXPORT Q_DECL_EXPORT +# else +# define Q_QUICK_TEST_EXPORT Q_DECL_IMPORT +# endif +# elif defined(QT_DLL) /* use a Qt DLL library */ +# define Q_QUICK_TEST_EXPORT Q_DECL_IMPORT +# endif +#endif +#if !defined(Q_QUICK_TEST_EXPORT) +# if defined(QT_SHARED) +# define Q_QUICK_TEST_EXPORT Q_DECL_EXPORT +# else +# define Q_QUICK_TEST_EXPORT +# endif +#endif + +#endif diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp new file mode 100644 index 0000000000..59fea965e8 --- /dev/null +++ b/src/qmltest/quicktestresult.cpp @@ -0,0 +1,630 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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 "quicktestresult_p.h" +#include <QtTest/qtestcase.h> +#include <QtTest/qtestsystem.h> +#include <QtTest/private/qtestresult_p.h> +#include <QtTest/private/qtesttable_p.h> +#include <QtTest/private/qtestlog_p.h> +#include "qtestoptions_p.h" +#include <QtTest/qbenchmark.h> +#include <QtTest/private/qbenchmark_p.h> +#include <QtCore/qset.h> +#include <QtCore/qmap.h> +#include <QtCore/qbytearray.h> +#include <QtCore/qcoreapplication.h> +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +static const char *globalProgramName = 0; +static bool loggingStarted = false; +static QBenchmarkGlobalData globalBenchmarkData; + +class QuickTestResultPrivate +{ +public: + QuickTestResultPrivate() + : table(0) + , benchmarkIter(0) + , benchmarkData(0) + , iterCount(0) + { + } + ~QuickTestResultPrivate() + { + delete table; + delete benchmarkIter; + delete benchmarkData; + } + + QByteArray intern(const QString &str); + void updateTestObjectName(); + + QString testCaseName; + QString functionName; + QSet<QByteArray> internedStrings; + QTestTable *table; + QTest::QBenchmarkIterationController *benchmarkIter; + QBenchmarkTestMethodData *benchmarkData; + int iterCount; + QList<QBenchmarkResult> results; +}; + +QByteArray QuickTestResultPrivate::intern(const QString &str) +{ + QByteArray bstr = str.toUtf8(); + return *(internedStrings.insert(bstr)); +} + +void QuickTestResultPrivate::updateTestObjectName() +{ + // In plain logging mode we use the TestCase name as the + // class name so that multiple TestCase elements will report + // results with "testCase::function". In XML logging mode, + // we use the program name as the class name and report test + // functions as "testCase__function". + if (QTestLog::logMode() == QTestLog::Plain) { + if (testCaseName.isEmpty()) { + QTestResult::setCurrentTestObject(globalProgramName); + } else if (QTestLog::logMode() == QTestLog::Plain) { + QTestResult::setCurrentTestObject + (intern(testCaseName).constData()); + } + } else { + QTestResult::setCurrentTestObject(globalProgramName); + } +} + +QuickTestResult::QuickTestResult(QObject *parent) + : QObject(parent), d_ptr(new QuickTestResultPrivate) +{ + if (!QBenchmarkGlobalData::current) + QBenchmarkGlobalData::current = &globalBenchmarkData; +} + +QuickTestResult::~QuickTestResult() +{ +} + +/*! + \qmlproperty string TestResult::testCaseName + + This property defines the name of current TestCase element + that is running test cases. + + \sa functionName +*/ +QString QuickTestResult::testCaseName() const +{ + Q_D(const QuickTestResult); + return d->testCaseName; +} + +void QuickTestResult::setTestCaseName(const QString &name) +{ + Q_D(QuickTestResult); + d->testCaseName = name; + d->updateTestObjectName(); + emit testCaseNameChanged(); +} + +/*! + \qmlproperty string TestResult::functionName + + This property defines the name of current test function + within a TestCase element that is running. If this string is + empty, then no function is currently running. + + \sa testCaseName +*/ +QString QuickTestResult::functionName() const +{ + Q_D(const QuickTestResult); + return d->functionName; +} + +void QuickTestResult::setFunctionName(const QString &name) +{ + Q_D(QuickTestResult); + if (!name.isEmpty()) { + // In plain logging mode, we use the function name directly. + // In XML logging mode, we use "testCase__functionName" as the + // program name is acting as the class name. + if (QTestLog::logMode() == QTestLog::Plain || + d->testCaseName.isEmpty()) { + QTestResult::setCurrentTestFunction + (d->intern(name).constData()); + } else { + QString fullName = d->testCaseName + QLatin1String("__") + name; + QTestResult::setCurrentTestFunction + (d->intern(fullName).constData()); + } + } else { + QTestResult::setCurrentTestFunction(0); + } + d->functionName = name; + emit functionNameChanged(); +} + +QuickTestResult::FunctionType QuickTestResult::functionType() const +{ + return FunctionType(QTestResult::currentTestLocation()); +} + +void QuickTestResult::setFunctionType(FunctionType type) +{ + QTestResult::setCurrentTestLocation(QTestResult::TestLocation(type)); + emit functionTypeChanged(); +} + +/*! + \qmlproperty string TestResult::dataTag + + This property defines the tag for the current row in a + data-driven test, or an empty string if not a data-driven test. +*/ +QString QuickTestResult::dataTag() const +{ + const char *tag = QTestResult::currentDataTag(); + if (tag) + return QString::fromUtf8(tag); + else + return QString(); +} + +void QuickTestResult::setDataTag(const QString &tag) +{ + if (!tag.isEmpty()) { + QTestData *data = &(QTest::newRow(tag.toUtf8().constData())); + QTestResult::setCurrentTestData(data); + emit dataTagChanged(); + } else { + QTestResult::setCurrentTestData(0); + } +} + +/*! + \qmlproperty bool TestResult::failed + + This property returns true if the current test function has + failed; false otherwise. The fail state is reset when + functionName is changed or finishTestFunction() is called. + + \sa skipped, dataFailed +*/ +bool QuickTestResult::isFailed() const +{ + return QTestResult::testFailed(); +} + +/*! + \qmlproperty bool TestResult::dataFailed + + This property returns true if the current data function has + failed; false otherwise. The fail state is reset when + functionName is changed or finishTestFunction() is called. + + \sa failed +*/ +bool QuickTestResult::isDataFailed() const +{ + return QTestResult::currentTestFailed(); +} + +/*! + \qmlproperty bool TestResult::skipped + + This property returns true if the current test function was + marked as skipped; false otherwise. + + \sa failed +*/ +bool QuickTestResult::isSkipped() const +{ + return QTestResult::skipCurrentTest(); +} + +void QuickTestResult::setSkipped(bool skip) +{ + QTestResult::setSkipCurrentTest(skip); + emit skippedChanged(); +} + +/*! + \qmlproperty int TestResult::passCount + + This property returns the number of tests that have passed. + + \sa failCount, skipCount +*/ +int QuickTestResult::passCount() const +{ + return QTestResult::passCount(); +} + +/*! + \qmlproperty int TestResult::failCount + + This property returns the number of tests that have failed. + + \sa passCount, skipCount +*/ +int QuickTestResult::failCount() const +{ + return QTestResult::failCount(); +} + +/*! + \qmlproperty int TestResult::skipCount + + This property returns the number of tests that have been skipped. + + \sa passCount, failCount +*/ +int QuickTestResult::skipCount() const +{ + return QTestResult::skipCount(); +} + +/*! + \qmlproperty list<string> TestResult::functionsToRun + + This property returns the list of function names to be run. +*/ +QStringList QuickTestResult::functionsToRun() const +{ + return QTest::testFunctions; +} + +/*! + \qmlmethod TestResult::reset() + + Resets all pass/fail/skip counters and prepare for testing. +*/ +void QuickTestResult::reset() +{ + if (!globalProgramName) // Only if run via qmlviewer. + QTestResult::reset(); +} + +/*! + \qmlmethod TestResult::startLogging() + + Starts logging to the test output stream and writes the + test header. + + \sa stopLogging() +*/ +void QuickTestResult::startLogging() +{ + // The program name is used for logging headers and footers if it + // is set. Otherwise the test case name is used. + Q_D(QuickTestResult); + if (loggingStarted) + return; + const char *saved = QTestResult::currentTestObjectName(); + if (globalProgramName) { + QTestResult::setCurrentTestObject(globalProgramName); + } else { + QTestResult::setCurrentTestObject + (d->intern(d->testCaseName).constData()); + } + QTestLog::startLogging(); + QTestResult::setCurrentTestObject(saved); + loggingStarted = true; +} + +/*! + \qmlmethod TestResult::stopLogging() + + Writes the test footer to the test output stream and then stops logging. + + \sa startLogging() +*/ +void QuickTestResult::stopLogging() +{ + Q_D(QuickTestResult); + if (globalProgramName) + return; // Logging will be stopped by setProgramName(0). + const char *saved = QTestResult::currentTestObjectName(); + QTestResult::setCurrentTestObject(d->intern(d->testCaseName).constData()); + QTestLog::stopLogging(); + QTestResult::setCurrentTestObject(saved); +} + +void QuickTestResult::initTestTable() +{ + Q_D(QuickTestResult); + delete d->table; + d->table = new QTestTable; +} + +void QuickTestResult::clearTestTable() +{ + Q_D(QuickTestResult); + delete d->table; + d->table = 0; +} + +void QuickTestResult::finishTestFunction() +{ + QTestResult::finishedCurrentTestFunction(); +} + +static QString qtest_fixFile(const QString &file) +{ + if (file.startsWith(QLatin1String("file://"))) + return file.mid(7); + else + return file; +} + +void QuickTestResult::fail + (const QString &message, const QString &file, int line) +{ + QTestResult::addFailure(message.toLatin1().constData(), + qtest_fixFile(file).toLatin1().constData(), line); +} + +bool QuickTestResult::verify + (bool success, const QString &message, const QString &file, int line) +{ + if (!success && message.isEmpty()) { + return QTestResult::verify + (success, "verify()", "", + qtest_fixFile(file).toLatin1().constData(), line); + } else { + return QTestResult::verify + (success, message.toLatin1().constData(), "", + qtest_fixFile(file).toLatin1().constData(), line); + } +} + +bool QuickTestResult::compare + (bool success, const QString &message, + const QString &val1, const QString &val2, + const QString &file, int line) +{ + if (success) { + return QTestResult::compare + (success, message.toLocal8Bit().constData(), + qtest_fixFile(file).toLatin1().constData(), line); + } else { + return QTestResult::compare + (success, message.toLocal8Bit().constData(), + QTest::toString(val1.toLatin1().constData()), + QTest::toString(val2.toLatin1().constData()), + "", "", + qtest_fixFile(file).toLatin1().constData(), line); + } +} + +void QuickTestResult::skipSingle + (const QString &message, const QString &file, int line) +{ + QTestResult::addSkip(message.toLatin1().constData(), QTest::SkipSingle, + qtest_fixFile(file).toLatin1().constData(), line); +} + +void QuickTestResult::skipAll + (const QString &message, const QString &file, int line) +{ + QTestResult::addSkip(message.toLatin1().constData(), QTest::SkipAll, + qtest_fixFile(file).toLatin1().constData(), line); + QTestResult::setSkipCurrentTest(true); +} + +bool QuickTestResult::expectFail + (const QString &tag, const QString &comment, const QString &file, int line) +{ + return QTestResult::expectFail + (tag.toLatin1().constData(), + QTest::toString(comment.toLatin1().constData()), + QTest::Abort, qtest_fixFile(file).toLatin1().constData(), line); +} + +bool QuickTestResult::expectFailContinue + (const QString &tag, const QString &comment, const QString &file, int line) +{ + return QTestResult::expectFail + (tag.toLatin1().constData(), + QTest::toString(comment.toLatin1().constData()), + QTest::Continue, qtest_fixFile(file).toLatin1().constData(), line); +} + +void QuickTestResult::warn(const QString &message) +{ + QTestLog::warn(message.toLatin1().constData()); +} + +void QuickTestResult::ignoreWarning(const QString &message) +{ + QTestResult::ignoreMessage(QtWarningMsg, message.toLatin1().constData()); +} + +void QuickTestResult::wait(int ms) +{ + QTest::qWait(ms); +} + +void QuickTestResult::sleep(int ms) +{ + QTest::qSleep(ms); +} + +void QuickTestResult::startMeasurement() +{ + Q_D(QuickTestResult); + delete d->benchmarkData; + d->benchmarkData = new QBenchmarkTestMethodData(); + QBenchmarkTestMethodData::current = d->benchmarkData; + d->iterCount = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0; + d->results.clear(); +} + +void QuickTestResult::beginDataRun() +{ + QBenchmarkTestMethodData::current->beginDataRun(); +} + +void QuickTestResult::endDataRun() +{ + Q_D(QuickTestResult); + QBenchmarkTestMethodData::current->endDataRun(); + if (d->iterCount > -1) // iteration -1 is the warmup iteration. + d->results.append(QBenchmarkTestMethodData::current->result); + + if (QBenchmarkGlobalData::current->verboseOutput) { + if (d->iterCount == -1) { + qDebug() << "warmup stage result :" << QBenchmarkTestMethodData::current->result.value; + } else { + qDebug() << "accumulation stage result:" << QBenchmarkTestMethodData::current->result.value; + } + } +} + +bool QuickTestResult::measurementAccepted() +{ + return QBenchmarkTestMethodData::current->resultsAccepted(); +} + +static QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container) +{ + const int count = container.count(); + if (count == 0) + return QBenchmarkResult(); + + if (count == 1) + return container.at(0); + + QList<QBenchmarkResult> containerCopy = container; + qSort(containerCopy); + + const int middle = count / 2; + + // ### handle even-sized containers here by doing an aritmetic mean of the two middle items. + return containerCopy.at(middle); +} + +bool QuickTestResult::needsMoreMeasurements() +{ + Q_D(QuickTestResult); + ++(d->iterCount); + if (d->iterCount < QBenchmarkGlobalData::current->adjustMedianIterationCount()) + return true; + if (QBenchmarkTestMethodData::current->resultsAccepted()) + QTestLog::addBenchmarkResult(qMedian(d->results)); + return false; +} + +void QuickTestResult::startBenchmark(RunMode runMode, const QString &tag) +{ + QBenchmarkTestMethodData::current->result = QBenchmarkResult(); + QBenchmarkTestMethodData::current->resultAccepted = false; + QBenchmarkGlobalData::current->context.tag = tag; + QBenchmarkGlobalData::current->context.slotName = functionName(); + + Q_D(QuickTestResult); + delete d->benchmarkIter; + d->benchmarkIter = new QTest::QBenchmarkIterationController + (QTest::QBenchmarkIterationController::RunMode(runMode)); +} + +bool QuickTestResult::isBenchmarkDone() const +{ + Q_D(const QuickTestResult); + if (d->benchmarkIter) + return d->benchmarkIter->isDone(); + else + return true; +} + +void QuickTestResult::nextBenchmark() +{ + Q_D(QuickTestResult); + if (d->benchmarkIter) + d->benchmarkIter->next(); +} + +void QuickTestResult::stopBenchmark() +{ + Q_D(QuickTestResult); + delete d->benchmarkIter; + d->benchmarkIter = 0; +} + +namespace QTest { + void qtest_qParseArgs(int argc, char *argv[], bool qml); +}; + +void QuickTestResult::parseArgs(int argc, char *argv[]) +{ + if (!QBenchmarkGlobalData::current) + QBenchmarkGlobalData::current = &globalBenchmarkData; + QTest::qtest_qParseArgs(argc, argv, true); +} + +void QuickTestResult::setProgramName(const char *name) +{ + if (name) { + QTestResult::reset(); + } else if (!name && loggingStarted) { + QTestResult::setCurrentTestObject(globalProgramName); + QTestLog::stopLogging(); + QTestResult::setCurrentTestObject(0); + } + globalProgramName = name; +} + +int QuickTestResult::exitCode() +{ +#if defined(QTEST_NOEXITCODE) + return 0; +#else + // make sure our exit code is never going above 127 + // since that could wrap and indicate 0 test fails + return qMin(QTestResult::failCount(), 127); +#endif +} + +QT_END_NAMESPACE diff --git a/src/qmltest/quicktestresult_p.h b/src/qmltest/quicktestresult_p.h new file mode 100644 index 0000000000..d9ae694f10 --- /dev/null +++ b/src/qmltest/quicktestresult_p.h @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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 QUICKTESTRESULT_P_H +#define QUICKTESTRESULT_P_H + +#include <QtQuickTest/quicktestglobal.h> +#include <QtCore/qobject.h> +#include <QtCore/qstring.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qscopedpointer.h> + +QT_BEGIN_NAMESPACE + +class QuickTestResultPrivate; + +class Q_QUICK_TEST_EXPORT QuickTestResult : public QObject +{ + Q_OBJECT + Q_ENUMS(FunctionType RunMode) + Q_PROPERTY(QString testCaseName READ testCaseName WRITE setTestCaseName NOTIFY testCaseNameChanged) + Q_PROPERTY(QString functionName READ functionName WRITE setFunctionName NOTIFY functionNameChanged) + Q_PROPERTY(FunctionType functionType READ functionType WRITE setFunctionType NOTIFY functionTypeChanged) + Q_PROPERTY(QString dataTag READ dataTag WRITE setDataTag NOTIFY dataTagChanged) + Q_PROPERTY(bool failed READ isFailed) + Q_PROPERTY(bool dataFailed READ isDataFailed) + Q_PROPERTY(bool skipped READ isSkipped WRITE setSkipped NOTIFY skippedChanged) + Q_PROPERTY(int passCount READ passCount) + Q_PROPERTY(int failCount READ failCount) + Q_PROPERTY(int skipCount READ skipCount) + Q_PROPERTY(QStringList functionsToRun READ functionsToRun) +public: + QuickTestResult(QObject *parent = 0); + ~QuickTestResult(); + + // Values must match QTestResult::TestLocation. + enum FunctionType + { + NoWhere = 0, + DataFunc = 1, + InitFunc = 2, + Func = 3, + CleanupFunc = 4 + }; + + // Values must match QBenchmarkIterationController::RunMode. + enum RunMode + { + RepeatUntilValidMeasurement, + RunOnce + }; + + QString testCaseName() const; + void setTestCaseName(const QString &name); + + QString functionName() const; + void setFunctionName(const QString &name); + + FunctionType functionType() const; + void setFunctionType(FunctionType type); + + QString dataTag() const; + void setDataTag(const QString &tag); + + bool isFailed() const; + bool isDataFailed() const; + + bool isSkipped() const; + void setSkipped(bool skip); + + int passCount() const; + int failCount() const; + int skipCount() const; + + QStringList functionsToRun() const; + +public Q_SLOTS: + void reset(); + + void startLogging(); + void stopLogging(); + + void initTestTable(); + void clearTestTable(); + + void finishTestFunction(); + + void fail(const QString &message, const QString &file, int line); + bool verify(bool success, const QString &message, + const QString &file, int line); + bool compare(bool success, const QString &message, + const QString &val1, const QString &val2, + const QString &file, int line); + void skipSingle(const QString &message, const QString &file, int line); + void skipAll(const QString &message, const QString &file, int line); + bool expectFail(const QString &tag, const QString &comment, + const QString &file, int line); + bool expectFailContinue(const QString &tag, const QString &comment, + const QString &file, int line); + void warn(const QString &message); + + void ignoreWarning(const QString &message); + + void wait(int ms); + void sleep(int ms); + + void startMeasurement(); + void beginDataRun(); + void endDataRun(); + bool measurementAccepted(); + bool needsMoreMeasurements(); + + void startBenchmark(RunMode runMode, const QString &tag); + bool isBenchmarkDone() const; + void nextBenchmark(); + void stopBenchmark(); + +public: + // Helper functions for the C++ main() shell. + static void parseArgs(int argc, char *argv[]); + static void setProgramName(const char *name); + static int exitCode(); + +Q_SIGNALS: + void programNameChanged(); + void testCaseNameChanged(); + void functionNameChanged(); + void functionTypeChanged(); + void dataTagChanged(); + void skippedChanged(); + +private: + QScopedPointer<QuickTestResultPrivate> d_ptr; + + Q_DECLARE_PRIVATE(QuickTestResult) + Q_DISABLE_COPY(QuickTestResult) +}; + +QT_END_NAMESPACE + +#endif |