New test of pixman_region_contains_{rectangle,point}
[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 pixman_bool_t
134 is_little_endian (void)
135 {
136     volatile uint16_t endian_check_var = 0x1234;
137
138     return (*(volatile uint8_t *)&endian_check_var == 0x34);
139 }
140
141 /* perform endian conversion of pixel data
142  */
143 void
144 image_endian_swap (pixman_image_t *img)
145 {
146     int stride = pixman_image_get_stride (img);
147     uint32_t *data = pixman_image_get_data (img);
148     int height = pixman_image_get_height (img);
149     int bpp = PIXMAN_FORMAT_BPP (pixman_image_get_format (img));
150     int i, j;
151
152     /* swap bytes only on big endian systems */
153     if (is_little_endian())
154         return;
155
156     if (bpp == 8)
157         return;
158
159     for (i = 0; i < height; i++)
160     {
161         uint8_t *line_data = (uint8_t *)data + stride * i;
162         
163         switch (bpp)
164         {
165         case 1:
166             for (j = 0; j < stride; j++)
167             {
168                 line_data[j] =
169                     ((line_data[j] & 0x80) >> 7) |
170                     ((line_data[j] & 0x40) >> 5) |
171                     ((line_data[j] & 0x20) >> 3) |
172                     ((line_data[j] & 0x10) >> 1) |
173                     ((line_data[j] & 0x08) << 1) |
174                     ((line_data[j] & 0x04) << 3) |
175                     ((line_data[j] & 0x02) << 5) |
176                     ((line_data[j] & 0x01) << 7);
177             }
178             break;
179         case 4:
180             for (j = 0; j < stride; j++)
181             {
182                 line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
183             }
184             break;
185         case 16:
186             for (j = 0; j + 2 <= stride; j += 2)
187             {
188                 char t1 = line_data[j + 0];
189                 char t2 = line_data[j + 1];
190
191                 line_data[j + 1] = t1;
192                 line_data[j + 0] = t2;
193             }
194             break;
195         case 24:
196             for (j = 0; j + 3 <= stride; j += 3)
197             {
198                 char t1 = line_data[j + 0];
199                 char t2 = line_data[j + 1];
200                 char t3 = line_data[j + 2];
201
202                 line_data[j + 2] = t1;
203                 line_data[j + 1] = t2;
204                 line_data[j + 0] = t3;
205             }
206             break;
207         case 32:
208             for (j = 0; j + 4 <= stride; j += 4)
209             {
210                 char t1 = line_data[j + 0];
211                 char t2 = line_data[j + 1];
212                 char t3 = line_data[j + 2];
213                 char t4 = line_data[j + 3];
214
215                 line_data[j + 3] = t1;
216                 line_data[j + 2] = t2;
217                 line_data[j + 1] = t3;
218                 line_data[j + 0] = t4;
219             }
220             break;
221         default:
222             assert (FALSE);
223             break;
224         }
225     }
226 }
227
228 #define N_LEADING_PROTECTED     10
229 #define N_TRAILING_PROTECTED    10
230
231 typedef struct
232 {
233     void *addr;
234     uint32_t len;
235     uint8_t *trailing;
236     int n_bytes;
237 } info_t;
238
239 #if defined(HAVE_MPROTECT) && defined(HAVE_GETPAGESIZE) && defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)
240
241 /* This is apparently necessary on at least OS X */
242 #ifndef MAP_ANONYMOUS
243 #define MAP_ANONYMOUS MAP_ANON
244 #endif
245
246 void *
247 fence_malloc (int64_t len)
248 {
249     unsigned long page_size = getpagesize();
250     unsigned long page_mask = page_size - 1;
251     uint32_t n_payload_bytes = (len + page_mask) & ~page_mask;
252     uint32_t n_bytes =
253         (page_size * (N_LEADING_PROTECTED + N_TRAILING_PROTECTED + 2) +
254          n_payload_bytes) & ~page_mask;
255     uint8_t *initial_page;
256     uint8_t *leading_protected;
257     uint8_t *trailing_protected;
258     uint8_t *payload;
259     uint8_t *addr;
260
261     if (len < 0)
262         abort();
263     
264     addr = mmap (NULL, n_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
265                  -1, 0);
266
267     if (addr == MAP_FAILED)
268     {
269         printf ("mmap failed on %lld %u\n", (long long int)len, n_bytes);
270         return NULL;
271     }
272
273     initial_page = (uint8_t *)(((unsigned long)addr + page_mask) & ~page_mask);
274     leading_protected = initial_page + page_size;
275     payload = leading_protected + N_LEADING_PROTECTED * page_size;
276     trailing_protected = payload + n_payload_bytes;
277
278     ((info_t *)initial_page)->addr = addr;
279     ((info_t *)initial_page)->len = len;
280     ((info_t *)initial_page)->trailing = trailing_protected;
281     ((info_t *)initial_page)->n_bytes = n_bytes;
282
283     if ((mprotect (leading_protected, N_LEADING_PROTECTED * page_size,
284                   PROT_NONE) == -1) ||
285         (mprotect (trailing_protected, N_TRAILING_PROTECTED * page_size,
286                   PROT_NONE) == -1))
287     {
288         munmap (addr, n_bytes);
289         return NULL;
290     }
291
292     return payload;
293 }
294
295 void
296 fence_free (void *data)
297 {
298     uint32_t page_size = getpagesize();
299     uint8_t *payload = data;
300     uint8_t *leading_protected = payload - N_LEADING_PROTECTED * page_size;
301     uint8_t *initial_page = leading_protected - page_size;
302     info_t *info = (info_t *)initial_page;
303
304     munmap (info->addr, info->n_bytes);
305 }
306
307 #else
308
309 void *
310 fence_malloc (int64_t len)
311 {
312     return malloc (len);
313 }
314
315 void
316 fence_free (void *data)
317 {
318     free (data);
319 }
320
321 #endif
322
323 uint8_t *
324 make_random_bytes (int n_bytes)
325 {
326     uint8_t *bytes = fence_malloc (n_bytes);
327     int i;
328
329     if (!bytes)
330         return NULL;
331
332     for (i = 0; i < n_bytes; ++i)
333         bytes[i] = lcg_rand () & 0xff;
334
335     return bytes;
336 }
337
338 /*
339  * A function, which can be used as a core part of the test programs,
340  * intended to detect various problems with the help of fuzzing input
341  * to pixman API (according to some templates, aka "smart" fuzzing).
342  * Some general information about such testing can be found here:
343  * http://en.wikipedia.org/wiki/Fuzz_testing
344  *
345  * It may help detecting:
346  *  - crashes on bad handling of valid or reasonably invalid input to
347  *    pixman API.
348  *  - deviations from the behavior of older pixman releases.
349  *  - deviations from the behavior of the same pixman release, but
350  *    configured in a different way (for example with SIMD optimizations
351  *    disabled), or running on a different OS or hardware.
352  *
353  * The test is performed by calling a callback function a huge number
354  * of times. The callback function is expected to run some snippet of
355  * pixman code with pseudorandom variations to the data feeded to
356  * pixman API. A result of running each callback function should be
357  * some deterministic value which depends on test number (test number
358  * can be used as a seed for PRNG). When 'verbose' argument is nonzero,
359  * callback function is expected to print to stdout some information
360  * about what it does.
361  *
362  * Return values from many small tests are accumulated together and
363  * used as final checksum, which can be compared to some expected
364  * value. Running the tests not individually, but in a batch helps
365  * to reduce process start overhead and also allows to parallelize
366  * testing and utilize multiple CPU cores.
367  *
368  * The resulting executable can be run without any arguments. In
369  * this case it runs a batch of tests starting from 1 and up to
370  * 'default_number_of_iterations'. The resulting checksum is
371  * compared with 'expected_checksum' and FAIL or PASS verdict
372  * depends on the result of this comparison.
373  *
374  * If the executable is run with 2 numbers provided as command line
375  * arguments, they specify the starting and ending numbers for a test
376  * batch.
377  *
378  * If the executable is run with only one number provided as a command
379  * line argument, then this number is used to call the callback function
380  * once, and also with verbose flag set.
381  */
382 int
383 fuzzer_test_main (const char *test_name,
384                   int         default_number_of_iterations,
385                   uint32_t    expected_checksum,
386                   uint32_t    (*test_function)(int testnum, int verbose),
387                   int         argc,
388                   const char *argv[])
389 {
390     int i, n1 = 1, n2 = 0;
391     uint32_t checksum = 0;
392     int verbose = getenv ("VERBOSE") != NULL;
393
394     if (argc >= 3)
395     {
396         n1 = atoi (argv[1]);
397         n2 = atoi (argv[2]);
398         if (n2 < n1)
399         {
400             printf ("invalid test range\n");
401             return 1;
402         }
403     }
404     else if (argc >= 2)
405     {
406         n2 = atoi (argv[1]);
407         checksum = test_function (n2, 1);
408         printf ("%d: checksum=%08X\n", n2, checksum);
409         return 0;
410     }
411     else
412     {
413         n1 = 1;
414         n2 = default_number_of_iterations;
415     }
416
417 #ifdef USE_OPENMP
418     #pragma omp parallel for reduction(+:checksum) default(none) \
419                                         shared(n1, n2, test_function, verbose)
420 #endif
421     for (i = n1; i <= n2; i++)
422     {
423         uint32_t crc = test_function (i, 0);
424         if (verbose)
425             printf ("%d: %08X\n", i, crc);
426         checksum += crc;
427     }
428
429     if (n1 == 1 && n2 == default_number_of_iterations)
430     {
431         if (checksum == expected_checksum)
432         {
433             printf ("%s test passed (checksum=%08X)\n",
434                     test_name, checksum);
435         }
436         else
437         {
438             printf ("%s test failed! (checksum=%08X, expected %08X)\n",
439                     test_name, checksum, expected_checksum);
440             return 1;
441         }
442     }
443     else
444     {
445         printf ("%d-%d: checksum=%08X\n", n1, n2, checksum);
446     }
447
448     return 0;
449 }
450
451 /* Try to obtain current time in seconds */
452 double
453 gettime (void)
454 {
455 #ifdef HAVE_GETTIMEOFDAY
456     struct timeval tv;
457
458     gettimeofday (&tv, NULL);
459     return (double)((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.;
460 #else
461     return (double)clock() / (double)CLOCKS_PER_SEC;
462 #endif
463 }
464
465 uint32_t
466 get_random_seed (void)
467 {
468     double d = gettime();
469
470     lcg_srand (*(uint32_t *)&d);
471
472     return lcg_rand_u32 ();
473 }
474
475 static const char *global_msg;
476
477 static void
478 on_alarm (int signo)
479 {
480     printf ("%s\n", global_msg);
481     exit (1);
482 }
483
484 void
485 fail_after (int seconds, const char *msg)
486 {
487 #ifdef HAVE_SIGACTION
488 #ifdef HAVE_ALARM
489     struct sigaction action;
490
491     global_msg = msg;
492
493     memset (&action, 0, sizeof (action));
494     action.sa_handler = on_alarm;
495
496     alarm (seconds);
497
498     sigaction (SIGALRM, &action, NULL);
499 #endif
500 #endif
501 }
502
503 void
504 enable_fp_exceptions (void)
505 {
506 #ifdef HAVE_FENV_H
507 #ifdef HAVE_FEENABLEEXCEPT
508     /* Note: we don't enable the FE_INEXACT trap because
509      * that happens quite commonly. It is possible that
510      * over- and underflow should similarly be considered
511      * okay, but for now the test suite passes with them
512      * enabled, and it's useful to know if they start
513      * occuring.
514      */
515     feenableexcept (FE_DIVBYZERO        |
516                     FE_INVALID          |
517                     FE_OVERFLOW         |
518                     FE_UNDERFLOW);
519 #endif
520 #endif
521 }
522
523 void *
524 aligned_malloc (size_t align, size_t size)
525 {
526     void *result;
527
528 #ifdef HAVE_POSIX_MEMALIGN
529     if (posix_memalign (&result, align, size) != 0)
530       result = NULL;
531 #else
532     result = malloc (size);
533 #endif
534
535     return result;
536 }
537
538 #define CONVERT_15(c, is_rgb)                                           \
539     (is_rgb?                                                            \
540      ((((c) >> 3) & 0x001f) |                                           \
541       (((c) >> 6) & 0x03e0) |                                           \
542       (((c) >> 9) & 0x7c00)) :                                          \
543      (((((c) >> 16) & 0xff) * 153 +                                     \
544        (((c) >>  8) & 0xff) * 301 +                                     \
545        (((c)      ) & 0xff) * 58) >> 2))
546
547 void
548 initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
549 {
550     int i;
551     uint32_t mask = (1 << depth) - 1;
552
553     for (i = 0; i < 32768; ++i)
554         palette->ent[i] = lcg_rand() & mask;
555
556     memset (palette->rgba, 0, sizeof (palette->rgba));
557
558     for (i = 0; i < mask + 1; ++i)
559     {
560         uint32_t rgba24;
561         pixman_bool_t retry;
562         uint32_t i15;
563
564         /* We filled the rgb->index map with random numbers, but we
565          * do need the ability to round trip, that is if some indexed
566          * color expands to an argb24, then the 15 bit version of that
567          * color must map back to the index. Anything else, we don't
568          * care about too much.
569          */
570         do
571         {
572             uint32_t old_idx;
573
574             rgba24 = lcg_rand();
575             i15 = CONVERT_15 (rgba24, is_rgb);
576
577             old_idx = palette->ent[i15];
578             if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15)
579                 retry = 1;
580             else
581                 retry = 0;
582         } while (retry);
583
584         palette->rgba[i] = rgba24;
585         palette->ent[i15] = i;
586     }
587
588     for (i = 0; i < mask + 1; ++i)
589     {
590         assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i);
591     }
592 }