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