summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2012-02-27 16:23:39 +0100
committerSamuel Rødal <samuel.rodal@nokia.com>2012-03-05 14:22:02 +0100
commit0f5abf0189a8f111e5a3762772f0750bac206ba8 (patch)
tree09e031f732ea5aa7e94885370e842e23549cf800
parentce1e3fd8dc416a9a4f6550a6c139aec435e79940 (diff)
Added auto-test for WaylandCompositor.
Change-Id: I2fda66c30736218ee847d9f6827709507c84c301 Reviewed-by: Laszlo Agocs <laszlo.p.agocs@nokia.com>
-rw-r--r--qtwayland.pro3
-rw-r--r--tests/auto/auto.pro2
-rw-r--r--tests/auto/compositor/compositor.pro10
-rw-r--r--tests/auto/compositor/mockclient.cpp185
-rw-r--r--tests/auto/compositor/mockclient.h106
-rw-r--r--tests/auto/compositor/testcompositor.cpp54
-rw-r--r--tests/auto/compositor/testcompositor.h53
-rw-r--r--tests/auto/compositor/tst_compositor.cpp195
-rw-r--r--tests/tests.pro2
9 files changed, 609 insertions, 1 deletions
diff --git a/qtwayland.pro b/qtwayland.pro
index 2d56e733a..07dea21ab 100644
--- a/qtwayland.pro
+++ b/qtwayland.pro
@@ -10,5 +10,6 @@ module_qtcompositor_examples.depends = module_qtcompositor_src
module_qtcompositor_examples.CONFIG = no_default_target no_default_install
}
-SUBDIRS += module_qtcompositor_src \
+SUBDIRS += tests \
+ module_qtcompositor_src \
module_qtcompositor_examples \
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
new file mode 100644
index 000000000..1e1c0702f
--- /dev/null
+++ b/tests/auto/auto.pro
@@ -0,0 +1,2 @@
+TEMPLATE=subdirs
+SUBDIRS=compositor
diff --git a/tests/auto/compositor/compositor.pro b/tests/auto/compositor/compositor.pro
new file mode 100644
index 000000000..49fbc1d79
--- /dev/null
+++ b/tests/auto/compositor/compositor.pro
@@ -0,0 +1,10 @@
+CONFIG += testcase
+TARGET = tst_compositor
+
+QT += testlib
+QT += core-private gui-private compositor
+
+LIBS += -lwayland-client
+
+SOURCES += tst_compositor.cpp testcompositor.cpp mockclient.cpp
+HEADERS += testcompositor.h mockclient.h
diff --git a/tests/auto/compositor/mockclient.cpp b/tests/auto/compositor/mockclient.cpp
new file mode 100644
index 000000000..f47f25339
--- /dev/null
+++ b/tests/auto/compositor/mockclient.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mockclient.h"
+
+#include <QElapsedTimer>
+#include <QSocketNotifier>
+
+#include <private/qguiapplication_p.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+
+MockClient::MockClient()
+ : display(wl_display_connect(0))
+ , compositor(0)
+ , output(0)
+{
+ if (!display)
+ qFatal("MockClient(): wl_display_connect() failed");
+
+ wl_display_add_global_listener(display, handleGlobal, this);
+
+ fd = wl_display_get_fd(display, sourceUpdate, 0);
+
+ QSocketNotifier *readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+ connect(readNotifier, SIGNAL(activated(int)), this, SLOT(readEvents()));
+
+ QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
+ connect(dispatcher, SIGNAL(awake()), this, SLOT(flushDisplay()));
+
+ QElapsedTimer timeout;
+ timeout.start();
+ do {
+ QCoreApplication::processEvents();
+ } while (!(compositor && output) && timeout.elapsed() < 1000);
+
+ if (!compositor || !output)
+ qFatal("MockClient(): failed to receive globals from display");
+}
+
+const wl_output_listener MockClient::outputListener = {
+ MockClient::outputGeometryEvent,
+ MockClient::outputModeEvent
+};
+
+MockClient::~MockClient()
+{
+ wl_display_disconnect(display);
+}
+
+void MockClient::handleGlobal(wl_display *, uint32_t id, const char *interface, uint32_t, void *data)
+{
+ resolve(data)->handleGlobal(id, QByteArray(interface));
+}
+
+int MockClient::sourceUpdate(uint32_t, void *)
+{
+ return 0;
+}
+
+void MockClient::outputGeometryEvent(void *data, wl_output *,
+ int32_t x, int32_t y,
+ int32_t width, int32_t height,
+ int, const char *, const char *)
+{
+ resolve(data)->geometry = QRect(x, y, width, height);
+}
+
+void MockClient::outputModeEvent(void *, wl_output *, uint32_t,
+ int, int, int)
+{
+}
+
+void MockClient::readEvents()
+{
+ wl_display_iterate(display, WL_DISPLAY_READABLE);
+}
+
+void MockClient::flushDisplay()
+{
+ wl_display_flush(display);
+}
+
+void MockClient::handleGlobal(uint32_t id, const QByteArray &interface)
+{
+ if (interface == "wl_compositor") {
+ compositor = static_cast<wl_compositor *>(wl_display_bind(display, id, &wl_compositor_interface));
+ } else if (interface == "wl_output") {
+ output = static_cast<wl_output *>(wl_display_bind(display, id, &wl_output_interface));
+ wl_output_add_listener(output, &outputListener, this);
+ } else if (interface == "wl_shm") {
+ shm = static_cast<wl_shm *>(wl_display_bind(display, id, &wl_shm_interface));
+ }
+}
+
+wl_surface *MockClient::createSurface()
+{
+ flushDisplay();
+ return wl_compositor_create_surface(compositor);
+}
+
+ShmBuffer::ShmBuffer(const QSize &size, wl_shm *shm)
+ : handle(0)
+{
+ int stride = size.width() * 4;
+ int alloc = stride * size.height();
+
+ char filename[] = "/tmp/wayland-shm-XXXXXX";
+
+ int fd = mkstemp(filename);
+ if (fd < 0) {
+ qWarning("open %s failed: %s", filename, strerror(errno));
+ return;
+ }
+
+ if (ftruncate(fd, alloc) < 0) {
+ qWarning("ftruncate failed: %s", strerror(errno));
+ close(fd);
+ return;
+ }
+
+ void *data = mmap(0, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ unlink(filename);
+
+ if (data == MAP_FAILED) {
+ qWarning("mmap failed: %s", strerror(errno));
+ close(fd);
+ return;
+ }
+
+ image = QImage(static_cast<uchar *>(data), size.width(), size.height(), stride, QImage::Format_ARGB32_Premultiplied);
+ handle = wl_shm_create_buffer(shm,fd, size.width(), size.height(),
+ stride, WL_SHM_FORMAT_ARGB8888);
+ close(fd);
+}
+
+ShmBuffer::~ShmBuffer()
+{
+ munmap(image.bits(), image.byteCount());
+ wl_buffer_destroy(handle);
+}
+
diff --git a/tests/auto/compositor/mockclient.h b/tests/auto/compositor/mockclient.h
new file mode 100644
index 000000000..2f2f665cd
--- /dev/null
+++ b/tests/auto/compositor/mockclient.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "wayland-client.h"
+
+#include <QObject>
+#include <QImage>
+#include <QRect>
+
+class ShmBuffer
+{
+public:
+ ShmBuffer(const QSize &size, wl_shm *shm);
+ ~ShmBuffer();
+
+ wl_buffer *handle;
+ QImage image;
+};
+
+class MockClient : public QObject
+{
+ Q_OBJECT
+
+public:
+ MockClient();
+ ~MockClient();
+
+ wl_surface *createSurface();
+
+ wl_display *display;
+ wl_compositor *compositor;
+ wl_output *output;
+ wl_shm *shm;
+
+ QRect geometry;
+
+ int fd;
+
+private slots:
+ void readEvents();
+ void flushDisplay();
+
+private:
+ static MockClient *resolve(void *data) { return static_cast<MockClient *>(data); }
+
+ static void handleGlobal(wl_display *display, uint32_t id, const char *interface, uint32_t, void *data);
+ static int sourceUpdate(uint32_t mask, void *data);
+
+ static void outputGeometryEvent(void *data,
+ wl_output *output,
+ int32_t x, int32_t y,
+ int32_t width, int32_t height,
+ int subpixel,
+ const char *make,
+ const char *model);
+
+ static void outputModeEvent(void *data,
+ wl_output *wl_output,
+ uint32_t flags,
+ int width,
+ int height,
+ int refresh);
+
+ void handleGlobal(uint32_t id, const QByteArray &interface);
+
+ static const wl_output_listener outputListener;
+};
+
diff --git a/tests/auto/compositor/testcompositor.cpp b/tests/auto/compositor/testcompositor.cpp
new file mode 100644
index 000000000..f222ba76e
--- /dev/null
+++ b/tests/auto/compositor/testcompositor.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "testcompositor.h"
+
+void TestCompositor::surfaceCreated(WaylandSurface *surface)
+{
+ surfaces << surface;
+}
+
+void TestCompositor::surfaceAboutToBeDestroyed(WaylandSurface *surface)
+{
+ surfaces.removeOne(surface);
+}
+
+
diff --git a/tests/auto/compositor/testcompositor.h b/tests/auto/compositor/testcompositor.h
new file mode 100644
index 000000000..580d733a6
--- /dev/null
+++ b/tests/auto/compositor/testcompositor.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "waylandcompositor.h"
+#include "waylandsurface.h"
+
+class TestCompositor : public WaylandCompositor
+{
+public:
+ void surfaceCreated(WaylandSurface *surface);
+ void surfaceAboutToBeDestroyed(WaylandSurface *surface);
+
+ QList<WaylandSurface *> surfaces;
+};
+
diff --git a/tests/auto/compositor/tst_compositor.cpp b/tests/auto/compositor/tst_compositor.cpp
new file mode 100644
index 000000000..0e632c4d1
--- /dev/null
+++ b/tests/auto/compositor/tst_compositor.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mockclient.h"
+#include "testcompositor.h"
+
+#include <QtTest/QtTest>
+
+class tst_WaylandCompositor : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_WaylandCompositor() {
+ setenv("XDG_RUNTIME_DIR", ".", 1);
+ }
+
+private slots:
+ void singleClient();
+ void multipleClients();
+ void geometry();
+ void mapSurface();
+ void frameCallback();
+};
+
+void tst_WaylandCompositor::singleClient()
+{
+ TestCompositor compositor;
+
+ MockClient client;
+
+ wl_surface *sa = client.createSurface();
+ QTRY_COMPARE(compositor.surfaces.size(), 1);
+
+ wl_surface *sb = client.createSurface();
+ QTRY_COMPARE(compositor.surfaces.size(), 2);
+
+ wl_surface_destroy(sa);
+ QTRY_COMPARE(compositor.surfaces.size(), 1);
+
+ wl_surface_destroy(sb);
+ QTRY_COMPARE(compositor.surfaces.size(), 0);
+}
+
+void tst_WaylandCompositor::multipleClients()
+{
+ TestCompositor compositor;
+
+ MockClient a;
+ MockClient b;
+ MockClient c;
+
+ wl_surface *sa = a.createSurface();
+ wl_surface *sb = b.createSurface();
+ wl_surface *sc = c.createSurface();
+
+ QTRY_COMPARE(compositor.surfaces.size(), 3);
+
+ wl_surface_destroy(sa);
+ wl_surface_destroy(sb);
+ wl_surface_destroy(sc);
+
+ QTRY_COMPARE(compositor.surfaces.size(), 0);
+}
+
+void tst_WaylandCompositor::geometry()
+{
+ TestCompositor compositor;
+
+ QRect geometry(0, 0, 4096, 3072);
+ compositor.setOutputGeometry(geometry);
+
+ MockClient client;
+
+ QTRY_COMPARE(client.geometry, geometry);
+}
+
+void tst_WaylandCompositor::mapSurface()
+{
+ TestCompositor compositor;
+
+ MockClient client;
+
+ wl_surface *surface = client.createSurface();
+ QTRY_COMPARE(compositor.surfaces.size(), 1);
+
+ WaylandSurface *waylandSurface = compositor.surfaces.at(0);
+
+ QSignalSpy mappedSpy(waylandSurface, SIGNAL(mapped()));
+
+ QCOMPARE(waylandSurface->size(), QSize());
+ QCOMPARE(waylandSurface->type(), WaylandSurface::Invalid);
+
+ QSize size(256, 256);
+ ShmBuffer buffer(size, client.shm);
+
+ wl_surface_attach(surface, buffer.handle, 0, 0);
+ wl_surface_damage(surface, 0, 0, size.width(), size.height());
+
+ QTRY_COMPARE(waylandSurface->size(), size);
+ QTRY_COMPARE(waylandSurface->type(), WaylandSurface::Shm);
+ QTRY_COMPARE(mappedSpy.count(), 1);
+
+ wl_surface_destroy(surface);
+}
+
+static void frameCallbackFunc(void *data, wl_callback *callback, uint32_t)
+{
+ ++*static_cast<int *>(data);
+ wl_callback_destroy(callback);
+}
+
+static void registerFrameCallback(wl_surface *surface, int *counter)
+{
+ static const wl_callback_listener frameCallbackListener = {
+ frameCallbackFunc
+ };
+
+ wl_callback_add_listener(wl_surface_frame(surface), &frameCallbackListener, counter);
+}
+
+void tst_WaylandCompositor::frameCallback()
+{
+ TestCompositor compositor;
+
+ MockClient client;
+
+ QSize size(8, 8);
+ ShmBuffer buffer(size, client.shm);
+
+ wl_surface *surface = client.createSurface();
+ wl_surface_attach(surface, buffer.handle, 0, 0);
+
+ int frameCounter = 0;
+
+ QTRY_COMPARE(compositor.surfaces.size(), 1);
+ WaylandSurface *waylandSurface = compositor.surfaces.at(0);
+ QSignalSpy damagedSpy(waylandSurface, SIGNAL(damaged(const QRect &)));
+
+ for (int i = 0; i < 10; ++i) {
+ registerFrameCallback(surface, &frameCounter);
+ wl_surface_damage(surface, 0, 0, size.width(), size.height());
+
+ QTRY_COMPARE(waylandSurface->type(), WaylandSurface::Shm);
+ QTRY_COMPARE(damagedSpy.count(), i + 1);
+
+ QCOMPARE(waylandSurface->image(), buffer.image);
+ waylandSurface->frameFinished();
+
+ QTRY_COMPARE(frameCounter, i + 1);
+ }
+
+ wl_surface_destroy(surface);
+}
+
+#include <tst_compositor.moc>
+QTEST_MAIN(tst_WaylandCompositor);
diff --git a/tests/tests.pro b/tests/tests.pro
new file mode 100644
index 000000000..85e4f3a53
--- /dev/null
+++ b/tests/tests.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += auto