File: testlib.h

package info (click to toggle)
phoc 0.52.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,052 kB
  • sloc: ansic: 107,165; xml: 3,765; sh: 138; makefile: 33; javascript: 5
file content (238 lines) | stat: -rw-r--r-- 10,604 bytes parent folder | download
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