tests: Add internal test for the weston test screenshot capability

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@osg.samsung.com>
Reviewed-By: Derek Foreman <derekf@osg.samsung.com>
diff --git a/Makefile.am b/Makefile.am
index 543c736..e860e0e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -941,7 +941,10 @@
 # tests subdirectory
 #
 
-TESTS = $(shared_tests) $(module_tests) $(weston_tests) $(ivi_tests)
+TESTS = $(internal_tests) $(shared_tests) $(module_tests) $(weston_tests) $(ivi_tests)
+
+internal_tests = 				\
+	internal-screenshot.weston
 
 shared_tests =					\
 	config-parser.test			\
@@ -988,6 +991,7 @@
 
 noinst_PROGRAMS +=			\
 	$(setbacklight)			\
+	$(internal_tests)		\
 	$(shared_tests)			\
 	$(weston_tests)			\
 	$(ivi_tests)			\
@@ -1040,6 +1044,20 @@
 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)
+
+
+#
+# Weston Tests
+#
+
 bad_buffer_weston_SOURCES = tests/bad-buffer-test.c
 bad_buffer_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS)
 bad_buffer_weston_LDADD = libtest-client.la
diff --git a/tests/internal-screenshot-test.c b/tests/internal-screenshot-test.c
new file mode 100644
index 0000000..27b1547
--- /dev/null
+++ b/tests/internal-screenshot-test.c
@@ -0,0 +1,144 @@
+/*
+ * 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 */
+#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 surface *reference = NULL;
+	struct rectangle clip;
+	const char *fname;
+	cairo_surface_t *reference_cairo_surface;
+	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);
+	assert(screenshot);
+
+	/* 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)
+		if (wl_display_dispatch(client->wl_display) < 0)
+			break;
+	printf("Roundtrip done\n");
+
+	/* 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.
+	 * 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_surface = cairo_image_surface_create_from_png(fname);
+	status = cairo_surface_status(reference_cairo_surface);
+	if (status != CAIRO_STATUS_SUCCESS) {
+		printf("Could not open %s: %s\n", fname, cairo_status_to_string(status));
+		cairo_surface_destroy(reference_cairo_surface);
+		assert(status != CAIRO_STATUS_SUCCESS);
+	}
+
+	/* Disguise the cairo surface in a weston test surface */
+	reference =  xzalloc(sizeof *reference);
+	reference->width = cairo_image_surface_get_width(reference_cairo_surface);
+	reference->height = cairo_image_surface_get_height(reference_cairo_surface);
+	reference->data = cairo_image_surface_get_data(reference_cairo_surface);
+
+	/* 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);
+
+	/* 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 = 101;
+	clip.height = 101;
+	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_cairo_surface);
+	free(reference);
+
+	/* Test dumping of non-matching images */
+	if (!match || dump_all_images) {
+		/* Write image to .png file */
+		cairo_surface_t *surface;
+		int bpp = 4; /* ARGB assumed */
+		int stride = bpp * screenshot->width;
+
+		surface = cairo_image_surface_create_for_data(screenshot->data,
+							      CAIRO_FORMAT_ARGB32,
+							      screenshot->width,
+							      screenshot->height,
+							      stride);
+
+		printf("Writing PNG to disk\n");
+		cairo_surface_write_to_png(surface, "clientside-screenshot.png");
+		cairo_surface_destroy(surface);
+	}
+
+	free(screenshot);
+
+	printf("Test complete\n");
+	assert(match);
+}
diff --git a/tests/internal-screenshot.ini b/tests/internal-screenshot.ini
new file mode 100644
index 0000000..abc046e
--- /dev/null
+++ b/tests/internal-screenshot.ini
@@ -0,0 +1,3 @@
+[shell]
+startup-animation=none
+background-color=0xCC336699
diff --git a/tests/reference/internal-screenshot-00.png b/tests/reference/internal-screenshot-00.png
new file mode 100644
index 0000000..5dc7957
--- /dev/null
+++ b/tests/reference/internal-screenshot-00.png
Binary files differ