[Pixman] [PATCH] test: larger 0xFF/0x00 filled clusters in random images for blitters-test

Siarhei Siamashka siarhei.siamashka at gmail.com
Mon Mar 4 20:34:49 PST 2013


Current blitters-test program had difficulties detecting a bug in
over_n_8888_8888_ca implementation for MIPS DSPr2:

    http://lists.freedesktop.org/archives/pixman/2013-March/002645.html

In order to hit the buggy code path, two consecutive mask values had
to be equal to 0xFFFFFFFF because of loop unrolling. The current
blitters-test generates random images in such a way that each byte
has 25% probability for having 0xFF value. Hence each 32-bit mask
value has ~0.4% probability for 0xFFFFFFFF. Because we are testing
many compositing operations with many pixels, encountering at least
one 0xFFFFFFFF mask value reasonably fast is not a problem. If a
bug related to 0xFFFFFFFF mask value is artificialy introduced into
over_n_8888_8888_ca generic C function, it gets detected on 675591
iteration in blitters-test (out of 2000000).

However two consecutive 0xFFFFFFFF mask values are much less likely
to be generated, so the bug was missed by blitters-test.

This patch addresses the problem by also randomly setting the 32-bit
values in images to either 0xFFFFFFFF or 0x00000000 (also with 25%
probability). It allows to have larger clusters of consecutive 0x00
or 0xFF bytes in images which may have special shortcuts for handling
them in unrolled or SIMD optimized code.
---
 test/blitters-test.c | 13 ++++++++++--
 test/prng-test.c     |  5 ++++-
 test/utils-prng.c    | 58 +++++++++++++++++++++++++++++++++++++++++++++++-----
 test/utils-prng.h    |  5 ++++-
 4 files changed, 72 insertions(+), 9 deletions(-)

diff --git a/test/blitters-test.c b/test/blitters-test.c
index 8766fa8..a2c6ff4 100644
--- a/test/blitters-test.c
+++ b/test/blitters-test.c
@@ -46,7 +46,16 @@ create_random_image (pixman_format_code_t *allowed_formats,
     /* do the allocation */
     buf = aligned_malloc (64, stride * height);
 
-    prng_randmemset (buf, stride * height, RANDMEMSET_MORE_00_AND_FF);
+    if (prng_rand_n (4) == 0)
+    {
+	/* uniform distribution */
+	prng_randmemset (buf, stride * height, 0);
+    }
+    else
+    {
+	/* significantly increased probability for 0x00 and 0xFF */
+	prng_randmemset (buf, stride * height, RANDMEMSET_MORE_00_AND_FF);
+    }
 
     img = pixman_image_create_bits (fmt, width, height, buf, stride);
 
@@ -393,6 +402,6 @@ main (int argc, const char *argv[])
     }
 
     return fuzzer_test_main("blitters", 2000000,
-			    0xD8265D5E,
+			    0x0CF3283B,
 			    test_composite, argc, argv);
 }
