Check in tests

* tests/Imakefile:
* tests/README
* tests/basic_test_card.png:
* tests/blue.png:
* tests/simple_test.c:
* tests/simple_test.dump:
* tests/svnignore.txt:
* tests/test_harness.c:
* tests/test_harness.h: New files.
This commit is contained in:
hujianwei 2022-11-04 02:41:19 +00:00
parent 2230f5e406
commit 83a2d26df3
9 changed files with 1063 additions and 0 deletions

37
tests/Imakefile Normal file
View file

@ -0,0 +1,37 @@
#include "../12to11.conf"
12TO11ROOT = ..
DEPLIBS = $(DEPXLIB)
LOCAL_LIBRARIES = $(WAYLAND_CLIENT) $(XLIB) $(PNG)
COMMONOBJS = test_harness.o
COMMONSRCS = test_harness.c
HEADER = test_harness.h
EXTRA_DEFINES := -D_GNU_SOURCE -U_BSD_SOURCE -U_SVID_SOURCE
#define ScannerTarget(name) @@\
name.h: $(12TO11ROOT)/name.xml @@\
$(WAYLAND_SCANNER) client-header $< $@ @@\
@@\
name.c: $(12TO11ROOT)/name.xml name.h @@\
$(WAYLAND_SCANNER) private-code $< $@ @@\
@@\
COMMONOBJS := $(COMMONOBJS) name.o @@\
COMMONSRCS := $(COMMONSRCS) name.c @@\
HEADER := $(HEADER) name.h @@\
ScannerTarget(12to11-test)
SRCS1 = $(COMMONSRCS) simple_test.c
OBJS1 = $(COMMONOBJS) simple_test.o
PROGRAMS = simple_test
/* Make all objects depend on HEADER. */
$(OBJS1): $(HEADER)
/* And depend on all sources and headers. */
depend:: $(HEADER) $(SRCS1)
NormalProgramTarget(simple_test,$(OBJS1),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
DependTarget3($(SRCS1),NullParameter,NullParameter)
all:: $(PROGRAMS)

6
tests/README Normal file
View file

@ -0,0 +1,6 @@
This directory holds some work-in-progress code for testing the
protocol translator. At present, there is only a simple smoke test of
limited utility.
Each test must be individually run on a system with an a8r8g8b8
visual, GLOBAL_SCALE and OUTPUT_SCALE set to 1.

BIN
tests/basic_test_card.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
tests/blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

171
tests/simple_test.c Normal file
View file

@ -0,0 +1,171 @@
/* Tests for the Wayland compositor running on the X server.
Copyright (C) 2022 to various contributors.
This file is part of 12to11.
12to11 is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
12to11 is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
#include "test_harness.h"
enum test_kind
{
MAP_WINDOW_KIND,
BASIC_TEST_CARD_IMAGE_KIND,
};
/* The display. */
static struct test_display *display;
/* Test interfaces. */
static struct test_interface test_interfaces[] =
{
/* No interfaces yet. */
};
/* The test surface window. */
static Window test_surface_window;
/* The test surface and Wayland surface. */
static struct test_surface *test_surface;
static struct wl_surface *wayland_surface;
/* Forward declarations. */
static void submit_frame_callback (struct wl_surface *, enum test_kind);
static void
verify_single_step (enum test_kind kind)
{
verify_image_data (display, test_surface_window, "simple_test.dump");
}
static void
test_single_step (enum test_kind kind)
{
struct wl_buffer *buffer;
switch (kind)
{
case MAP_WINDOW_KIND:
buffer = load_png_image (display, "blue.png");
if (!buffer)
report_test_failure ("failed to load blue.png");
wl_surface_attach (wayland_surface, buffer, 0, 0);
wl_surface_commit (wayland_surface);
wl_buffer_destroy (buffer);
break;
case BASIC_TEST_CARD_IMAGE_KIND:
buffer = load_png_image (display, "basic_test_card.png");
if (!buffer)
report_test_failure ("failed to load basic_test_card.png");
wl_surface_attach (wayland_surface, buffer, 0, 0);
submit_frame_callback (wayland_surface, kind);
wl_surface_commit (wayland_surface);
wl_buffer_destroy (buffer);
break;
}
}
static void
handle_test_surface_mapped (void *data, struct test_surface *surface,
uint32_t xid, const char *display_string)
{
/* Sleep for 1 second to ensure that the window is exposed and
redirected. */
sleep (1);
/* Start the test. */
test_surface_window = xid;
/* Run the test again. */
test_single_step (BASIC_TEST_CARD_IMAGE_KIND);
}
static const struct test_surface_listener test_surface_listener =
{
handle_test_surface_mapped,
};
static void
handle_wl_callback_done (void *data, struct wl_callback *callback,
uint32_t callback_data)
{
enum test_kind kind;
kind = (intptr_t) data;
wl_callback_destroy (callback);
verify_single_step (kind);
}
static const struct wl_callback_listener wl_callback_listener =
{
handle_wl_callback_done,
};
static void
submit_frame_callback (struct wl_surface *surface, enum test_kind kind)
{
struct wl_callback *callback;
callback = wl_surface_frame (surface);
wl_callback_set_user_data (callback, (void *) (intptr_t) kind);
wl_callback_add_listener (callback, &wl_callback_listener,
NULL);
}
static void
run_test (void)
{
if (!make_test_surface (display, &wayland_surface,
&test_surface))
report_test_failure ("failed to create test surface");
test_surface_add_listener (test_surface, &test_surface_listener,
NULL);
test_single_step (MAP_WINDOW_KIND);
while (true)
{
if (wl_display_dispatch (display->display) == -1)
die ("wl_display_dispatch");
}
}
int
main (void)
{
test_init ();
display = open_test_display (test_interfaces,
ARRAYELTS (test_interfaces));
if (!display)
report_test_failure ("failed to open display");
run_test ();
}

BIN
tests/simple_test.dump Normal file

Binary file not shown.

5
tests/svnignore.txt Normal file
View file

@ -0,0 +1,5 @@
*-*.h
*-*.c
vgcore*
simple_test
Makefile

753
tests/test_harness.c Normal file
View file

@ -0,0 +1,753 @@
/* Tests for the Wayland compositor running on the X server.
Copyright (C) 2022 to various contributors.
This file is part of 12to11.
12to11 is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
12to11 is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <setjmp.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/errno.h>
#include <sys/uio.h>
#include <png.h>
#include "test_harness.h"
#define BIG_ENDIAN_BYTE_ORDER (1 << 8)
struct image_data_header
{
/* Currently 1. High bit is byte order. */
unsigned char version;
/* The data format. Currently always 0. */
unsigned char format;
/* The width and height. */
unsigned short width, height;
/* The stride. */
unsigned int stride;
};
enum image_data_format
{
/* Little-endian ARGB8888. */
IMAGE_DATA_ARGB8888_LE,
/* Little-endian XRGB8888. */
IMAGE_DATA_XRGB8888_LE,
};
#if PNG_LIBPNG_VER < 10500
#define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
# else
#define PNG_JMPBUF(ptr) \
(*png_set_longjmp_fn (ptr, longjmp, sizeof (jmp_buf)))
#endif
/* Whether or not to write image data instead of verifying it. */
static bool write_image_data_instead;
static void
handle_test_manager_display_string (void *data, struct test_manager *manager,
const char *display_string)
{
struct test_display *display;
display = data;
display->x_display = XOpenDisplay (display_string);
display->pixmap_formats
= XListPixmapFormats (display->x_display,
&display->num_pixmap_formats);
}
static const struct test_manager_listener test_manager_listener =
{
handle_test_manager_display_string,
};
static bool
test_manager_check (struct test_display *display)
{
return (display->x_display != NULL
&& display->num_pixmap_formats
&& display->pixmap_formats);
}
static void
handle_registry_global (void *data, struct wl_registry *registry,
uint32_t id, const char *interface,
uint32_t version)
{
struct test_display *display;
int i;
display = data;
if (!strcmp (interface, "wl_compositor") && version >= 5)
display->compositor
= wl_registry_bind (registry, id, &wl_compositor_interface,
5);
if (!strcmp (interface, "wl_shm") && version >= 1)
display->shm = wl_registry_bind (registry, id, &wl_shm_interface, 1);
else if (!strcmp (interface, "test_manager"))
display->test_manager
= wl_registry_bind (registry, id, &test_manager_interface, 1);
else
{
/* Look through the user specified list of interfaces. */
for (i = 0; i < display->num_test_interfaces; ++i)
{
if (!strcmp (interface, display->interfaces[i].interface)
&& display->interfaces[i].version >= version)
/* Bind to it. */
*((void **) display->interfaces[i].data)
= wl_registry_bind (registry, id,
display->interfaces[i].c_interface,
display->interfaces[i].version);
}
}
}
static void
handle_registry_global_remove (void *data, struct wl_registry *registry,
uint32_t name)
{
return;
}
static const struct wl_registry_listener registry_listener =
{
handle_registry_global,
handle_registry_global_remove,
};
/* Check whether or not all required globals were found and bound
to. */
static bool
registry_listener_check (struct test_display *display)
{
int i;
if (!display->compositor)
return false;
if (!display->shm)
return false;
if (!display->test_manager)
return false;
for (i = 0; i < display->num_test_interfaces; ++i)
{
if (!*((void **) display->interfaces[i].interface))
return false;
}
return true;
}
void __attribute__ ((noreturn))
die (const char *reason)
{
perror (reason);
exit (1);
}
struct test_display *
open_test_display (struct test_interface *interfaces, int num_interfaces)
{
struct test_display *display;
display = malloc (sizeof *display);
if (!display)
return NULL;
display->display = wl_display_connect (NULL);
if (!display->display)
goto error_1;
display->registry = wl_display_get_registry (display->display);
if (!display->registry)
goto error_2;
display->interfaces = interfaces;
display->num_test_interfaces = num_interfaces;
wl_registry_add_listener (display->registry, &registry_listener,
display);
wl_display_roundtrip (display->display);
if (!registry_listener_check (display))
goto error_2;
/* Now establish the connection to the X display. */
test_manager_add_listener (display->test_manager,
&test_manager_listener, display);
wl_display_roundtrip (display->display);
if (!test_manager_check (display))
goto error_3;
return display;
error_3:
if (display->x_display)
XCloseDisplay (display->x_display);
error_2:
wl_display_disconnect (display->display);
error_1:
free (display);
return NULL;
}
int
get_shm_file_descriptor (void)
{
char name[sizeof "test_driver_buffer_XXXXXXXX"];
int fd;
uint32_t i;
i = 0;
while (i <= 0xffffffff)
{
sprintf (name, "test_driver_buffer_%"PRIu32, i);
fd = shm_open (name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd >= 0)
{
shm_unlink (name);
return fd;
}
if (errno == EEXIST)
++i;
else
return -1;
}
return -1;
}
#define IMAGE_PAD(nbytes, pad) ((((nbytes) + ((pad) - 1)) / (pad)) * ((pad) >> 3))
size_t
get_image_stride (struct test_display *display, int depth, int width)
{
int bpp, scanline_pad, i;
size_t stride;
for (i = 0; i < display->num_pixmap_formats; ++i)
{
if (display->pixmap_formats[i].depth == depth)
{
bpp = display->pixmap_formats[i].bits_per_pixel;
scanline_pad = display->pixmap_formats[i].bits_per_pixel;
stride = IMAGE_PAD (width * bpp, scanline_pad);
return stride;
}
}
return 0;
}
struct wl_buffer *
upload_image_data (struct test_display *display, const char *data,
int width, int height, int depth)
{
size_t stride;
int fd;
void *mapping;
struct wl_shm_pool *pool;
struct wl_buffer *buffer;
if (depth != 32 && depth != 24)
return NULL;
stride = get_image_stride (display, depth, width);
if (!stride)
return NULL;
fd = get_shm_file_descriptor ();
if (fd < 0)
return NULL;
if (ftruncate (fd, stride * height) < 0)
return NULL;
mapping = mmap (NULL, stride * height, PROT_WRITE, MAP_SHARED,
fd, 0);
if (mapping == (void *) -1)
{
perror ("mmap");
close (fd);
return NULL;
}
memcpy (mapping, data, stride * height);
if (munmap (mapping, stride * height) < 0)
die ("munmap");
pool = wl_shm_create_pool (display->shm, fd, stride * height);
if (!pool)
{
close (fd);
return NULL;
}
close (fd);
buffer = wl_shm_pool_create_buffer (pool, 0, width, height, stride,
(depth == 32
? WL_SHM_FORMAT_ARGB8888
: WL_SHM_FORMAT_XRGB8888));
wl_shm_pool_destroy (pool);
return buffer;
}
void __attribute__ ((noreturn, format (gnu_printf, 1, 2)))
report_test_failure (const char *format, ...)
{
va_list ap;
va_start (ap, format);
fputs ("failure: ", stderr);
vfprintf (stderr, format, ap);
fputs ("\n", stderr);
va_end (ap);
exit (1);
}
void __attribute__ ((format (gnu_printf, 1, 2)))
test_log (const char *format, ...)
{
va_list ap;
va_start (ap, format);
fputs ("note: ", stderr);
vfprintf (stderr, format, ap);
fputs ("\n", stderr);
va_end (ap);
}
bool
make_test_surface (struct test_display *display,
struct wl_surface **surface_return,
struct test_surface **test_surface_return)
{
struct wl_surface *surface;
struct test_surface *test_surface;
surface = wl_compositor_create_surface (display->compositor);
if (!surface)
return false;
test_surface
= test_manager_get_test_surface (display->test_manager,
surface);
if (!test_surface)
{
wl_surface_destroy (surface);
return false;
}
*surface_return = surface;
*test_surface_return = test_surface;
return true;
}
/* Swizzle the big-endian data in ROW_DATA to the little-endian format
Wayland mandates. */
static void
swizzle_png_row (unsigned char *row_data, int width)
{
int i;
unsigned char byte_1, byte_2, byte_3, byte_4;
for (i = 0; i < width; ++i)
{
byte_1 = row_data[i * 4 + 0];
byte_2 = row_data[i * 4 + 1];
byte_3 = row_data[i * 4 + 2];
byte_4 = row_data[i * 4 + 3];
row_data[i * 4 + 0] = byte_3;
row_data[i * 4 + 1] = byte_2;
row_data[i * 4 + 2] = byte_1;
row_data[i * 4 + 3] = byte_4;
}
}
/* Load a PNG image into a wl_buffer. The image must be either
PNG_COLOR_TYPE_RGB or PNG_COLOR_TYPE_RGB_ALPHA. The image
background is ignored. */
struct wl_buffer *
load_png_image (struct test_display *display, const char *filename)
{
FILE *file;
unsigned char signature[8];
png_structp png_ptr;
png_infop info_ptr;
png_uint_32 width, height;
int bit_depth, color_type, depth;
png_uint_32 i, rowbytes;
png_bytep *row_pointers;
unsigned char *image_data;
struct wl_buffer *buffer;
image_data = NULL;
file = fopen (filename, "r");
if (!file)
return NULL;
if (fread (signature, 1, 8, file) != 8)
goto error_1;
if (!png_check_sig (signature, 8))
goto error_1;
png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL,
NULL);
if (!png_ptr)
goto error_1;
info_ptr = png_create_info_struct (png_ptr);
if (!info_ptr)
goto error_2;
if (setjmp (PNG_JMPBUF (png_ptr)))
goto error_3;
png_init_io (png_ptr, file);
png_set_sig_bytes (png_ptr, 8);
png_read_info (png_ptr, info_ptr);
png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth,
&color_type, NULL, NULL, NULL);
if (color_type != PNG_COLOR_TYPE_RGB
&& color_type != PNG_COLOR_TYPE_RGB_ALPHA)
goto error_3;
/* Get data as ARGB. */
if (color_type == PNG_COLOR_TYPE_RGB)
png_set_filler (png_ptr, 0, PNG_FILLER_AFTER);
/* Start reading the PNG data. Get the stride and depth. */
depth = (color_type == PNG_COLOR_TYPE_RGB_ALPHA
? 32 : 24);
png_read_update_info (png_ptr, info_ptr);
rowbytes = get_image_stride (display, depth, width);
/* Allocate a buffer for the image data. */
image_data = malloc (rowbytes * height);
if (!image_data)
goto error_3;
/* Allocate the array of row pointers. */
row_pointers = alloca (sizeof *row_pointers * height);
for (i = 0; i < height; ++i)
row_pointers[i] = image_data + i * rowbytes;
/* Read the data. */
png_read_image (png_ptr, row_pointers);
png_read_end (png_ptr, NULL);
for (i = 0; i < height; ++i)
/* Swizzle the big-endian data. */
swizzle_png_row (row_pointers[i], width);
/* Now, destroy the read struct and close the file. */
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
fclose (file);
/* Upload the image data. */
buffer = upload_image_data (display, (const char *) image_data,
width, height, depth);
/* Free the image data. */
free (image_data);
return buffer;
error_3:
if (image_data)
free (image_data);
/* This looks silly... */
if (true)
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
else
error_2:
png_destroy_read_struct (&png_ptr, NULL, NULL);
error_1:
fclose (file);
return NULL;
}
static unsigned short
bytes_per_pixel_for_format (enum image_data_format format)
{
switch (format)
{
case IMAGE_DATA_ARGB8888_LE:
case IMAGE_DATA_XRGB8888_LE:
return 4;
default:
return 0;
}
}
static int
byte_order_for_format (enum image_data_format format)
{
switch (format)
{
case IMAGE_DATA_ARGB8888_LE:
case IMAGE_DATA_XRGB8888_LE:
return LSBFirst;
default:
return 0;
}
}
/* Load image data from a file. */
static unsigned char *
load_image_data (const char *filename, struct image_data_header *header)
{
int fd;
struct iovec iov;
unsigned char *buffer;
unsigned short bpp;
fd = open (filename, O_RDONLY);
if (fd < 0)
return NULL;
iov.iov_base = header;
iov.iov_len = sizeof *header;
if (readv (fd, &iov, 1) != iov.iov_len)
goto error_1;
#ifdef __BIG_ENDIAN__
if (!(header->version & BIG_ENDIAN_BYTE_ORDER))
goto error_1;
#endif
if ((header->version & ~BIG_ENDIAN_BYTE_ORDER) != 1)
goto error_1;
bpp = bytes_per_pixel_for_format (header->format);
if (!bpp || header->stride < header->height * bpp)
goto error_1;
buffer = malloc (header->stride * header->height);
if (!buffer)
goto error_1;
iov.iov_base = buffer;
iov.iov_len = header->stride * header->height;
if (readv (fd, &iov, 1) != iov.iov_len)
goto error_2;
close (fd);
return buffer;
error_2:
free (buffer);
error_1:
close (fd);
return NULL;
}
static void
compare_single_row (unsigned char *data, int row_no,
struct image_data_header *header, XImage *image)
{
char *xdata;
unsigned short bytes_per_pixel;
bytes_per_pixel = bytes_per_pixel_for_format (header->format);
data = data + header->stride * row_no;
xdata = image->data + image->bytes_per_line * row_no;
if (memcmp (data, xdata, bytes_per_pixel * header->width))
report_test_failure ("row %d differs", row_no);
}
static void
write_image_data (struct test_display *display, Window window,
const char *filename)
{
struct image_data_header header;
XImage *image;
struct iovec iovecs[2];
int fd;
XWindowAttributes attrs;
test_log ("writing contents of drawable to reference %s", filename);
XGetWindowAttributes (display->x_display, window, &attrs);
image = XGetImage (display->x_display, window, 0, 0, attrs.width,
attrs.height, ~0, ZPixmap);
if (!image)
report_test_failure ("failed to load from drawable 0x%lx", window);
memset (&header, 0, sizeof header);
header.version = 1;
#ifdef __BIG_ENDIAN__
header.version |= BIG_ENDIAN_BYTE_ORDER;
#endif
if ((image->depth != 24 && image->depth != 32)
|| image->bits_per_pixel != 32)
report_test_failure ("don't know how to save image of depth %d (bpp %d)",
image->depth, image->bits_per_pixel);
if (image->byte_order != LSBFirst)
report_test_failure ("don't know how to save big-endian image");
/* TODO: determine the image format based on the visual of the
window. */
header.format = (image->depth == 24
? IMAGE_DATA_XRGB8888_LE
: IMAGE_DATA_ARGB8888_LE);
header.width = image->width;
header.height = image->height;
header.stride = image->bytes_per_line;
/* Open the output file and write the data. */
fd = open (filename, O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd < 0)
report_test_failure ("failed to open output file %s", filename);
iovecs[0].iov_base = &header;
iovecs[0].iov_len = sizeof header;
iovecs[1].iov_base = image->data;
iovecs[1].iov_len = image->bytes_per_line * image->height;
if (writev (fd, iovecs, 2) != iovecs[0].iov_len + iovecs[1].iov_len)
report_test_failure ("failed to write to output file %s", filename);
close (fd);
XDestroyImage (image);
test_log ("image data written to %s", filename);
}
/* Verify the image data against a file. */
void
verify_image_data (struct test_display *display, Window window,
const char *filename)
{
XImage *image;
XWindowAttributes attrs;
unsigned char *data;
struct image_data_header header;
unsigned short data_bpp, i;
int byte_order;
if (write_image_data_instead)
write_image_data (display, window, filename);
data = load_image_data (filename, &header);
if (!data)
report_test_failure ("failed to load input file: %s", filename);
XGetWindowAttributes (display->x_display, window, &attrs);
image = XGetImage (display->x_display, window, 0, 0, attrs.width,
attrs.height, ~0, ZPixmap);
if (!image)
report_test_failure ("failed to load from drawable 0x%lx", window);
/* Check if the image data is compatible. */
data_bpp = bytes_per_pixel_for_format (header.format);
byte_order = byte_order_for_format (header.format);
if (byte_order != image->byte_order)
report_test_failure ("image data has wrong byte order");
if (data_bpp * 8 != image->bits_per_pixel)
report_test_failure ("image data has %d bits per pixel, but reference"
" data has %hd * 8", image->bits_per_pixel, data_bpp);
if (image->width != header.width
|| image->height != header.height)
report_test_failure ("image data is %d by %d, but reference data is"
" %hd by %hd", image->width, image->height,
header.width, header.height);
/* Now compare the actual image data. Make sure this is done with
the same visual as the reference data was saved in! */
for (i = 0; i < header.height; ++i)
compare_single_row (data, i, &header, image);
/* Destroy the images. */
free (data);
XDestroyImage (image);
test_log ("verified image data");
}
void
test_init (void)
{
write_image_data_instead
= getenv ("TEST_WRITE_REFERENCE") != NULL;
}

