From 82f9b4faaf1aa63ec26b0dfd227f1a8e5e139ae2 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Thu, 7 May 2015 19:32:46 +0100 Subject: [PATCH] test: Add new fuzz tester targeting solid images This places a heavier emphasis on solid images than the other fuzz testers, and tests both single-pixel repeating bitmap images as well as those created using pixman_image_create_solid_fill(). In the former case, it also exercises the case where the bitmap contents are written to after the image's first use, which is not a use-case that any other test has previously covered. [Pekka: added the default case to the switch in test_solid ().] Reviewed-by: Pekka Paalanen --- test/Makefile.sources | 1 + test/solid-test.c | 350 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 351 insertions(+) create mode 100644 test/solid-test.c diff --git a/test/Makefile.sources b/test/Makefile.sources index 8b0e855..d0d7928 100644 --- a/test/Makefile.sources +++ b/test/Makefile.sources @@ -23,6 +23,7 @@ TESTPROGRAMS = \ composite-traps-test \ region-contains-test \ glyph-test \ + solid-test \ stress-test \ blitters-test \ affine-test \ diff --git a/test/solid-test.c b/test/solid-test.c new file mode 100644 index 0000000..7be5466 --- /dev/null +++ b/test/solid-test.c @@ -0,0 +1,350 @@ +/* + * Copyright © 2015 RISC OS Open 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. + * + * Author: Ben Avison (bavison@riscosopen.org) + * + */ + +#include "utils.h" +#include +#include + +#define WIDTH 32 +#define HEIGHT 32 + +static const pixman_op_t op_list[] = { + PIXMAN_OP_SRC, + PIXMAN_OP_OVER, + PIXMAN_OP_ADD, + PIXMAN_OP_CLEAR, + PIXMAN_OP_SRC, + PIXMAN_OP_DST, + PIXMAN_OP_OVER, + PIXMAN_OP_OVER_REVERSE, + PIXMAN_OP_IN, + PIXMAN_OP_IN_REVERSE, + PIXMAN_OP_OUT, + PIXMAN_OP_OUT_REVERSE, + PIXMAN_OP_ATOP, + PIXMAN_OP_ATOP_REVERSE, + PIXMAN_OP_XOR, + PIXMAN_OP_ADD, + PIXMAN_OP_MULTIPLY, + PIXMAN_OP_SCREEN, + PIXMAN_OP_OVERLAY, + PIXMAN_OP_DARKEN, + PIXMAN_OP_LIGHTEN, + PIXMAN_OP_HARD_LIGHT, + PIXMAN_OP_DIFFERENCE, + PIXMAN_OP_EXCLUSION, +#if 0 /* these use floating point math and are not always bitexact on different platforms */ + PIXMAN_OP_SATURATE, + PIXMAN_OP_DISJOINT_CLEAR, + PIXMAN_OP_DISJOINT_SRC, + PIXMAN_OP_DISJOINT_DST, + PIXMAN_OP_DISJOINT_OVER, + PIXMAN_OP_DISJOINT_OVER_REVERSE, + PIXMAN_OP_DISJOINT_IN, + PIXMAN_OP_DISJOINT_IN_REVERSE, + PIXMAN_OP_DISJOINT_OUT, + PIXMAN_OP_DISJOINT_OUT_REVERSE, + PIXMAN_OP_DISJOINT_ATOP, + PIXMAN_OP_DISJOINT_ATOP_REVERSE, + PIXMAN_OP_DISJOINT_XOR, + PIXMAN_OP_CONJOINT_CLEAR, + PIXMAN_OP_CONJOINT_SRC, + PIXMAN_OP_CONJOINT_DST, + PIXMAN_OP_CONJOINT_OVER, + PIXMAN_OP_CONJOINT_OVER_REVERSE, + PIXMAN_OP_CONJOINT_IN, + PIXMAN_OP_CONJOINT_IN_REVERSE, + PIXMAN_OP_CONJOINT_OUT, + PIXMAN_OP_CONJOINT_OUT_REVERSE, + PIXMAN_OP_CONJOINT_ATOP, + PIXMAN_OP_CONJOINT_ATOP_REVERSE, + PIXMAN_OP_CONJOINT_XOR, + PIXMAN_OP_COLOR_DODGE, + PIXMAN_OP_COLOR_BURN, + PIXMAN_OP_SOFT_LIGHT, + PIXMAN_OP_HSL_HUE, + PIXMAN_OP_HSL_SATURATION, + PIXMAN_OP_HSL_COLOR, + PIXMAN_OP_HSL_LUMINOSITY, +#endif +}; + +/* The first eight format in the list are by far the most widely + * used formats, so we test those more than the others + */ +#define N_MOST_LIKELY_FORMATS 8 + +static const pixman_format_code_t img_fmt_list[] = { + PIXMAN_a8r8g8b8, + PIXMAN_a8b8g8r8, + PIXMAN_x8r8g8b8, + PIXMAN_x8b8g8r8, + PIXMAN_r5g6b5, + PIXMAN_b5g6r5, + PIXMAN_a8, + PIXMAN_a1, + PIXMAN_r3g3b2, + PIXMAN_b8g8r8a8, + PIXMAN_b8g8r8x8, + PIXMAN_r8g8b8a8, + PIXMAN_r8g8b8x8, + PIXMAN_x14r6g6b6, + PIXMAN_r8g8b8, + PIXMAN_b8g8r8, +#if 0 /* These are going to use floating point in the near future */ + PIXMAN_x2r10g10b10, + PIXMAN_a2r10g10b10, + PIXMAN_x2b10g10r10, + PIXMAN_a2b10g10r10, +#endif + PIXMAN_a1r5g5b5, + PIXMAN_x1r5g5b5, + PIXMAN_a1b5g5r5, + PIXMAN_x1b5g5r5, + PIXMAN_a4r4g4b4, + PIXMAN_x4r4g4b4, + PIXMAN_a4b4g4r4, + PIXMAN_x4b4g4r4, + PIXMAN_r3g3b2, + PIXMAN_b2g3r3, + PIXMAN_a2r2g2b2, + PIXMAN_a2b2g2r2, + PIXMAN_c8, + PIXMAN_g8, + PIXMAN_x4c4, + PIXMAN_x4g4, + PIXMAN_c4, + PIXMAN_g4, + PIXMAN_g1, + PIXMAN_x4a4, + PIXMAN_a4, + PIXMAN_r1g2b1, + PIXMAN_b1g2r1, + PIXMAN_a1r1g1b1, + PIXMAN_a1b1g1r1, + PIXMAN_null +}; + +static const pixman_format_code_t mask_fmt_list[] = { + PIXMAN_a8r8g8b8, + PIXMAN_a8, + PIXMAN_a4, + PIXMAN_a1, + PIXMAN_null +}; + +static pixman_indexed_t rgb_palette[9]; +static pixman_indexed_t y_palette[9]; + +static pixman_format_code_t +random_format (const pixman_format_code_t *allowed_formats) +{ + int n = 0; + + while (allowed_formats[n] != PIXMAN_null) + n++; + + if (n > N_MOST_LIKELY_FORMATS && prng_rand_n (4) != 0) + n = N_MOST_LIKELY_FORMATS; + + return allowed_formats[prng_rand_n (n)]; +} + +static pixman_image_t * +create_multi_pixel_image (const pixman_format_code_t *allowed_formats, + uint32_t *buffer, + pixman_format_code_t *used_fmt) +{ + pixman_format_code_t fmt; + pixman_image_t *img; + int stride; + + fmt = random_format (allowed_formats); + stride = (WIDTH * PIXMAN_FORMAT_BPP (fmt) + 31) / 32 * 4; + img = pixman_image_create_bits (fmt, WIDTH, HEIGHT, buffer, stride); + + if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR) + pixman_image_set_indexed (img, &(rgb_palette[PIXMAN_FORMAT_BPP (fmt)])); + else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY) + pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)])); + + prng_randmemset (buffer, WIDTH * HEIGHT * 4, 0); + image_endian_swap (img); + + if (used_fmt) + *used_fmt = fmt; + + return img; +} + +static pixman_image_t * +create_solid_image (const pixman_format_code_t *allowed_formats, + uint32_t *buffer, + pixman_format_code_t *used_fmt) +{ + if (prng_rand_n (2)) + { + /* Use a repeating 1x1 bitmap image for solid */ + pixman_format_code_t fmt; + pixman_image_t *img, *dummy_img; + uint32_t bpp, dummy_buf; + + fmt = random_format (allowed_formats); + bpp = PIXMAN_FORMAT_BPP (fmt); + img = pixman_image_create_bits (fmt, 1, 1, buffer, 4); + pixman_image_set_repeat (img, PIXMAN_REPEAT_NORMAL); + + if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR) + pixman_image_set_indexed (img, &(rgb_palette[bpp])); + else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY) + pixman_image_set_indexed (img, &(y_palette[bpp])); + + /* Force the flags to be calculated for image with initial + * bitmap contents of 0 or 2^bpp-1 by plotting from it into a + * separate throwaway image. It is simplest to write all 0s + * or all 1s to the first word irrespective of the colour + * depth even though we actually only care about the first + * pixel since the stride has to be a whole number of words. + */ + *buffer = prng_rand_n (2) ? 0xFFFFFFFFu : 0; + dummy_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, 1, 1, + &dummy_buf, 4); + pixman_image_composite (PIXMAN_OP_SRC, img, NULL, dummy_img, + 0, 0, 0, 0, 0, 0, 1, 1); + pixman_image_unref (dummy_img); + + /* Now set the bitmap contents to a random value */ + *buffer = prng_rand (); + image_endian_swap (img); + + if (used_fmt) + *used_fmt = fmt; + + return img; + } + else + { + /* Use a native solid image */ + pixman_color_t color; + pixman_image_t *img; + + prng_randmemset (&color, sizeof color, 0); + img = pixman_image_create_solid_fill (&color); + + if (used_fmt) + *used_fmt = PIXMAN_solid; + + return img; + } +} + +static uint32_t +test_solid (int testnum, int verbose) +{ + pixman_op_t op; + uint32_t src_buf[WIDTH * HEIGHT]; + uint32_t dst_buf[WIDTH * HEIGHT]; + uint32_t mask_buf[WIDTH * HEIGHT]; + pixman_image_t *src_img; + pixman_image_t *dst_img; + pixman_image_t *mask_img = NULL; + pixman_format_code_t src_fmt, dst_fmt, mask_fmt = PIXMAN_null; + pixman_bool_t ca = 0; + uint32_t crc32; + + prng_srand (testnum); + + op = op_list[prng_rand_n (ARRAY_LENGTH (op_list))]; + + dst_img = create_multi_pixel_image (img_fmt_list, dst_buf, &dst_fmt); + switch (prng_rand_n (3)) + { + case 0: /* Solid source, no mask */ + src_img = create_solid_image (img_fmt_list, src_buf, &src_fmt); + break; + case 1: /* Solid source, bitmap mask */ + src_img = create_solid_image (img_fmt_list, src_buf, &src_fmt); + mask_img = create_multi_pixel_image (mask_fmt_list, mask_buf, &mask_fmt); + break; + case 2: /* Bitmap image, solid mask */ + src_img = create_multi_pixel_image (img_fmt_list, src_buf, &src_fmt); + mask_img = create_solid_image (mask_fmt_list, mask_buf, &mask_fmt); + break; + default: + abort (); + } + + if (mask_img) + { + ca = prng_rand_n (2); + pixman_image_set_component_alpha (mask_img, ca); + } + + if (verbose) + { + printf ("op=%s\n", operator_name (op)); + printf ("src_fmt=%s, dst_fmt=%s, mask_fmt=%s\n", + format_name (src_fmt), format_name (dst_fmt), + format_name (mask_fmt)); + printf ("src_size=%u, mask_size=%u, component_alpha=%u\n", + src_fmt == PIXMAN_solid ? 1 : src_img->bits.width, + !mask_img || mask_fmt == PIXMAN_solid ? 1 : mask_img->bits.width, + ca); + } + + pixman_image_composite (op, src_img, mask_img, dst_img, + 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); + + if (verbose) + print_image (dst_img); + + crc32 = compute_crc32_for_image (0, dst_img); + + pixman_image_unref (src_img); + pixman_image_unref (dst_img); + if (mask_img) + pixman_image_unref (mask_img); + + return crc32; +} + +int +main (int argc, const char *argv[]) +{ + int i; + + prng_srand (0); + + for (i = 1; i <= 8; i++) + { + initialize_palette (&(rgb_palette[i]), i, TRUE); + initialize_palette (&(y_palette[i]), i, FALSE); + } + + return fuzzer_test_main ("solid", 500000, + 0x1B6DFF8D, + test_solid, argc, argv); +} -- 2.7.4