diff --git a/test/prng-test.c b/test/prng-test.c
index 0a3ad5e..c1d9320 100644
--- a/test/prng-test.c
+++ b/test/prng-test.c
@@ -106,7 +106,10 @@ int main (int argc, char *argv[])
 {
     const uint32_t ref_crc[RANDMEMSET_MORE_00_AND_FF + 1] =
     {
-        0xBA06763D, 0x103FC550, 0x8B59ABA5, 0xD82A0F39
+        0xBA06763D, 0x103FC550, 0x8B59ABA5, 0xD82A0F39,
+        0xD2321099, 0xFD8C5420, 0xD3B7C42A, 0xFC098093,
+        0x85E01DE0, 0x6680F8F7, 0x4D32DD3C, 0xAE52382B,
+        0x149E6CB5, 0x8B336987, 0x15DCB2B3, 0x8A71B781
     };
     uint32_t crc1, crc2;
     uint32_t ref, seed, seed0, seed1, seed2, seed3;
diff --git a/test/utils-prng.c b/test/utils-prng.c
index 967b898..7b32e35 100644
--- a/test/utils-prng.c
+++ b/test/utils-prng.c
@@ -107,6 +107,7 @@ randmemset_internal (prng_t                  *prng,
 {
     prng_t local_prng = *prng;
     prng_rand_128_data_t randdata;
+    size_t i;
 
     while (size >= 16)
     {
@@ -138,6 +139,22 @@ randmemset_internal (prng_t                  *prng,
                 };
                 randdata.vb &= (t.vb >= const_40);
             }
+            if (flags & RANDMEMSET_MORE_FFFFFFFF)
+            {
+                const uint32x4 const_C0000000 =
+                {
+                    0xC0000000, 0xC0000000, 0xC0000000, 0xC0000000
+                };
+                randdata.vw |= ((t.vw << 30) >= const_C0000000);
+            }
+            if (flags & RANDMEMSET_MORE_00000000)
+            {
+                const uint32x4 const_40000000 =
+                {
+                    0x40000000, 0x40000000, 0x40000000, 0x40000000
+                };
+                randdata.vw &= ((t.vw << 30) >= const_40000000);
+            }
 #else
             #define PROCESS_ONE_LANE(i)                                       \
                 if (flags & RANDMEMSET_MORE_FF)                               \
@@ -155,6 +172,18 @@ randmemset_internal (prng_t                  *prng,
                     mask_00 |= mask_00 >> 2;                                  \
                     mask_00 |= mask_00 >> 4;                                  \
                     randdata.w[i] &= mask_00;                                 \
+                }                                                             \
+                if (flags & RANDMEMSET_MORE_FFFFFFFF)                         \
+                {                                                             \
+                    int32_t mask_ff = ((t.w[i] << 30) & (t.w[i] << 31)) &     \
+                                       0x80000000;                            \
+                    randdata.w[i] |= mask_ff >> 31;                           \
+                }                                                             \
+                if (flags & RANDMEMSET_MORE_00000000)                         \
+                {                                                             \
+                    int32_t mask_00 = ((t.w[i] << 30) | (t.w[i] << 31)) &     \
+                                       0x80000000;                            \
+                    randdata.w[i] &= mask_00 >> 31;                           \
                 }
 
             PROCESS_ONE_LANE (0)
@@ -198,7 +227,8 @@ randmemset_internal (prng_t                  *prng,
         }
         size -= 16;
     }
-    while (size > 0)
+    i = 0;
+    while (i < size)
     {
         uint8_t randbyte = prng_rand_r (&local_prng) & 0xFF;
         if (flags != 0)
@@ -208,9 +238,25 @@ randmemset_internal (prng_t                  *prng,
                 randbyte = 0xFF;
             if ((flags & RANDMEMSET_MORE_00) && (t < 0x40))
                 randbyte = 0x00;
+            if (i % 4 == 0 && i + 4 <= size)
+            {
+                t = prng_rand_r (&local_prng) & 0xFF;
+                if ((flags & RANDMEMSET_MORE_FFFFFFFF) && (t >= 0xC0))
+                {
+                    memset(&buf[i], 0xFF, 4);
+                    i += 4;
+                    continue;
+                }
+                if ((flags & RANDMEMSET_MORE_00000000) && (t < 0x40))
+                {
+                    memset(&buf[i], 0x00, 4);
+                    i += 4;
+                    continue;
+                }
+            }
         }
-        *buf++ = randbyte;
-        size--;
+        buf[i] = randbyte;
+        i++;
     }
     *prng = local_prng;
 }
@@ -218,8 +264,10 @@ randmemset_internal (prng_t                  *prng,
 /*
  * Fill memory buffer with random data. Flags argument may be used
  * to tweak some statistics properties:
- *    RANDMEMSET_MORE_00 - set ~25% of bytes to 0x00
- *    RANDMEMSET_MORE_FF - set ~25% of bytes to 0xFF
+ *    RANDMEMSET_MORE_00        - set ~25% of bytes to 0x00
+ *    RANDMEMSET_MORE_FF        - set ~25% of bytes to 0xFF
+ *    RANDMEMSET_MORE_00000000  - ~25% chance for 00000000 4-byte clusters
+ *    RANDMEMSET_MORE_FFFFFFFF  - ~25% chance for FFFFFFFF 4-byte clusters
  */
 void prng_randmemset_r (prng_t                  *prng,
                         void                    *voidbuf,
diff --git a/test/utils-prng.h b/test/utils-prng.h
index 285107f..564ffce 100644
--- a/test/utils-prng.h
+++ b/test/utils-prng.h
@@ -153,7 +153,10 @@ typedef enum
 {
     RANDMEMSET_MORE_00        = 1, /* ~25% chance for 0x00 bytes */
     RANDMEMSET_MORE_FF        = 2, /* ~25% chance for 0xFF bytes */
-    RANDMEMSET_MORE_00_AND_FF = (RANDMEMSET_MORE_00 | RANDMEMSET_MORE_FF)
+    RANDMEMSET_MORE_00000000  = 4, /* ~25% chance for 0x00000000 clusters */
+    RANDMEMSET_MORE_FFFFFFFF  = 8, /* ~25% chance for 0xFFFFFFFF clusters */
+    RANDMEMSET_MORE_00_AND_FF = (RANDMEMSET_MORE_00 | RANDMEMSET_MORE_00000000 |
+                                 RANDMEMSET_MORE_FF | RANDMEMSET_MORE_FFFFFFFF)
 } prng_randmemset_flags_t;
 
 /* Set the 32-bit seed for PRNG */
-- 
1.7.12.4



More information about the Pixman mailing list