1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
|
/*
* Copyright (C) 2020 Purism SPC
* 2025 Phosh.mobi e.V.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "server.h"
#include "gtk-shell-client-protocol.h"
#include "phoc-layer-shell-effects-unstable-v1-client-protocol.h"
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "wlr-screencopy-unstable-v1-client-protocol.h"
#include "xdg-decoration-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h"
/* Needs wlr-screencopy-unstable */
#include "phosh-private-client-protocol.h"
#include <glib.h>
#pragma once
G_BEGIN_DECLS
typedef struct _PhocTestClientGlobals PhocTestClientGlobals;
typedef struct _PhocTestBuffer {
struct wl_buffer *wl_buffer;
guint8 *shm_data;
guint32 width, height, stride;
enum wl_shm_format format;
gboolean valid;
} PhocTestBuffer;
typedef struct _PhocTestScreencopyFrame {
PhocTestBuffer buffer;
gboolean done;
uint32_t flags;
PhocTestClientGlobals *globals;
} PhocTestScreencopyFrame;
typedef struct _PhocTestOutputConfig {
guint width;
guint height;
float scale;
enum wl_output_transform transform;
} PhocTestOutputConfig;
typedef struct _PhocTestOutput {
struct wl_output *output;
guint32 width, height;
PhocTestScreencopyFrame screenshot;
} PhocTestOutput;
struct _PhocTestClientGlobals {
struct wl_display *display;
struct wl_compositor *compositor;
struct wl_shm *shm;
struct xdg_wm_base *xdg_shell;
struct zwlr_layer_shell_v1 *layer_shell;
struct zphoc_layer_shell_effects_v1 *layer_shell_effects;
struct zwlr_screencopy_manager_v1 *screencopy_manager;
struct zwlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
struct zxdg_decoration_manager_v1 *decoration_manager;
GSList *foreign_toplevels;
struct phosh_private *phosh;
struct gtk_shell1 *gtk_shell1;
/* TODO: handle multiple outputs */
PhocTestOutput output;
PhocTestOutputConfig output_config;
GPtrArray *formats;
};
typedef struct _PhocTestForeignToplevel {
char* title;
struct zwlr_foreign_toplevel_handle_v1 *handle;
PhocTestClientGlobals *globals;
} PhocTestForeignToplevel;
typedef gboolean (* PhocTestServerFunc) (PhocServer *server, gpointer data);
typedef gboolean (* PhocTestClientFunc) (PhocTestClientGlobals *globals, gpointer data);
typedef struct PhocTestClientIface {
/* Prepare function runs in server context */
PhocTestServerFunc server_prepare;
PhocTestClientFunc client_run;
PhocServerFlags server_flags;
PhocServerDebugFlags debug_flags;
gboolean xwayland;
PhocTestOutputConfig output_config;
} PhocTestClientIface;
typedef struct _PhocTestXdgToplevelSurface PhocTestXdgToplevelSurface;
typedef void (* PhocXdgAckConfigureCallback) (PhocTestXdgToplevelSurface *surface, gpointer data);
struct _PhocTestXdgToplevelSurface {
struct wl_surface *wl_surface;
struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel;
PhocTestForeignToplevel *foreign_toplevel;
char* title;
PhocTestBuffer buffer;
guint32 width, height;
gboolean configured;
gboolean toplevel_configured;
struct {
PhocXdgAckConfigureCallback callback;
gpointer data;
GDestroyNotify data_free_func;
} ack_configure;
};
typedef struct _PhocTestFixture {
GTestDBus *bus;
char *tmpdir;
} PhocTestFixture;
/* Test client */
void phoc_test_client_run (int timeout, PhocTestClientIface *iface, gpointer data);
int phoc_test_client_create_shm_buffer (PhocTestClientGlobals *globals,
PhocTestBuffer *buffer,
int width, int height, guint32 format);
PhocTestBuffer *phoc_test_client_capture_frame (PhocTestClientGlobals *globals,
PhocTestScreencopyFrame *frame,
struct zwlr_screencopy_frame_v1 *handle);
PhocTestBuffer *phoc_test_client_capture_output (PhocTestClientGlobals *globals,
PhocTestOutput *output);
PhocTestForeignToplevel *phoc_test_client_get_foreign_toplevel_handle (PhocTestClientGlobals *globals,
const char *title);
/* Test surfaces */
PhocTestXdgToplevelSurface *
phoc_test_xdg_toplevel_new (PhocTestClientGlobals *globals,
guint32 width,
guint32 height,
const char *title);
PhocTestXdgToplevelSurface *
phoc_test_xdg_toplevel_new_with_buffer (PhocTestClientGlobals *globals,
guint32 width,
guint32 height,
const char *title,
guint32 color);
void phoc_test_xdg_toplevel_free (PhocTestXdgToplevelSurface *xs);
void phoc_test_xdg_toplevel_set_ack_configure_callback (PhocTestXdgToplevelSurface *xs,
PhocXdgAckConfigureCallback callback,
gpointer data,
GDestroyNotify data_free_func);
void phoc_test_xdg_update_buffer (PhocTestClientGlobals *globals,
PhocTestXdgToplevelSurface *xs,
guint32 color);
/* Buffers */
gboolean phoc_test_buffer_equal (PhocTestBuffer *buf1, PhocTestBuffer *buf2);
gboolean phoc_test_buffer_save (PhocTestBuffer *buffer, const char *filename);
gboolean phoc_test_buffer_matches_screenshot (PhocTestBuffer *buffer, const char *filename);
void phoc_test_buffer_free (PhocTestBuffer *buffer);
#define _phoc_test_screenshot_name(l, f, n) \
(g_strdup_printf ("phoc-test-screenshot-%d-%s_%d.png", l, f, n))
/*
* phoc_assert_screenshot:
* @g: The client global object
* @f: The screenshot to compare the current output to
*/
#define phoc_assert_screenshot(g, f) G_STMT_START { \
PhocTestClientGlobals *__g = (g); \
char *__f = g_test_build_filename (G_TEST_DIST, "screenshots", f, NULL); \
PhocTestBuffer *__s = phoc_test_client_capture_output (__g, &__g->output); \
g_test_message ("Snapshotting %s", f); \
if (phoc_test_buffer_matches_screenshot (__s, __f)); else { \
g_autofree char *__name = _phoc_test_screenshot_name (__LINE__, G_STRFUNC, 0); \
g_autofree char *__msg = \
g_strdup_printf ("Output content in '%s' does not match " #f, __name); \
phoc_test_buffer_save (&__g->output.screenshot.buffer, __name); \
g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, __msg); \
} \
phoc_test_buffer_free (__s); \
g_free (__f); \
} G_STMT_END
/**
* phoc_test_assert_buffer_equal:
* @b1: A PhocClientBuffer
* @b2: A PhocClientBuffer
*
* Debugging macro to compare two buffers. If the buffers don't match
* screenshots are taken and saved as PNG.
*/
#define phoc_assert_buffer_equal(b1, b2) G_STMT_START { \
PhocTestBuffer *__b1 = (b1), *__b2 = (b2); \
if (phoc_test_buffer_equal (__b1, __b2)); else { \
g_autofree char *__name1 = _phoc_test_screenshot_name (__LINE__, G_STRFUNC, 1); \
g_autofree char *__name2 = _phoc_test_screenshot_name (__LINE__, G_STRFUNC, 2); \
phoc_test_buffer_save (__b1, __name1); \
phoc_test_buffer_save (__b2, __name2); \
g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
"Buffer " #b1 " != " #b2); \
} \
} G_STMT_END
/**
* phoc_test_assert_cmpbox
* @b1: A box
* @b2: A box
*
* Debugging macro to compare two boxes.
*/
#define phoc_assert_cmpbox(b1, b2) G_STMT_START { \
__auto_type __b1 = (b1); \
__auto_type __b2 = (b2); \
if (__b1->x != __b2->x || __b1->y != __b2->y || \
__b1->width != __b2->width || __b1->height != __b2->height) { \
g_autofree char *__msg = \
g_strdup_printf ("Box " #b1 " (%d,%d %dx%d) doesn't match " #b2 " (%d,%d %dx%d)", \
__b1->x, __b1->y, __b1->width, __b1->height, \
__b2->x, __b2->y, __b2->width, __b2->height); \
g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, __msg); \
} \
} G_STMT_END
/* Test setup and fixtures */
void phoc_test_setup (PhocTestFixture *fixture, gconstpointer data);
void phoc_test_teardown (PhocTestFixture *fixture, gconstpointer unused);
#define PHOC_TEST_ADD(name, func) g_test_add ((name), PhocTestFixture, NULL, \
(gpointer)phoc_test_setup, \
(gpointer)(func), \
(gpointer)phoc_test_teardown)
G_END_DECLS
|