diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2012-02-27 16:23:39 +0100 |
---|---|---|
committer | Samuel Rødal <samuel.rodal@nokia.com> | 2012-03-05 14:22:02 +0100 |
commit | 0f5abf0189a8f111e5a3762772f0750bac206ba8 (patch) | |
tree | 09e031f732ea5aa7e94885370e842e23549cf800 | |
parent | ce1e3fd8dc416a9a4f6550a6c139aec435e79940 (diff) |
Added auto-test for WaylandCompositor.
Change-Id: I2fda66c30736218ee847d9f6827709507c84c301
Reviewed-by: Laszlo Agocs <laszlo.p.agocs@nokia.com>
-rw-r--r-- | qtwayland.pro | 3 | ||||
-rw-r--r-- | tests/auto/auto.pro | 2 | ||||
-rw-r--r-- | tests/auto/compositor/compositor.pro | 10 | ||||
-rw-r--r-- | tests/auto/compositor/mockclient.cpp | 185 | ||||
-rw-r--r-- | tests/auto/compositor/mockclient.h | 106 | ||||
-rw-r--r-- | tests/auto/compositor/testcompositor.cpp | 54 | ||||
-rw-r--r-- | tests/auto/compositor/testcompositor.h | 53 | ||||
-rw-r--r-- | tests/auto/compositor/tst_compositor.cpp | 195 | ||||
-rw-r--r-- | tests/tests.pro | 2 |
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 |