summaryrefslogtreecommitdiffstats
path: root/tests/auto/client/shared/corecompositor.h
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/client/shared/corecompositor.h')
-rw-r--r--tests/auto/client/shared/corecompositor.h209
1 files changed, 209 insertions, 0 deletions
diff --git a/tests/auto/client/shared/corecompositor.h b/tests/auto/client/shared/corecompositor.h
new file mode 100644
index 000000000..875b7d050
--- /dev/null
+++ b/tests/auto/client/shared/corecompositor.h
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MOCKCOMPOSITOR_CORECOMPOSITOR_H
+#define MOCKCOMPOSITOR_CORECOMPOSITOR_H
+
+#include <QtTest/QtTest>
+
+#include <wayland-server-core.h>
+
+struct wl_resource;
+
+namespace MockCompositor {
+
+class Global : public QObject
+{
+ Q_OBJECT
+public:
+ virtual bool isClean() { return true; }
+ virtual QString dirtyMessage() { return isClean() ? "clean" : "dirty"; }
+};
+
+class CoreCompositor
+{
+public:
+ explicit CoreCompositor();
+ ~CoreCompositor();
+ bool isClean();
+ QString dirtyMessage();
+ void dispatch();
+
+ template<typename function_type, typename... arg_types>
+ auto exec(function_type func, arg_types&&... args) -> decltype(func())
+ {
+ Lock lock(this);
+ return func(std::forward<arg_types>(args)...);
+ }
+
+ template<typename function_type, typename... arg_types>
+ auto call(function_type func, arg_types&&... args) -> decltype(func())
+ {
+ Lock lock(this);
+ auto boundFunc = std::bind(func, this);
+ return boundFunc(this, std::forward<arg_types>(args)...);
+ }
+
+ // Unsafe section below, YOU are responsible that the compositor is locked or
+ // this is run through the mutex() method!
+
+ void add(Global *global);
+ void remove(Global *global);
+
+ /*!
+ * \brief Constructs and adds a new global with the given parameters
+ *
+ * Convenience function. i.e.
+ *
+ * compositor->add(new MyGlobal(compositor, version);
+ *
+ * can be written as:
+ *
+ * compositor->add<MyGlobal>(version);
+ *
+ * Returns the new global
+ */
+ template<typename global_type, typename... arg_types>
+ global_type *add(arg_types&&... args)
+ {
+ warnIfNotLockedByThread(Q_FUNC_INFO);
+ auto *global = new global_type(this, std::forward<arg_types>(args)...);
+ m_globals.append(global);
+ return global;
+ }
+
+ /*!
+ * \brief Removes all globals of the given type
+ *
+ * Convenience function
+ */
+ template<typename global_type, typename... arg_types>
+ void removeAll()
+ {
+ const auto globals = getAll<global_type>();
+ for (auto global : globals)
+ remove(global);
+ }
+
+ /*!
+ * \brief Returns a global with the given type, if any
+ */
+ template<typename global_type>
+ global_type *get()
+ {
+ warnIfNotLockedByThread(Q_FUNC_INFO);
+ for (auto *global : qAsConst(m_globals)) {
+ if (auto *casted = qobject_cast<global_type *>(global))
+ return casted;
+ }
+ return nullptr;
+ }
+
+ /*!
+ * \brief Returns all globals with the given type, if any
+ */
+ template<typename global_type>
+ QVector<global_type *> getAll()
+ {
+ warnIfNotLockedByThread(Q_FUNC_INFO);
+ QVector<global_type *> matching;
+ for (auto *global : qAsConst(m_globals)) {
+ if (auto *casted = qobject_cast<global_type *>(global))
+ matching.append(casted);
+ }
+ return matching;
+ }
+
+ uint nextSerial();
+ uint currentTimeMilliseconds();
+ wl_client *client(int index = 0);
+ void warnIfNotLockedByThread(const char* caller = "warnIfNotLockedbyThread");
+
+public:
+ // Only use this carefully from the test thread (i.e. lock first)
+ wl_display *m_display = nullptr;
+protected:
+ class Lock {
+ public:
+ explicit Lock(CoreCompositor *compositor)
+ : m_compositor(compositor)
+ , m_threadId(std::this_thread::get_id())
+ {
+ // Can't use a QMutexLocker here, as it's not movable
+ compositor->m_mutex.lock();
+ Q_ASSERT(compositor->m_lock == nullptr);
+ compositor->m_lock = this;
+ }
+ ~Lock()
+ {
+ Q_ASSERT(m_compositor->m_lock == this);
+ m_compositor->m_lock = nullptr;
+ m_compositor->m_mutex.unlock();
+ }
+
+ // Move semantics
+ Lock(Lock &&) = default;
+ Lock &operator=(Lock &&) = default;
+
+ // Disable copying
+ Lock(const Lock &) = delete;
+ Lock &operator=(const Lock &) = delete;
+
+ bool isOwnedByCurrentThread() const { return m_threadId == std::this_thread::get_id(); }
+ private:
+ CoreCompositor *m_compositor = nullptr;
+ std::thread::id m_threadId;
+ };
+ QByteArray m_socketName;
+ wl_event_loop *m_eventLoop = nullptr;
+ bool m_running = true;
+ QVector<Global *> m_globals;
+ QElapsedTimer m_timer;
+
+private:
+ Lock *m_lock = nullptr;
+ QMutex m_mutex;
+ std::thread m_dispatchThread;
+};
+
+template<typename container_type>
+QByteArray toByteArray(container_type container)
+{
+ return QByteArray(reinterpret_cast<const char *>(container.data()), sizeof (container[0]) * container.size());
+}
+
+template<typename return_type>
+return_type *fromResource(::wl_resource *resource) {
+ if (auto *r = return_type::Resource::fromResource(resource))
+ return static_cast<return_type *>(r->object());
+ return nullptr;
+}
+
+} // namespace MockCompositor
+
+#endif // MOCKCOMPOSITOR_CORECOMPOSITOR_H