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