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