[PATCH weston 09/10] tests: Add internal test for the weston test screenshot capability

Pekka Paalanen ppaalanen at gmail.com
Mon May 11 05:24:28 PDT 2015


On Wed,  6 May 2015 17:44:28 -0700
Bryce Harrington <bryce at osg.samsung.com> wrote:

> This also serves as a proof of concept of the screen capture
> functionality and as a demo for snapshot-based rendering verification.
> Implements screenshot saving clientside in the test itself.
> 
> This also demonstrates use of test-specific configuration files, in this
> case to disable fadein animations and background images.
> 
> Signed-off-by: Bryce Harrington <bryce at osg.samsung.com>
> ---
>  Makefile.am                                |  19 +++-
>  tests/internal-screenshot-test.c           | 151 +++++++++++++++++++++++++++++
>  tests/internal-screenshot.ini              |   3 +
>  tests/reference/internal-screenshot-00.png | Bin 0 -> 5149 bytes
>  4 files changed, 172 insertions(+), 1 deletion(-)
>  create mode 100644 tests/internal-screenshot-test.c
>  create mode 100644 tests/internal-screenshot.ini
>  create mode 100644 tests/reference/internal-screenshot-00.png
> 
> diff --git a/Makefile.am b/Makefile.am
> index 023b7e1..5bca9c2 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -941,7 +941,10 @@ libshared_cairo_la_SOURCES =			\
>  # tests subdirectory
>  #
>  
> -TESTS = $(shared_tests) $(module_tests) $(weston_tests) $(ivi_tests)
> +TESTS = $(internal_tests) $(shared_tests) $(module_tests) $(weston_tests) $(ivi_tests)

Chop.

> +
> +internal_tests = 				\
> +	internal-screenshot.weston
>  
>  shared_tests =					\
>  	config-parser.test			\
> @@ -1041,6 +1044,20 @@ nodist_libtest_client_la_SOURCES =		\
>  libtest_client_la_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS)
>  libtest_client_la_LIBADD = $(TEST_CLIENT_LIBS) libshared.la libtest-runner.la
>  
> +
> +#
> +# Internal tests - tests functionality of the testsuite itself
> +#
> +
> +internal_screenshot_weston_SOURCES = tests/internal-screenshot-test.c
> +internal_screenshot_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS) $(CAIRO_CFLAGS)
> +internal_screenshot_weston_LDADD = libtest-client.la  $(CAIRO_LIBS)

Will be getting Cairo via TEST_CLIENT.

> +
> +
> +#
> +# Weston Tests
> +#
> +
>  bad_buffer_weston_SOURCES = tests/bad-buffer-test.c
>  bad_buffer_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS) $(CAIRO_CFLAGS)
>  bad_buffer_weston_LDADD = libtest-client.la $(CAIRO_LIBS)
> diff --git a/tests/internal-screenshot-test.c b/tests/internal-screenshot-test.c
> new file mode 100644
> index 0000000..1aea393
> --- /dev/null
> +++ b/tests/internal-screenshot-test.c
> @@ -0,0 +1,151 @@
> +/*
> + * Copyright © 2015 Samsung Electronics Co., Ltd
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and
> + * its documentation for any purpose is hereby granted without fee, provided
> + * that the above copyright notice appear in all copies and that both that
> + * copyright notice and this permission notice appear in supporting
> + * documentation, and that the name of the copyright holders not be used in
> + * advertising or publicity pertaining to distribution of the software
> + * without specific, written prior permission.  The copyright holders make
> + * no representations about the suitability of this software for any
> + * purpose.  It is provided "as is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
> + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
> + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
> + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
> + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
> + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
> + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include "config.h"
> +
> +#include <unistd.h>
> +#include <stdio.h>
> +#include <string.h> // memcpy

Use /* */ everywhere.

