[Spice-devel] [spice-common v2 13/13] quic: Add test case for compression/decompression
Frediano Ziglio
fziglio at redhat.com
Wed Aug 2 09:32:04 UTC 2017
>
> This only adds a basic test relying on gdk-pixbuf.
> The main limitation is that gdk-pixbuf does not handle 16bpp images,
> nor 32bpp/no alpha images. I should have picked something else instead ;)
>
> This allows at least to exercise the QUIC_IMAGE_TYPE_RGB24 and
> QUIC_IMAGE_TYPE_RGBA codepaths.
>
> Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
> ---
> configure.ac | 1 +
> m4/spice-deps.m4 | 15 ++++
> tests/Makefile.am | 22 +++++
> tests/test-quic.c | 235
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 273 insertions(+)
> create mode 100644 tests/test-quic.c
>
> diff --git a/configure.ac b/configure.ac
> index 3542161..1f2ecc0 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -47,6 +47,7 @@ SPICE_CHECK_CELT051
> SPICE_CHECK_GLIB2
> SPICE_CHECK_OPUS
> SPICE_CHECK_OPENSSL
> +SPICE_CHECK_GDK_PIXBUF
>
> SPICE_COMMON_CFLAGS='$(PIXMAN_CFLAGS) $(SMARTCARD_CFLAGS) $(CELT051_CFLAGS)
> $(GLIB2_CFLAGS) $(OPUS_CFLAGS) $(OPENSSL_CFLAGS)'
> SPICE_COMMON_CFLAGS="$SPICE_COMMON_CFLAGS -DG_LOG_DOMAIN=\\\"Spice\\\""
> diff --git a/m4/spice-deps.m4 b/m4/spice-deps.m4
> index 68e3091..3fe4a5b 100644
> --- a/m4/spice-deps.m4
> +++ b/m4/spice-deps.m4
> @@ -147,6 +147,21 @@ AC_DEFUN([SPICE_CHECK_GLIB2], [
> PKG_CHECK_MODULES(GLIB2, glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >=
> 2.22)
> ])
>
> +# SPICE_CHECK_GDK_PIXBUF
> +# ----------------------
> +# Check for the availability of gdk-pixbuf. If found, it will return the
> flags to use
> +# in the GDK_PIXBUF_CFLAGS and GDK_PIXBUF_LIBS variables, and it will define
> a
> +# HAVE_GDK_PIXBUF preprocessor symbol as well as a HAVE_GDK_PIXBUF Makefile
> conditional.
> +# ----------------
> +AC_DEFUN([SPICE_CHECK_GDK_PIXBUF], [
> + PKG_CHECK_MODULES([GDK_PIXBUF], [gdk-pixbuf-2.0], [have_gdk_pixbuf=yes],
> [have_gdk_pixbuf=no])
> +
> + AM_CONDITIONAL([HAVE_GDK_PIXBUF], [test "x$have_gdk_pixbuf" = "xyes"])
> + if test "x$have_gdk_pixbuf" = "xyes" ; then
> + AC_DEFINE([HAVE_GDK_PIXBUF], [1], [Define if gdk-pixbuf was found])
> + fi
> +])
> +
> # SPICE_CHECK_PYTHON_MODULES()
> # --------------------------
> # Adds a --enable-python-checks configure flags as well as checks for the
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index 10033c0..02f679d 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -1,6 +1,9 @@
> NULL =
>
> TESTS = test_logging test_marshallers
> +if HAVE_GDK_PIXBUF
> +TESTS += test_quic
> +endif
I would put these with other lines
> noinst_PROGRAMS = $(TESTS)
>
> test_logging_SOURCES = test-logging.c
> @@ -33,6 +36,25 @@ test_marshallers_LDADD = \
> $(GLIB2_LIBS) \
> $(NULL)
>
> +
> +if HAVE_GDK_PIXBUF
so here
TESTS += test_quic
> +test_quic_SOURCES = \
> + test-quic.c \
> + $(NULL)
> +test_quic_CFLAGS = \
> + -I$(top_srcdir) \
> + $(GLIB2_CFLAGS) \
> + $(GDK_PIXBUF_CFLAGS) \
> + $(PROTOCOL_CFLAGS) \
> + $(NULL)
> +test_quic_LDADD = \
> + $(top_builddir)/common/libspice-common.la \
> + $(GLIB2_LIBS) \
> + $(GDK_PIXBUF_LIBS) \
> + $(NULL)
> +endif
> +
> +
Maybe you want also to add test-quic.c to EXTRA_DIST in order to be
able to build a proper package if gdk-pixbuf is missing.
> # Avoid need for python(pyparsing) by end users
> TEST_MARSHALLERS = \
> generated_test_marshallers.c \
> diff --git a/tests/test-quic.c b/tests/test-quic.c
> new file mode 100644
> index 0000000..b45794f
> --- /dev/null
> +++ b/tests/test-quic.c
> @@ -0,0 +1,235 @@
I would put a license.
> +#include "common/quic.h"
shouldn't you include config.h (or syntax checks would fail) ?
> +#include <glib.h>
> +#include <gdk-pixbuf/gdk-pixbuf.h>
I would include these first.
> +
> +typedef struct {
> + QuicUsrContext usr;
> + GByteArray *dest;
> +} QuicData;
> +
> +static SPICE_GNUC_NORETURN SPICE_GNUC_PRINTF(2, 3) void
> +quic_usr_error(QuicUsrContext *usr, const char *fmt, ...)
> +{
> + va_list ap;
> +
> + va_start(ap, fmt);
> + g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, fmt, ap);
> + va_end(ap);
> +
> + g_assert_not_reached();
> +}
> +
> +static SPICE_GNUC_PRINTF(2, 3) void
> +quic_usr_warn(QuicUsrContext *usr, const char *fmt, ...)
> +{
> + va_list ap;
> +
> + va_start(ap, fmt);
> + g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, fmt, ap);
> + va_end(ap);
> +}
> +
> +static void *quic_usr_malloc(QuicUsrContext *usr, int size)
> +{
> + return g_malloc(size);
> +}
> +
> +
> +static void quic_usr_free(QuicUsrContext *usr, void *ptr)
> +{
> + g_free(ptr);
> +}
> +
> +static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int
> rows_completed)
> +{
> + QuicData *quic_data = (QuicData *)usr;
> + int initial_len = quic_data->dest->len;
> +
> + g_byte_array_set_size(quic_data->dest, quic_data->dest->len*2);
> +
> + *io_ptr = (uint32_t *)(quic_data->dest->data + initial_len);
> + return (quic_data->dest->len - initial_len)/4;
> +}
> +
> +
> +static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines)
> +{
> + g_return_val_if_reached(0);
> +}
> +
> +
> +static void init_quic_data(QuicData *quic_data)
> +{
> + quic_data->usr.error = quic_usr_error;
> + quic_data->usr.warn = quic_usr_warn;
> + quic_data->usr.info = quic_usr_warn;
> + quic_data->usr.malloc = quic_usr_malloc;
> + quic_data->usr.free = quic_usr_free;
> + quic_data->usr.more_space = quic_usr_more_space;
> + quic_data->usr.more_lines = quic_usr_more_lines;
> + quic_data->dest = g_byte_array_new();
> +}
> +
> +static GByteArray *quic_encode_from_pixbuf(GdkPixbuf *pixbuf)
> +{
> + QuicData quic_data;
> + QuicContext *quic;
> + int encoded_size;
> + QuicImageType quic_type;
> +
> + init_quic_data(&quic_data);
> + g_byte_array_set_size(quic_data.dest, 1024);
> +
> + quic = quic_create(&quic_data.usr);
> + g_assert(quic != NULL);
> + switch (gdk_pixbuf_get_n_channels(pixbuf)) {
> + case 3:
> + quic_type = QUIC_IMAGE_TYPE_RGB24;
> + break;
> + case 4:
> + quic_type = QUIC_IMAGE_TYPE_RGBA;
> + break;
> + default:
> + g_assert_not_reached();
> + }
> + encoded_size = quic_encode(quic, quic_type,
> + gdk_pixbuf_get_width(pixbuf),
> + gdk_pixbuf_get_height(pixbuf),
> + gdk_pixbuf_get_pixels(pixbuf),
> + gdk_pixbuf_get_height(pixbuf),
> + gdk_pixbuf_get_rowstride(pixbuf),
> + (uint32_t *)quic_data.dest->data,
> + quic_data.dest->len/sizeof(uint32_t));
> + encoded_size *= 4;
> + g_byte_array_set_size(quic_data.dest, encoded_size);
> + quic_destroy(quic);
> +
> + return quic_data.dest;
> +}
> +
> +static GdkPixbuf *quic_decode_to_pixbuf(GByteArray *compressed_data)
> +{
> + QuicData quic_data;
> + QuicContext *quic;
> + int encoded_size;
> + QuicImageType quic_type;
> + GdkPixbuf *pixbuf;
> + QuicImageType type;
> + int width;
> + int height;
> + int status;
> +
> + init_quic_data(&quic_data);
> + g_byte_array_free(quic_data.dest, TRUE);
> + quic_data.dest = NULL;
> +
> + quic = quic_create(&quic_data.usr);
> + g_assert(quic != NULL);
> +
> + status = quic_decode_begin(quic,
> + (uint32_t *)compressed_data->data,
> compressed_data->len/4,
> + &type, &width, &height);
> + g_assert(status == QUIC_OK);
> +
> + pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
> + (type == QUIC_IMAGE_TYPE_RGBA), 8,
> + width, height);
> + status = quic_decode(quic, type,
> + gdk_pixbuf_get_pixels(pixbuf),
> + gdk_pixbuf_get_rowstride(pixbuf));
> + g_assert(status == QUIC_OK);
> + quic_destroy(quic);
> +
> + return pixbuf;
> +}
> +
> +static void gdk_pixbuf_compare(GdkPixbuf *pixbuf_a, GdkPixbuf *pixbuf_b)
> +{
> + int width = gdk_pixbuf_get_width(pixbuf_a);
> + int height = gdk_pixbuf_get_height(pixbuf_a);
> + int n_channels = gdk_pixbuf_get_n_channels (pixbuf_a);
> + int x;
> + int y;
> + guint8 *pixels_a = gdk_pixbuf_get_pixels(pixbuf_a);
> + guint8 *pixels_b = gdk_pixbuf_get_pixels(pixbuf_a);
> +
> + g_assert(width == gdk_pixbuf_get_width(pixbuf_b));
> + g_assert(height == gdk_pixbuf_get_height(pixbuf_b));
> + g_assert(n_channels == gdk_pixbuf_get_n_channels (pixbuf_b));
> + for (y = 0; y < height; y++) {
> + for (x = 0; x < width; x++) {
> + guint8 *p_a = pixels_a + y*gdk_pixbuf_get_rowstride(pixbuf_a) +
> x*n_channels;
> + guint8 *p_b = pixels_b + y*gdk_pixbuf_get_rowstride(pixbuf_b) +
> x*n_channels;
> +
> + g_assert(p_a[0] == p_b[0]);
> + g_assert(p_a[1] == p_b[1]);
> + g_assert(p_a[2] == p_b[2]);
> + if (gdk_pixbuf_get_has_alpha(pixbuf_a)) {
> + g_assert(p_a[3] == p_b[3]);
> + }
> + }
> + }
> +}
> +
> +static GdkPixbuf *gdk_pixbuf_new_random(void)
> +{
> + gboolean has_alpha = g_random_boolean();
> + gint n_channels = g_random_int_range(3, 5);
> + gint width = g_random_int_range(100, 2000);
> + gint height = g_random_int_range(100, 2000);
> + GdkPixbuf *random_pixbuf;
> + gint i;
> + guint8 *pixels;
> +
> + random_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8, width,
> height);
> + pixels = gdk_pixbuf_get_pixels(random_pixbuf);
> + for (i = 0; i < gdk_pixbuf_get_byte_length(random_pixbuf); i++) {
> + pixels[i] = g_random_int_range(0, 256);
> + }
> +
> + return random_pixbuf;
> +}
> +
> +static void test_pixbuf(GdkPixbuf *pixbuf)
> +{
> + GdkPixbuf *uncompressed_pixbuf;
> + GByteArray *compressed_data;
> + g_assert(pixbuf != NULL);
> + g_assert (gdk_pixbuf_get_colorspace(pixbuf) == GDK_COLORSPACE_RGB);
> + g_assert (gdk_pixbuf_get_bits_per_sample(pixbuf) == 8);
> +
> + compressed_data = quic_encode_from_pixbuf(pixbuf);
> +
> + uncompressed_pixbuf = quic_decode_to_pixbuf(compressed_data);
> +
> + g_assert(gdk_pixbuf_get_byte_length(pixbuf) ==
> gdk_pixbuf_get_byte_length(uncompressed_pixbuf));
> + //g_assert(memcmp(gdk_pixbuf_get_pixels(pixbuf),
> gdk_pixbuf_get_pixels(uncompressed_pixbuf),
> gdk_pixbuf_get_byte_length(uncompressed_pixbuf)));
> + gdk_pixbuf_compare(pixbuf, uncompressed_pixbuf);
> +
> + g_byte_array_free(compressed_data, TRUE);
> + g_object_unref(uncompressed_pixbuf);
> +
> +}
> +
> +int main(int argc, char **argv)
> +{
> + if (argc == 2) {
> + GdkPixbuf *source_pixbuf;
> +
> + source_pixbuf = gdk_pixbuf_new_from_file(argv[1], NULL);
> + test_pixbuf(source_pixbuf);
> + g_object_unref(source_pixbuf);
> + } else if (argc == 1) {
> + unsigned int count;
> +
> + for (count = 0; count < 50; count++) {
> + GdkPixbuf *pixbuf = gdk_pixbuf_new_random();
> + test_pixbuf(pixbuf);
> + g_object_unref(pixbuf);
> + }
> + } else {
> + g_assert_not_reached();
> + }
> +
> + return 0;
> +}
Frediano
More information about the Spice-devel
mailing list