test: Randomize some tests if PIXMAN_RANDOMIZE_TESTS is set
[profile/ivi/pixman.git] / test / utils.c
1 #define _GNU_SOURCE
2
3 #include "utils.h"
4 #include <signal.h>
5
6 #ifdef HAVE_GETTIMEOFDAY
7 #include <sys/time.h>
8 #else
9 #include <time.h>
10 #endif
11
12 #ifdef HAVE_UNISTD_H
13 #include <unistd.h>
14 #endif
15
16 #ifdef HAVE_SYS_MMAN_H
17 #include <sys/mman.h>
18 #endif
19
20 #ifdef HAVE_FENV_H
21 #include <fenv.h>
22 #endif
23
24 /* Random number seed
25  */
26
27 uint32_t lcg_seed;
28
29 /*----------------------------------------------------------------------------*\
30  *  CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
31  *
32  *  This program generates the CRC-32 values for the files named in the
33  *  command-line arguments.  These are the same CRC-32 values used by GZIP,
34  *  PKZIP, and ZMODEM.  The Crc32_ComputeBuf () can also be detached and
35  *  used independently.
36  *
37  *  THIS PROGRAM IS PUBLIC-DOMAIN SOFTWARE.
38  *
39  *  Based on the byte-oriented implementation "File Verification Using CRC"
40  *  by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67.
41  *
42  *  v1.0.0: original release.
43  *  v1.0.1: fixed printf formats.
44  *  v1.0.2: fixed something else.
45  *  v1.0.3: replaced CRC constant table by generator function.
46  *  v1.0.4: reformatted code, made ANSI C.  1994-12-05.
47  *  v2.0.0: rewrote to use memory buffer & static table, 2006-04-29.
48 \*----------------------------------------------------------------------------*/
49
50 /*----------------------------------------------------------------------------*\
51  *  NAME:
52  *     Crc32_ComputeBuf () - computes the CRC-32 value of a memory buffer
53  *  DESCRIPTION:
54  *     Computes or accumulates the CRC-32 value for a memory buffer.
55  *     The 'inCrc32' gives a previously accumulated CRC-32 value to allow
56  *     a CRC to be generated for multiple sequential buffer-fuls of data.
57  *     The 'inCrc32' for the first buffer must be zero.
58  *  ARGUMENTS:
59  *     inCrc32 - accumulated CRC-32 value, must be 0 on first call
60  *     buf     - buffer to compute CRC-32 value for
61  *     bufLen  - number of bytes in buffer
62  *  RETURNS:
63  *     crc32 - computed CRC-32 value
64  *  ERRORS:
65  *     (no errors are possible)
66 \*----------------------------------------------------------------------------*/
67
68 uint32_t
69 compute_crc32 (uint32_t    in_crc32,
70                const void *buf,
71                size_t      buf_len)
72 {
73     static const uint32_t crc_table[256] = {
74         0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
75         0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
76         0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
77         0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
78         0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
79         0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
80         0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
81         0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
82         0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
83         0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
84         0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
85         0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
86         0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
87         0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
88         0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
89         0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
90         0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
91         0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
92         0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
93         0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
94         0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
95         0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
96         0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
97         0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
98         0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
99         0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
100         0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
101         0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
102         0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
103         0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
104         0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
105         0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
106         0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
107         0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
108         0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
109         0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
110         0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
111         0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
112         0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
113         0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
114         0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
115         0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
116         0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
117     };
118
119     uint32_t              crc32;
120     unsigned char *       byte_buf;
121     size_t                i;
122
123     /* accumulate crc32 for buffer */
124     crc32 = in_crc32 ^ 0xFFFFFFFF;
125     byte_buf = (unsigned char*) buf;
126
127     for (i = 0; i < buf_len; i++)
128         crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ byte_buf[i]) & 0xFF];
129
130     return (crc32 ^ 0xFFFFFFFF);
131 }
132
133 /* perform endian conversion of pixel data
134  */
135 void
136 image_endian_swap (pixman_image_t *img)
137 {
138     int stride = pixman_image_get_stride (img);
139     uint32_t *data = pixman_image_get_data (img);
140     int height = pixman_image_get_height (img);
141     int bpp = PIXMAN_FORMAT_BPP (pixman_image_get_format (img));
142     int i, j;
143
144     /* swap bytes only on big endian systems */
145     volatile uint16_t endian_check_var = 0x1234;
146     if (*(volatile uint8_t *)&endian_check_var != 0x12)
147         return;
148
149     if (bpp == 8)
150         return;
151
152     for (i = 0; i < height; i++)
153     {
154         uint8_t *line_data = (uint8_t *)data + stride * i;
155         
156         switch (bpp)
157         {
158         case 1:
159             for (j = 0; j < stride; j++)
160             {
161                 line_data[j] =
162                     ((line_data[j] & 0x80) >> 7) |
163                     ((line_data[j] & 0x40) >> 5) |
164                     ((line_data[j] & 0x20) >> 3) |
165                     ((line_data[j] & 0x10) >> 1) |
166                     ((line_data[j] & 0x08) << 1) |
167                     ((line_data[j] & 0x04) << 3) |
168                     ((line_data[j] & 0x02) << 5) |
169                     ((line_data[j] & 0x01) << 7);
170             }
171             break;
172         case 4:
173             for (j = 0; j < stride; j++)
174             {
175                 line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
176             }
177             break;
178         case 16:
179             for (j = 0; j + 2 <= stride; j += 2)
180             {
181                 char t1 = line_data[j + 0];
182                 char t2 = line_data[j + 1];
183
184                 line_data[j + 1] = t1;
185                 line_data[j + 0] = t2;
186             }
187             break;
188         case 24:
189             for (j = 0; j + 3 <= stride; j += 3)
190             {
191                 char t1 = line_data[j + 0];
192                 char t2 = line_data[j + 1];
193                 char t3 = line_data[j + 2];
194
195                 line_data[j + 2] = t1;
196                 line_data[j + 1] = t2;
197                 line_data[j + 0] = t3;
198             }
199             break;
200         case 32:
201             for (j = 0; j + 4 <= stride; j += 4)
202             {
203                 char t1 = line_data[j + 0];
204                 char t2 = line_data[j + 1];
205                 char t3 = line_data[j + 2];
206                 char t4 = line_data[j + 3];
207
208                 line_data[j + 3] = t1;
209                 line_data[j + 2] = t2;
210                 line_data[j + 1] = t3;
211                 line_data[j + 0] = t4;
212             }
213             break;
214         default:
215             assert (FALSE);
216             break;
217         }
218     }
219 }
220
221 #define N_LEADING_PROTECTED     10
222 #define N_TRAILING_PROTECTED    10
223
224 typedef struct
225 {
226     void *addr;
227     uint32_t len;
228     uint8_t *trailing;
229     int n_bytes;
230 } info_t;
231
232 #if defined(HAVE_MPROTECT) && defined(HAVE_GETPAGESIZE) && defined(HAVE_SYS_MMAN_H)
233
234 /* This is apparently necessary on at least OS X */
235 #ifndef MAP_ANONYMOUS
236 #define MAP_ANONYMOUS MAP_ANON
237 #endif
238
239 void *
240 fence_malloc (int64_t len)
241 {
242     unsigned long page_size = getpagesize();
243     unsigned long page_mask = page_size - 1;
244     uint32_t n_payload_bytes = (len + page_mask) & ~page_mask;
245     uint32_t n_bytes =
246         (page_size * (N_LEADING_PROTECTED + N_TRAILING_PROTECTED + 2) +
247          n_payload_bytes) & ~page_mask;
248     uint8_t *initial_page;
249     uint8_t *leading_protected;
250     uint8_t *trailing_protected;
251     uint8_t *payload;
252     uint8_t *addr;
253
254     if (len < 0)
255         abort();
256     
257     addr = mmap (NULL, n_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
258                  -1, 0);
259
260     if (addr == MAP_FAILED)
261     {
262         printf ("mmap failed on %lld %u\n", (long long int)len, n_bytes);
263         return NULL;
264     }
265
266     initial_page = (uint8_t *)(((unsigned long)addr + page_mask) & ~page_mask);
267     leading_protected = initial_page + page_size;
268     payload = leading_protected + N_LEADING_PROTECTED * page_size;
269     trailing_protected = payload + n_payload_bytes;
270
271     ((info_t *)initial_page)->addr = addr;
272     ((info_t *)initial_page)->len = len;
273     ((info_t *)initial_page)->trailing = trailing_protected;
274     ((info_t *)initial_page)->n_bytes = n_bytes;
275
276     if ((mprotect (leading_protected, N_LEADING_PROTECTED * page_size,
277                   PROT_NONE) == -1) ||
278         (mprotect (trailing_protected, N_TRAILING_PROTECTED * page_size,
279                   PROT_NONE) == -1))
280     {
281         munmap (addr, n_bytes);
282         return NULL;
283     }
284
285     return payload;
286 }
287
288 void
289 fence_free (void *data)
290 {
291     uint32_t page_size = getpagesize();
292     uint8_t *payload = data;
293     uint8_t *leading_protected = payload - N_LEADING_PROTECTED * page_size;
294     uint8_t *initial_page = leading_protected - page_size;
295     info_t *info = (info_t *)initial_page;
296
297     munmap (info->addr, info->n_bytes);
298 }
299
300 #else
301
302 void *
303 fence_malloc (int64_t len)
304 {
305     return malloc (len);
306 }
307
308 void
309 fence_free (void *data)
310 {
311     free (data);
312 }
313
314 #endif
315
316 uint8_t *
317 make_random_bytes (int n_bytes)
318 {
319     uint8_t *bytes = fence_malloc (n_bytes);
320     int i;
321
322     if (!bytes)
323         return NULL;
324
325     for (i = 0; i < n_bytes; ++i)
326         bytes[i] = lcg_rand () & 0xff;
327
328     return bytes;
329 }
330
331 /*
332  * A function, which can be used as a core part of the test programs,
333  * intended to detect various problems with the help of fuzzing input
334  * to pixman API (according to some templates, aka "smart" fuzzing).
335  * Some general information about such testing can be found here:
336  * http://en.wikipedia.org/wiki/Fuzz_testing
337  *
338  * It may help detecting:
339  *  - crashes on bad handling of valid or reasonably invalid input to
340  *    pixman API.
341  *  - deviations from the behavior of older pixman releases.
342  *  - deviations from the behavior of the same pixman release, but
343  *    configured in a different way (for example with SIMD optimizations
344  *    disabled), or running on a different OS or hardware.
345  *
346  * The test is performed by calling a callback function a huge number
347  * of times. The callback function is expected to run some snippet of
348  * pixman code with pseudorandom variations to the data feeded to
349  * pixman API. A result of running each callback function should be
350  * some deterministic value which depends on test number (test number
351  * can be used as a seed for PRNG). When 'verbose' argument is nonzero,
352  * callback function is expected to print to stdout some information
353  * about what it does.
354  *
355  * Return values from many small tests are accumulated together and
356  * used as final checksum, which can be compared to some expected
357  * value. Running the tests not individually, but in a batch helps
358  * to reduce process start overhead and also allows to parallelize
359  * testing and utilize multiple CPU cores.
360  *
361  * The resulting executable can be run without any arguments. In
362  * this case it runs a batch of tests starting from 1 and up to
363  * 'default_number_of_iterations'. The resulting checksum is
364  * compared with 'expected_checksum' and FAIL or PASS verdict
365  * depends on the result of this comparison.
366  *
367  * If the executable is run with 2 numbers provided as command line
368  * arguments, they specify the starting and ending numbers for a test
369  * batch.
370  *
371  * If the executable is run with only one number provided as a command
372  * line argument, then this number is used to call the callback function
373  * once, and also with verbose flag set.
374  */
375 int
376 fuzzer_test_main (const char *test_name,
377                   int         default_number_of_iterations,
378                   uint32_t    expected_checksum,
379                   uint32_t    (*test_function)(int testnum, int verbose),
380                   int         argc,
381                   const char *argv[])
382 {
383     int i, n1 = 1, n2 = 0;
384     uint32_t checksum = 0;
385     int verbose = getenv ("VERBOSE") != NULL;
386
387     if (argc >= 3)
388     {
389         n1 = atoi (argv[1]);
390         n2 = atoi (argv[2]);
391         if (n2 < n1)
392         {
393             printf ("invalid test range\n");
394             return 1;
395         }
396     }
397     else if (argc >= 2)
398     {
399         n2 = atoi (argv[1]);
400         checksum = test_function (n2, 1);
401         printf ("%d: checksum=%08X\n", n2, checksum);
402         return 0;
403     }
404     else
405     {
406         n1 = 1;
407         n2 = default_number_of_iterations;
408     }
409
410 #ifdef USE_OPENMP
411     #pragma omp parallel for reduction(+:checksum) default(none) \
412                                         shared(n1, n2, test_function, verbose)
413 #endif
414     for (i = n1; i <= n2; i++)
415     {
416         uint32_t crc = test_function (i, 0);
417         if (verbose)
418             printf ("%d: %08X\n", i, crc);
419         checksum += crc;
420     }
421
422     if (n1 == 1 && n2 == default_number_of_iterations)
423     {
424         if (checksum == expected_checksum)
425         {
426             printf ("%s test passed (checksum=%08X)\n",
427                     test_name, checksum);
428         }
429         else
430         {
431             printf ("%s test failed! (checksum=%08X, expected %08X)\n",
432                     test_name, checksum, expected_checksum);
433             return 1;
434         }
435     }
436     else
437     {
438         printf ("%d-%d: checksum=%08X\n", n1, n2, checksum);
439     }
440
441     return 0;
442 }
443
444 /* Try to obtain current time in seconds */
445 double
446 gettime (void)
447 {
448 #ifdef HAVE_GETTIMEOFDAY
449     struct timeval tv;
450
451     gettimeofday (&tv, NULL);
452     return (double)((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.;
453 #else
454     return (double)clock() / (double)CLOCKS_PER_SEC;
455 #endif
456 }
457
458 uint32_t
459 get_random_seed (void)
460 {
461     double d = gettime();
462
463     lcg_srand (*(uint32_t *)&d);
464
465     return lcg_rand_u32 ();
466 }
467
468 static const char *global_msg;
469
470 static void
471 on_alarm (int signo)
472 {
473     printf ("%s\n", global_msg);
474     exit (1);
475 }
476
477 void
478 fail_after (int seconds, const char *msg)
479 {
480 #ifdef HAVE_SIGACTION
481 #ifdef HAVE_ALARM
482     struct sigaction action;
483
484     global_msg = msg;
485
486     memset (&action, 0, sizeof (action));
487     action.sa_handler = on_alarm;
488
489     alarm (seconds);
490
491     sigaction (SIGALRM, &action, NULL);
492 #endif
493 #endif
494 }
495
496 void
497 enable_fp_exceptions (void)
498 {
499 #ifdef HAVE_FENV_H
500 #ifdef HAVE_FEENABLEEXCEPT
501     /* Note: we don't enable the FE_INEXACT trap because
502      * that happens quite commonly. It is possible that
503      * over- and underflow should similarly be considered
504      * okay, but for now the test suite passes with them
505      * enabled, and it's useful to know if they start
506      * occuring.
507      */
508     feenableexcept (FE_DIVBYZERO        |
509                     FE_INVALID          |
510                     FE_OVERFLOW         |
511                     FE_UNDERFLOW);
512 #endif
513 #endif
514 }
515
516 void *
517 aligned_malloc (size_t align, size_t size)
518 {
519     void *result;
520
521 #ifdef HAVE_POSIX_MEMALIGN
522     if (posix_memalign (&result, align, size) != 0)
523       result = NULL;
524 #else
525     result = malloc (size);
526 #endif
527
528     return result;
529 }
530
531 #define CONVERT_15(c, is_rgb)                                           \
532     (is_rgb?                                                            \
533      ((((c) >> 3) & 0x001f) |                                           \
534       (((c) >> 6) & 0x03e0) |                                           \
535       (((c) >> 9) & 0x7c00)) :                                          \
536      (((((c) >> 16) & 0xff) * 153 +                                     \
537        (((c) >>  8) & 0xff) * 301 +                                     \
538        (((c)      ) & 0xff) * 58) >> 2))
539
540 void
541 initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
542 {
543     int i;
544     uint32_t mask = (1 << depth) - 1;
545
546     for (i = 0; i < 32768; ++i)
547         palette->ent[i] = lcg_rand() & mask;
548
549     memset (palette->rgba, 0, sizeof (palette->rgba));
550
551     for (i = 0; i < mask + 1; ++i)
552     {
553         uint32_t rgba24;
554         pixman_bool_t retry;
555         uint32_t i15;
556
557         /* We filled the rgb->index map with random numbers, but we
558          * do need the ability to round trip, that is if some indexed
559          * color expands to an argb24, then the 15 bit version of that
560          * color must map back to the index. Anything else, we don't
561          * care about too much.
562          */
563         do
564         {
565             uint32_t old_idx;
566
567             rgba24 = lcg_rand();
568             i15 = CONVERT_15 (rgba24, is_rgb);
569
570             old_idx = palette->ent[i15];
571             if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15)
572                 retry = 1;
573             else
574                 retry = 0;
575         } while (retry);
576
577         palette->rgba[i] = rgba24;
578         palette->ent[i15] = i;
579     }
580
581     for (i = 0; i < mask + 1; ++i)
582     {
583         assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i);
584     }
585 }