summaryrefslogtreecommitdiffstats
path: root/src/declarative/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/test')
-rw-r--r--src/declarative/test/qfxtestengine.cpp457
-rw-r--r--src/declarative/test/qfxtestengine.h85
-rw-r--r--src/declarative/test/qfxtestobjects.cpp348
-rw-r--r--src/declarative/test/qfxtestobjects.h212
-rw-r--r--src/declarative/test/qfxtestview.cpp79
-rw-r--r--src/declarative/test/qfxtestview.h74
-rw-r--r--src/declarative/test/test.pri9
7 files changed, 1264 insertions, 0 deletions
diff --git a/src/declarative/test/qfxtestengine.cpp b/src/declarative/test/qfxtestengine.cpp
new file mode 100644
index 0000000..70e600d
--- /dev/null
+++ b/src/declarative/test/qfxtestengine.cpp
@@ -0,0 +1,457 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QFile>
+#include <QmlComponent>
+#include <qmltimeline.h>
+#include "qfxtestengine.h"
+#include "qfxtestobjects.h"
+#include <QCryptographicHash>
+#include <QApplication>
+#include <QKeyEvent>
+#include <QSimpleCanvas>
+#include <QMouseEvent>
+#include <qmlengine.h>
+#include <private/qabstractanimation_p.h>
+#include <QAbstractAnimation>
+
+QT_BEGIN_NAMESPACE
+
+#define MAX_MISMATCHED_FRAMES 5
+#define MAX_MISMATCHED_PIXELS 5
+
+class QFxTestEnginePrivate : public QAbstractAnimation
+{
+public:
+ QFxTestEnginePrivate(QFxTestEngine *p)
+ : q(p), canvas(0), testMode(QFxTestEngine::NoTest), fullFrame(true),
+ status(Working), exitOnFail(true), mismatchedFrames(0),
+ lastFrameMismatch(false) {}
+
+ QFxTestEngine *q;
+
+ QmlEngine engine;
+ QSimpleCanvas *canvas;
+ QFxTestEngine::TestMode testMode;
+ QString testDirectory;
+
+ TestLog testData;
+ TestLog playbackTestData;
+ bool fullFrame;
+ QList<QImage> fullFrames;
+
+ virtual void updateCurrentTime(int);
+
+ void recordFrameEvent(const QImage &img);
+ void recordFullFrameEvent(const QImage &img);
+ void recordKeyEvent(QKeyEvent *e);
+ void recordMouseEvent(QMouseEvent *e);
+ void testPass();
+ void save(const QString &filename, bool = true);
+
+ enum MessageType { Success, Fail };
+ void message(MessageType t, const char *);
+
+ enum Status { Working, Failed, Passed };
+ Status status;
+ bool exitOnFail;
+
+ QList<TestObject *> toPost;
+ QSet<QEvent *> postedEvents;
+
+ // OpenGL seems to give inconsistent rendering results. We allow a small
+ // tolerance to compensate - a maximum number of mismatched frames and only
+ // one mismatch in a row
+ int mismatchedFrames;
+ bool lastFrameMismatch;
+
+ bool compare(const QImage &img1, const QImage &img2);
+
+ virtual int duration() const { return -1; }
+};
+
+bool QFxTestEnginePrivate::compare(const QImage &img1, const QImage &img2)
+{
+ if (img1.size() != img2.size())
+ return false;
+
+ int errorCount = 0;
+ for (int yy = 0; yy < img1.height(); ++yy) {
+ for (int xx = 0; xx < img1.width(); ++xx) {
+ if (img1.pixel(xx, yy) != img2.pixel(xx, yy)) {
+ errorCount++;
+ if (errorCount > MAX_MISMATCHED_PIXELS)
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+QFxTestEngine::QFxTestEngine(TestMode mode, const QString &dir,
+ QSimpleCanvas *canvas, QObject *parent)
+: QObject(parent), d(new QFxTestEnginePrivate(this))
+{
+ Q_ASSERT(canvas);
+
+ d->canvas = canvas;
+ d->start();
+
+ d->testDirectory = dir;
+ d->testMode = mode;
+ if (d->testMode == RecordTest) {
+ qWarning("QFxTestEngine: Record ON");
+ } else if (d->testMode == PlaybackTest) {
+
+ QString fileName(d->testDirectory + QLatin1String("/manifest.xml"));
+ QFile f(fileName);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning() << "QFxTestEngine: Unable to open file" << fileName;
+ return;
+ }
+
+ QByteArray data = f.readAll();
+ QmlComponent c(&d->engine, data, QUrl(d->testDirectory + QLatin1String("/manifest.xml")));
+ QObject *o = c.create();
+ TestLog *log = qobject_cast<TestLog *>(o);
+ if (log) {
+ log->setParent(this);
+ d->playbackTestData.actions() = log->actions();
+ qWarning("QFxTestEngine: Playback ON");
+ } else {
+ delete o;
+ qWarning() << "QFxTestEngine: File" << fileName << "is corrupt.";
+ return;
+ }
+ }
+
+ if (d->testMode != NoTest) {
+
+ QUnifiedTimer::instance()->setConsistentTiming(true);
+ QObject::connect(canvas, SIGNAL(framePainted()),
+ this, SLOT(framePainted()));
+
+ canvas->installEventFilter(this);
+ for (int ii = 0; ii < d->playbackTestData.actions().count(); ++ii) {
+ TestObject *o = d->playbackTestData.actions().at(ii);
+ if (TestMouse *m = qobject_cast<TestMouse *>(o))
+ d->toPost << m;
+ else if (TestKey *k = qobject_cast<TestKey *>(o))
+ d->toPost << k;
+ }
+ }
+}
+
+QFxTestEngine::~QFxTestEngine()
+{
+ delete d; d = 0;
+}
+
+void QFxTestEngine::framePainted()
+{
+ QImage img = d->canvas->asImage();
+
+ if (d->fullFrame) {
+ d->fullFrame = false;
+ d->recordFullFrameEvent(img);
+ } else {
+ d->recordFrameEvent(img);
+ }
+}
+
+void QFxTestEnginePrivate::recordFullFrameEvent(const QImage &img)
+{
+ TestFullFrame *ff = new TestFullFrame(q);
+ ff->setTime(QUnifiedTimer::instance()->elapsedTime());
+ ff->setFrameId(fullFrames.count());
+
+ fullFrames << img;
+ testData.actions() << ff;
+
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestFullFrame *pf = qobject_cast<TestFullFrame *>(playbackTestData.next());
+ QString filename = testDirectory + QLatin1String("/image") + QString::number(pf->frameId()) + QLatin1String(".png");
+ QImage recImg(filename);
+ if (!pf || !compare(recImg, img) || pf->time() != QUnifiedTimer::instance()->elapsedTime()) {
+ message(Fail, "FFrame mismatch");
+ } else {
+ message(Success, "FFrame OK");
+ }
+
+ testPass();
+ }
+}
+
+static QByteArray toHex(uchar c)
+{
+ QByteArray rv;
+ uint h = c / 16;
+ uint l = c % 16;
+ if (h >= 10)
+ rv.append(h - 10 + 'A');
+ else
+ rv.append(h + '0');
+ if (l >= 10)
+ rv.append(l - 10 + 'A');
+ else
+ rv.append(l + '0');
+ return rv;
+}
+
+void QFxTestEnginePrivate::recordFrameEvent(const QImage &img)
+{
+ QCryptographicHash hash(QCryptographicHash::Md5);
+
+ hash.addData((const char *)img.bits(), img.bytesPerLine() * img.height());
+
+ QByteArray result = hash.result();
+ QByteArray hexResult;
+ for (int ii = 0; ii < result.count(); ++ii)
+ hexResult.append(toHex(result.at(ii)));
+
+ TestFrame *f = new TestFrame(q);
+ f->setTime(QUnifiedTimer::instance()->elapsedTime());
+
+ f->setHash(QLatin1String(hexResult));
+ testData.actions() << f;
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestObject *o = playbackTestData.next();
+ TestFrame *f = qobject_cast<TestFrame *>(o);
+ if (!f || f->time() != QUnifiedTimer::instance()->elapsedTime() ||
+ f->hash() != QLatin1String(hexResult)) {
+ mismatchedFrames++;
+ if (mismatchedFrames > MAX_MISMATCHED_FRAMES ||
+ lastFrameMismatch)
+ message(Fail, "Frame mismatch");
+ else
+ message(Success, "Frame mismatch - within tolerance");
+ lastFrameMismatch = true;
+ } else {
+ message(Success, "Frame OK");
+ lastFrameMismatch = false;
+ }
+
+ testPass();
+ }
+}
+
+void QFxTestEnginePrivate::updateCurrentTime(int)
+{
+ if (status != Working)
+ return;
+
+ while(!toPost.isEmpty()) {
+ int t = QUnifiedTimer::instance()->elapsedTime();
+ TestObject *o = toPost.first();
+ if (testMode == QFxTestEngine::RecordTest)
+ o->setTime(t);
+ else if (o->time() != t)
+ return;
+ toPost.takeFirst();
+
+ if (TestMouse *m = qobject_cast<TestMouse *>(o)) {
+ QMouseEvent e((QEvent::Type)m->type(), m->pos(), m->globalPos(), (Qt::MouseButton)m->button(), (Qt::MouseButtons)m->buttons(), (Qt::KeyboardModifiers)0);
+ postedEvents.insert(&e);
+ QApplication::sendEvent(canvas, &e);
+ } else if (TestKey *k = qobject_cast<TestKey *>(o)) {
+ QKeyEvent e((QEvent::Type)k->type(), k->key(), (Qt::KeyboardModifiers)k->modifiers(), k->text());
+ postedEvents.insert(&e);
+ QApplication::sendEvent(canvas, &e);
+ }
+ }
+}
+
+bool QFxTestEngine::eventFilter(QObject *, QEvent *event)
+{
+ if (d->status != QFxTestEnginePrivate::Working)
+ return false;
+
+ if (event->type() == QEvent::MouseButtonPress ||
+ event->type() == QEvent::MouseButtonDblClick ||
+ event->type() == QEvent::MouseButtonRelease ||
+ event->type() == QEvent::MouseMove) {
+ if (d->testMode == RecordTest && d->postedEvents.contains(event)) {
+ d->postedEvents.remove(event);
+ } else {
+ d->recordMouseEvent(static_cast<QMouseEvent *>(event));
+ return d->testMode == RecordTest;
+ }
+ } else if (event->type() == QEvent::KeyPress ||
+ event->type() == QEvent::KeyRelease) {
+ QKeyEvent *key = static_cast<QKeyEvent *>(event);
+ if (key->key() < Qt::Key_F1 || key->key() > Qt::Key_F9) {
+
+ if (d->testMode == RecordTest && d->postedEvents.contains(event)) {
+ d->postedEvents.remove(event);
+ } else {
+ d->recordKeyEvent(key);
+ return d->testMode == RecordTest;
+ }
+
+ }
+ }
+
+ return false;
+}
+
+void QFxTestEnginePrivate::recordMouseEvent(QMouseEvent *e)
+{
+ TestMouse *m = new TestMouse(q);
+ m->setTime(QUnifiedTimer::instance()->elapsedTime());
+ m->setType(e->type());
+ m->setButton(e->button());
+ m->setButtons(e->buttons());
+ m->setGlobalPos(e->globalPos());
+ m->setPos(e->pos());
+ testData.actions() << m;
+
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestMouse *m = qobject_cast<TestMouse *>(playbackTestData.next());
+ if (!m || m->time() != QUnifiedTimer::instance()->elapsedTime() ||
+ m->type() != e->type() ||
+ m->button() != e->button() ||
+ m->buttons() != e->buttons() ||
+ m->globalPos() != e->globalPos() ||
+ m->pos() != e->pos())
+ message(Fail, "Mouse mismatch");
+ else
+ message(Success, "Mouse OK");
+
+ testPass();
+ } else {
+ toPost << m;
+ }
+
+}
+
+void QFxTestEnginePrivate::recordKeyEvent(QKeyEvent *e)
+{
+ TestKey *k = new TestKey(q);
+ k->setTime(QUnifiedTimer::instance()->elapsedTime());
+ k->setType(e->type());
+ k->setModifiers(e->QInputEvent::modifiers());
+ k->setText(e->text());
+ k->setKey(e->key());
+ testData.actions() << k;
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestKey *f = qobject_cast<TestKey *>(playbackTestData.next());
+ if (!f || f->time() != QUnifiedTimer::instance()->elapsedTime() ||
+ f->type() != e->type() ||
+ f->modifiers() != e->QInputEvent::modifiers() ||
+ f->text() != e->text() ||
+ f->key() != e->key())
+ message(Fail, "Key mismatch");
+ else
+ message(Success, "Key OK");
+
+ testPass();
+ } else {
+ toPost << k;
+ }
+}
+
+void QFxTestEngine::captureFullFrame()
+{
+ d->fullFrame = true;
+}
+
+void QFxTestEnginePrivate::message(MessageType t, const char *message)
+{
+ if (exitOnFail)
+ qWarning("%s", message);
+ if (t == Fail) {
+ if (exitOnFail) {
+ save(QLatin1String("manifest-fail.xml"), false);
+ qFatal("Failed");
+ } else {
+ status = Failed;
+ }
+ }
+}
+
+void QFxTestEnginePrivate::save(const QString &filename, bool images)
+{
+ qWarning() << "QFxTestEngine: Writing test data";
+
+ QFile manifest(testDirectory + QLatin1String("/") + filename);
+ manifest.open(QIODevice::WriteOnly);
+ testData.save(&manifest);
+ manifest.close();
+
+ if (images) {
+ for (int ii = 0; ii < fullFrames.count(); ++ii)
+ fullFrames.at(ii).save(testDirectory + QLatin1String("/image") + QString::number(ii) + QLatin1String(".png"));
+ }
+}
+
+void QFxTestEngine::save()
+{
+ if (d->testMode != RecordTest)
+ return;
+
+ d->save(QLatin1String("manifest.xml"));
+}
+
+void QFxTestEnginePrivate::testPass()
+{
+ if (playbackTestData.atEnd()) {
+ qWarning("Test PASSED");
+ if (exitOnFail) {
+ save(QLatin1String("manifest-play.xml"));
+ exit(0);
+ } else {
+ status = Passed;
+ }
+ }
+}
+
+bool QFxTestEngine::runTest()
+{
+ d->exitOnFail = false;
+ while(d->status == QFxTestEnginePrivate::Working)
+ QApplication::processEvents();
+ d->exitOnFail = true;
+ qWarning() << d->status;
+ return d->status == QFxTestEnginePrivate::Passed;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/test/qfxtestengine.h b/src/declarative/test/qfxtestengine.h
new file mode 100644
index 0000000..6698645
--- /dev/null
+++ b/src/declarative/test/qfxtestengine.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QFXTESTENGINE_H_
+#define _QFXTESTENGINE_H_
+
+#include <QObject>
+class QSimpleCanvas;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxTestEnginePrivate;
+class Q_DECLARATIVE_EXPORT QFxTestEngine : public QObject
+{
+Q_OBJECT
+public:
+ enum TestMode { NoTest, RecordTest, PlaybackTest };
+
+ QFxTestEngine(TestMode, const QString &,
+ QSimpleCanvas *canvas, QObject * = 0);
+ virtual ~QFxTestEngine();
+
+ void captureFullFrame();
+ void save();
+
+ bool runTest();
+
+protected:
+ virtual bool eventFilter(QObject *, QEvent *);
+
+private Q_SLOTS:
+ void framePainted();
+
+private:
+ QFxTestEnginePrivate *d;
+};
+
+#endif // _QFXTESTENGINE_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/test/qfxtestobjects.cpp b/src/declarative/test/qfxtestobjects.cpp
new file mode 100644
index 0000000..be1ab07
--- /dev/null
+++ b/src/declarative/test/qfxtestobjects.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qfxtestobjects.h"
+#include <qml.h>
+#include <QIODevice>
+
+
+QT_BEGIN_NAMESPACE
+QML_DECLARE_TYPE(TestObject);
+QML_DEFINE_TYPE(TestObject,TestObject);
+QML_DECLARE_TYPE(TestFrame);
+QML_DEFINE_TYPE(TestFrame,TestFrame);
+QML_DECLARE_TYPE(TestFullFrame);
+QML_DEFINE_TYPE(TestFullFrame,TestFullFrame);
+QML_DECLARE_TYPE(TestMouse);
+QML_DEFINE_TYPE(TestMouse,TestMouse);
+QML_DECLARE_TYPE(TestKey);
+QML_DEFINE_TYPE(TestKey,TestKey);
+QML_DECLARE_TYPE(TestLog);
+QML_DEFINE_TYPE(TestLog,TestLog);
+
+TestObject::TestObject(QObject *parent)
+: QObject(parent), _time(-1)
+{
+}
+
+int TestObject::time() const
+{
+ return _time;
+}
+
+void TestObject::setTime(int t)
+{
+ if (t == _time)
+ return;
+ _time = t;
+ emit dataChanged();
+}
+
+void TestObject::save(QXmlStreamWriter *device)
+{
+ device->writeStartElement(QLatin1String("TestObject"));
+ device->writeAttribute(QLatin1String("time"), QString::number(time()));
+ device->writeEndElement();
+}
+
+
+TestFrame::TestFrame(QObject *parent)
+: TestObject(parent)
+{
+}
+
+QString TestFrame::hash() const
+{
+ return _hash;
+}
+
+void TestFrame::setHash(const QString &h)
+{
+ if (_hash == h)
+ return;
+ _hash = h;
+ emit frameChanged();
+}
+
+void TestFrame::save(QXmlStreamWriter *device)
+{
+ device->writeStartElement(QLatin1String("TestFrame"));
+ device->writeAttribute(QLatin1String("time"), QLatin1String(QByteArray::number(time())));
+ device->writeAttribute(QLatin1String("hash"), hash());
+ device->writeEndElement();
+}
+
+TestFullFrame::TestFullFrame(QObject *parent)
+: TestObject(parent), _frameId(-1)
+{
+}
+
+int TestFullFrame::frameId() const
+{
+ return _frameId;
+}
+
+void TestFullFrame::setFrameId(int id)
+{
+ if (id == _frameId)
+ return;
+ _frameId = id;
+ emit frameChanged();
+}
+
+void TestFullFrame::save(QXmlStreamWriter *device)
+{
+ device->writeStartElement(QLatin1String("TestFullFrame"));
+ device->writeAttribute(QLatin1String("time"), QLatin1String(QByteArray::number(time())));
+ device->writeAttribute(QLatin1String("frameId"), QLatin1String(QByteArray::number(frameId())));
+ device->writeEndElement();
+}
+
+TestMouse::TestMouse(QObject *parent)
+: TestObject(parent), _type(-1), _button(-1), _buttons(-1)
+{
+}
+
+int TestMouse::type() const
+{
+ return _type;
+}
+
+void TestMouse::setType(int t)
+{
+ if (_type == t)
+ return;
+ _type = t;
+ emit mouseChanged();
+}
+
+int TestMouse::button() const
+{
+ return _button;
+}
+
+void TestMouse::setButton(int b)
+{
+ if (b == _button)
+ return;
+ _button = b;
+ emit mouseChanged();
+}
+
+int TestMouse::buttons() const
+{
+ return _buttons;
+}
+
+void TestMouse::setButtons(int buttons)
+{
+ if (_buttons == buttons)
+ return;
+ _buttons = buttons;
+ emit mouseChanged();
+}
+
+QPoint TestMouse::globalPos() const
+{
+ return _globalPos;
+}
+
+void TestMouse::setGlobalPos(const QPoint &g)
+{
+ if (_globalPos == g)
+ return;
+ _globalPos = g;
+ emit mouseChanged();
+}
+
+QPoint TestMouse::pos() const
+{
+ return _pos;
+}
+
+void TestMouse::setPos(const QPoint &p)
+{
+ if (p == _pos)
+ return;
+ _pos = p;
+ emit mouseChanged();
+}
+
+void TestMouse::save(QXmlStreamWriter *device)
+{
+ device->writeStartElement(QLatin1String("TestMouse"));
+ device->writeAttribute(QLatin1String("time"), QString::number(time()));
+ device->writeAttribute(QLatin1String("type"), QString::number(type()));
+ device->writeAttribute(QLatin1String("button"), QString::number(button()));
+ device->writeAttribute(QLatin1String("buttons"), QString::number(buttons()));
+ device->writeAttribute(QLatin1String("globalPos"), QString::number(globalPos().x()) + QLatin1String(",") + QString::number(globalPos().y()));
+ device->writeAttribute(QLatin1String("pos"), QString::number(pos().x()) + QLatin1String(",") + QString::number(pos().y()));
+ device->writeEndElement();
+}
+
+TestKey::TestKey(QObject *parent)
+: TestObject(parent), _type(-1), _modifiers(-1), _key(-1)
+{
+}
+
+int TestKey::type() const
+{
+ return _type;
+}
+
+void TestKey::setType(int t)
+{
+ if (t == _type)
+ return;
+ _type = t;
+ emit keyChanged();
+}
+
+int TestKey::modifiers() const
+{
+ return _modifiers;
+}
+
+void TestKey::setModifiers(int m)
+{
+ if (m == _modifiers)
+ return;
+ _modifiers = m;
+ emit keyChanged();
+}
+
+QString TestKey::text() const
+{
+ return _text;
+}
+
+void TestKey::setText(const QString &t)
+{
+ if (_text == t)
+ return;
+ _text = t;
+ emit keyChanged();
+}
+
+int TestKey::key() const
+{
+ return _key;
+}
+
+void TestKey::setKey(int k)
+{
+ if (_key == k)
+ return;
+ _key = k;
+ emit keyChanged();
+}
+
+void TestKey::save(QXmlStreamWriter *device)
+{
+ device->writeStartElement(QLatin1String("TestKey"));
+ device->writeAttribute(QLatin1String("time"), QString::number(time()));
+ device->writeAttribute(QLatin1String("type"), QString::number(type()));
+ device->writeAttribute(QLatin1String("modifiers"), QString::number(modifiers()));
+ device->writeAttribute(QLatin1String("key"), QString::number(key()));
+ if (key() != Qt::Key_Escape)
+ device->writeAttribute(QLatin1String("text"), text());
+ device->writeEndElement();
+}
+
+TestLog::TestLog(QObject *parent)
+: QObject(parent), _current(0)
+{
+}
+
+QList<TestObject *> *TestLog::qmlActions()
+{
+ return &_actions;
+}
+
+QList<TestObject *> &TestLog::actions()
+{
+ return _actions;
+}
+
+bool lessThan(TestObject *lhs, TestObject *rhs)
+{
+ return lhs->time() < rhs->time();
+}
+
+void TestLog::save(QIODevice *device)
+{
+ // Order correctly
+ qStableSort(_actions.begin(), _actions.end(), lessThan);
+
+ QXmlStreamWriter writer(device);
+ writer.setAutoFormatting(true);
+ writer.writeStartDocument(QLatin1String("1.0"));
+ writer.writeStartElement(QLatin1String("TestLog"));
+ for (int ii = 0; ii < _actions.count(); ++ii)
+ _actions.at(ii)->save(&writer);
+ writer.writeEndElement();
+ writer.writeEndDocument();
+}
+
+TestObject *TestLog::next()
+{
+ if (atEnd())
+ return 0;
+ TestObject *rv = _actions.at(_current);
+ _current++;
+ return rv;
+}
+
+bool TestLog::atEnd() const
+{
+ if (_current >= _actions.count())
+ return true;
+ else
+ return false;
+}
+
+int TestLog::current() const
+{
+ return _current;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/test/qfxtestobjects.h b/src/declarative/test/qfxtestobjects.h
new file mode 100644
index 0000000..4273d4e
--- /dev/null
+++ b/src/declarative/test/qfxtestobjects.h
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QFXTESTOBJECTS_H_
+#define _QFXTESTOBJECTS_H_
+
+#include <QObject>
+#include <QPoint>
+#include <QList>
+#include <QXmlStreamWriter>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QIODevice;
+class TestObject : public QObject
+{
+Q_OBJECT
+public:
+ TestObject(QObject * = 0);
+
+ Q_PROPERTY(int time READ time WRITE setTime NOTIFY dataChanged);
+ int time() const;
+ void setTime(int);
+
+ virtual void save(QXmlStreamWriter *);
+Q_SIGNALS:
+ void dataChanged();
+
+private:
+ int _time;
+};
+
+class TestFrame : public TestObject
+{
+Q_OBJECT
+public:
+ TestFrame(QObject * = 0);
+
+ Q_PROPERTY(QString hash READ hash WRITE setHash NOTIFY frameChanged);
+ QString hash() const;
+ void setHash(const QString &);
+
+ virtual void save(QXmlStreamWriter *);
+Q_SIGNALS:
+ void frameChanged();
+
+private:
+ QString _hash;
+};
+
+class TestFullFrame : public TestObject
+{
+Q_OBJECT
+public:
+ TestFullFrame(QObject * = 0);
+
+ Q_PROPERTY(int frameId READ frameId WRITE setFrameId NOTIFY frameChanged);
+ int frameId() const;
+ void setFrameId(int);
+
+ virtual void save(QXmlStreamWriter *);
+Q_SIGNALS:
+ void frameChanged();
+
+private:
+ int _frameId;
+};
+
+class TestMouse : public TestObject
+{
+Q_OBJECT
+public:
+ TestMouse(QObject * = 0);
+
+ Q_PROPERTY(int type READ type WRITE setType NOTIFY mouseChanged);
+ int type() const;
+ void setType(int);
+
+ Q_PROPERTY(int button READ button WRITE setButton NOTIFY mouseChanged);
+ int button() const;
+ void setButton(int);
+
+ Q_PROPERTY(int buttons READ buttons WRITE setButtons NOTIFY mouseChanged);
+ int buttons() const;
+ void setButtons(int);
+
+ Q_PROPERTY(QPoint globalPos READ globalPos WRITE setGlobalPos NOTIFY mouseChanged);
+ QPoint globalPos() const;
+ void setGlobalPos(const QPoint &);
+
+ Q_PROPERTY(QPoint pos READ pos WRITE setPos NOTIFY mouseChanged);
+ QPoint pos() const;
+ void setPos(const QPoint &);
+
+ virtual void save(QXmlStreamWriter *);
+
+Q_SIGNALS:
+ void mouseChanged();
+
+private:
+ int _type;
+ int _button;
+ int _buttons;
+ QPoint _globalPos;
+ QPoint _pos;
+};
+
+class TestKey : public TestObject
+{
+Q_OBJECT
+public:
+ TestKey(QObject * = 0);
+
+ Q_PROPERTY(int type READ type WRITE setType NOTIFY keyChanged);
+ int type() const;
+ void setType(int);
+
+ Q_PROPERTY(int modifiers READ modifiers WRITE setModifiers NOTIFY keyChanged);
+ int modifiers() const;
+ void setModifiers(int);
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY keyChanged);
+ QString text() const;
+ void setText(const QString &);
+
+ Q_PROPERTY(int key READ key WRITE setKey NOTIFY keyChanged);
+ int key() const;
+ void setKey(int);
+
+ virtual void save(QXmlStreamWriter *);
+
+Q_SIGNALS:
+ void keyChanged();
+
+private:
+ int _type;
+ int _modifiers;
+ int _key;
+ QString _text;
+};
+
+class TestLog : public QObject
+{
+Q_OBJECT
+public:
+ TestLog(QObject * = 0);
+
+ Q_CLASSINFO("DefaultProperty", "actions");
+ Q_PROPERTY(QList<TestObject *> *actions READ qmlActions);
+ QList<TestObject *> *qmlActions();
+
+ QList<TestObject *> &actions();
+
+ int current() const;
+ void save(QIODevice *);
+
+ TestObject *next();
+ bool atEnd() const;
+
+private:
+ int _current;
+ QList<TestObject *> _actions;
+};
+
+#endif // _QFXTESTOBJECTS_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/test/qfxtestview.cpp b/src/declarative/test/qfxtestview.cpp
new file mode 100644
index 0000000..94bcb30
--- /dev/null
+++ b/src/declarative/test/qfxtestview.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxtestview.h"
+#include <QFile>
+#include <QmlComponent>
+#include <QFileInfo>
+#include <QFxItem>
+#include <QmlContext>
+#include <QFxTestEngine>
+
+
+QT_BEGIN_NAMESPACE
+QFxTestView::QFxTestView(const QString &filename, const QString &testdir)
+: testEngine(0)
+{
+ QObject::connect(this, SIGNAL(sceneResized(QSize)),
+ this, SLOT(setSceneSize(QSize)));
+
+ testEngine = new QFxTestEngine(QFxTestEngine::PlaybackTest, testdir, this, this);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = QString::fromUtf8(file.readAll());
+ setQml(qml, filename);
+
+ execute();
+}
+
+void QFxTestView::setSceneSize(QSize s)
+{
+ setFixedSize(s);
+}
+
+bool QFxTestView::runTest()
+{
+ show();
+ return testEngine->runTest();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/test/qfxtestview.h b/src/declarative/test/qfxtestview.h
new file mode 100644
index 0000000..33275b9
--- /dev/null
+++ b/src/declarative/test/qfxtestview.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QFXTESTVIEW_H_
+#define _QFXTESTVIEW_H_
+
+#include <QFxView>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxTestEngine;
+class Q_DECLARATIVE_EXPORT QFxTestView : public QFxView
+{
+Q_OBJECT
+public:
+ QFxTestView(const QString &filename, const QString &testdir);
+
+ bool runTest();
+
+private Q_SLOTS:
+ void setSceneSize(QSize);
+
+private:
+ QFxTestEngine *testEngine;
+};
+
+#endif // _QFXTESTVIEW_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/test/test.pri b/src/declarative/test/test.pri
new file mode 100644
index 0000000..eacd00f
--- /dev/null
+++ b/src/declarative/test/test.pri
@@ -0,0 +1,9 @@
+SOURCES += \
+ test/qfxtestengine.cpp \
+ test/qfxtestobjects.cpp \
+ test/qfxtestview.cpp
+
+HEADERS += \
+ test/qfxtestengine.h \
+ test/qfxtestobjects.h \
+ test/qfxtestview.h