> +#include <cairo.h>
> +
> +#include "weston-test-client-helper.h"
> +
> +char *server_parameters="--use-pixman --width=320 --height=240";
> +
> +TEST(internal_screenshot)
> +{
> +	struct client *client;
> +	struct surface *screenshot = NULL;
> +	struct rectangle clip;
> +	const char *fname;
> +	cairo_surface_t *reference;
> +	cairo_status_t status;
> +	bool match = false;
> +	bool dump_all_images = true;
> +
> +	printf("Starting test\n");
> +
> +	/* Create the client */
> +	client = create_client_and_test_surface(100, 100, 100, 100);
> +	assert(client);
> +	printf("Client created\n");
> +
> +	/* Create a surface to hold the screenshot */
> +	screenshot = xzalloc(sizeof *screenshot);

I think you are leaking this. Could be allocated from stack just as
well.

> +	assert(screenshot);
> +	screenshot->wl_surface = wl_compositor_create_surface(client->wl_compositor);
> +	assert(screenshot->wl_surface);
> +	printf("Screenshot surface created\n");
> +
> +	/* Create and attach buffer to our surface */
> +	screenshot->wl_buffer = create_shm_buffer(client,
> +						  client->output->width,
> +						  client->output->height,
> +						  &screenshot->data);
> +	screenshot->height = client->output->height;
> +	screenshot->width = client->output->width;
> +	assert(screenshot->wl_buffer);
> +	printf("Screenshot buffer created and attached to surface\n");
> +
> +	/* Take a snapshot.  Result will be in screenshot->wl_buffer. */
> +	client->test->buffer_copy_done = 0;
> +	weston_test_capture_screenshot(client->test->weston_test,
> +				       client->output->wl_output,
> +				       screenshot->wl_buffer);
> +	printf("Capture request sent\n");
> +	while (client->test->buffer_copy_done == 0)
> +		client_roundtrip(client);

That's a pretty busy-loop-happy way to do it. You can spin lots of
roundtrips until the compositor goes repainting. If you would like to
block properly, look at frame_callback_wait().

> +	printf("Roundtrip done\n");
> +	assert(screenshot->wl_buffer);

Redundant assert.

> +
> +	// FIXME: Document somewhere the orientation the screenshot is taken
> +	// and how the clip coords are interpreted, in case of scaling/transform.
> +	// If we're using read_pixels() just make sure it is documented somewhere

Right. Protocol docs in the XML, comparison function docs in Doxygen
style.

> +	// Load reference image
> +	fname = screenshot_reference_filename("internal-screenshot", 0);
> +	printf("Loading reference image %s\n", fname);
> +	reference = cairo_image_surface_create_from_png(fname);
> +	status = cairo_surface_status(reference);
> +	if (status != CAIRO_STATUS_SUCCESS) {
> +		printf("Could not open %s: %s\n", fname, cairo_status_to_string(status));
> +		cairo_surface_destroy(reference);
> +		assert(status != CAIRO_STATUS_SUCCESS);
> +	}
> +
> +	// Test check_surfaces_equal()
> +	// We expect this to fail since the clock will differ from when we made the reference image
> +	match = check_surfaces_equal(screenshot, reference);
> +	printf("Screenshot %s reference image\n", match? "equal to" : "different from");
> +	assert(!match);

Heh, this is more like a test framework self-test for this particular
comparison function. I think such self-tests should be separated. (c.f.
for Pixman I recently wrote
http://lists.freedesktop.org/archives/pixman/2015-May/003643.html ).
There it would be easy to test stride and other differences properly.

But that's just for follow-up, not a blocker and not important in
this case because the correctness is fairly easy to see from the code.

> +
> +	// Test check_surfaces_match_in_clip()
> +	// Alpha-blending and other effects can cause irrelevant discrepancies, so look only
> +	// at a small portion of the solid-colored background
> +	clip.x = 50;
> +	clip.y = 50;
> +	clip.width = 20;
> +	clip.height = 20;
> +	printf("Clip: %d,%d %d x %d\n", clip.x, clip.y, clip.width, clip.height);
> +	match = check_surfaces_match_in_clip(screenshot, reference, &clip);
> +	printf("Screenshot %s reference image in clipped area\n", match? "matches" : "doesn't match");
> +	cairo_surface_destroy(reference);
> +
> +	// Test dumping of non-matching images
> +	if (!match || dump_all_images) {
> +		/* Write image to .png file */
> +		int output_stride, buffer_stride, i;
> +		cairo_surface_t *surface;
> +		void *data, *d, *s;
> +
> +		printf("Allocating memory for copying bad image to disk\n");
> +		buffer_stride = client->output->width * 4;
> +		data = xmalloc(buffer_stride * client->output->height);
> +		assert(data);
> +
> +		output_stride = client->output->width * 4;
> +		s = screenshot->data;
> +		d = data;
> +
> +		printf("Copying screenshot data\n");
> +		for (i = 0; i < client->output->height; i++) {
> +			memcpy(d, s, output_stride);
> +			d += buffer_stride;
> +			s += output_stride;
> +		}
> +
> +		printf("Creating Cairo image surface from returned data\n");
> +		surface = cairo_image_surface_create_for_data(data,

Why not simply pass screenshot->data here?

> +							      CAIRO_FORMAT_ARGB32,
> +							      client->output->width,
> +							      client->output->height,
> +							      buffer_stride);
> +
> +		printf("Writing PNG to disk\n");
> +		cairo_surface_write_to_png(surface, "clientside-screenshot.png");
> +		cairo_surface_destroy(surface);
> +		free(data);
> +	}
> +
> +	printf("Test complete\n");
> +	assert(match);
> +}

Could use splitting into functions. Lots of this could be reusable and
more structure woudln't hurt.


Thanks,
pq


More information about the wayland-devel mailing list