91
tests/test_harness.h Normal file
View file

@ -0,0 +1,91 @@
/* Tests for the Wayland compositor running on the X server.
Copyright (C) 2022 to various contributors.
This file is part of 12to11.
12to11 is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
12to11 is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <wayland-client.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "12to11-test.h"
struct test_display
{
/* The wayland display. */
struct wl_display *display;
/* The X display. */
Display *x_display;
/* List of pixmap formats. */
XPixmapFormatValues *pixmap_formats;
/* Number of pixmap formats. */
int num_pixmap_formats;
/* The registry and various Wayland interfaces. */
struct wl_registry *registry;
struct wl_compositor *compositor;
struct wl_shm *shm;
struct test_manager *test_manager;
/* Test interfaces. */
struct test_interface *interfaces;
/* The number of such interfaces. */
int num_test_interfaces;
};
struct test_interface
{
/* The name of the interface. */
const char *interface;
/* Pointer to the interface data. */
void *data;
/* Pointer to the interface. */
struct wl_interface *c_interface;
/* The wanted version. */
uint32_t version;
};
extern void die (const char *);
extern struct test_display *open_test_display (struct test_interface *, int);
extern int get_shm_file_descriptor (void);
extern size_t get_image_stride (struct test_display *, int, int);
extern struct wl_buffer *upload_image_data (struct test_display *,
const char *, int, int,
int);
extern void report_test_failure (const char *, ...)
__attribute__ ((noreturn, format (gnu_printf, 1, 2)));
extern void test_log (const char *, ...)
__attribute__ ((format (gnu_printf, 1, 2)));
extern bool make_test_surface (struct test_display *, struct wl_surface **,
struct test_surface **);
extern struct wl_buffer *load_png_image (struct test_display *, const char *);
extern void verify_image_data (struct test_display *, Window, const char *);
extern void test_init (void);
#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0])