PR other/67165
[official-gcc.git] / libbacktrace / ztest.c
blob103ad65506603c8cba9e922cf885ac6a49b67cee
1 /* ztest.c -- Test for libbacktrace inflate code.
2 Copyright (C) 2017 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Google.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
12 (2) Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
17 (3) The name of the author may not be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE. */
33 #include "config.h"
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <time.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
42 #ifdef HAVE_ZLIB
43 #include <zlib.h>
44 #endif
46 #include "backtrace.h"
47 #include "backtrace-supported.h"
49 #include "internal.h"
50 #include "testlib.h"
52 /* Some tests for the local zlib inflation code. */
54 struct zlib_test
56 const char *name;
57 const char *uncompressed;
58 const char *compressed;
59 size_t compressed_len;
62 /* Error callback. */
64 static void
65 error_callback_compress (void *vdata, const char *msg, int errnum)
67 fprintf (stderr, "%s", msg);
68 if (errnum > 0)
69 fprintf (stderr, ": %s", strerror (errnum));
70 fprintf (stderr, "\n");
71 exit (EXIT_FAILURE);
74 static const struct zlib_test tests[] =
77 "empty",
78 "",
79 "\x78\x9c\x03\x00\x00\x00\x00\x01",
83 "hello",
84 "hello, world\n",
85 ("\x78\x9c\xca\x48\xcd\xc9\xc9\xd7\x51\x28\xcf"
86 "\x2f\xca\x49\xe1\x02\x04\x00\x00\xff\xff\x21\xe7\x04\x93"),
87 25,
90 "goodbye",
91 "goodbye, world",
92 ("\x78\x9c\x4b\xcf\xcf\x4f\x49\xaa"
93 "\x4c\xd5\x51\x28\xcf\x2f\xca\x49"
94 "\x01\x00\x28\xa5\x05\x5e"),
95 22,
99 /* Test the hand coded samples. */
101 static void
102 test_samples (struct backtrace_state *state)
104 size_t i;
106 for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)
108 char *p;
109 size_t v;
110 size_t j;
111 unsigned char *uncompressed;
112 size_t uncompressed_len;
114 p = malloc (12 + tests[i].compressed_len);
115 memcpy (p, "ZLIB", 4);
116 v = strlen (tests[i].uncompressed);
117 for (j = 0; j < 8; ++j)
118 p[j + 4] = (v >> ((7 - j) * 8)) & 0xff;
119 memcpy (p + 12, tests[i].compressed, tests[i].compressed_len);
120 uncompressed = NULL;
121 uncompressed_len = 0;
122 if (!backtrace_uncompress_zdebug (state, (unsigned char *) p,
123 tests[i].compressed_len + 12,
124 error_callback_compress, NULL,
125 &uncompressed, &uncompressed_len))
127 fprintf (stderr, "test %s: uncompress failed\n", tests[i].name);
128 ++failures;
130 else
132 if (uncompressed_len != v)
134 fprintf (stderr,
135 "test %s: got uncompressed length %zu, want %zu\n",
136 tests[i].name, uncompressed_len, v);
137 ++failures;
139 else if (memcmp (tests[i].uncompressed, uncompressed, v) != 0)
141 size_t j;
143 fprintf (stderr, "test %s: uncompressed data mismatch\n",
144 tests[i].name);
145 for (j = 0; j < v; ++j)
146 if (tests[i].uncompressed[j] != uncompressed[j])
147 fprintf (stderr, " %zu: got %#x want %#x\n", j,
148 uncompressed[j], tests[i].uncompressed[j]);
149 ++failures;
151 else
152 printf ("PASS: inflate %s\n", tests[i].name);
154 backtrace_free (state, uncompressed, uncompressed_len,
155 error_callback_compress, NULL);
160 #ifdef HAVE_ZLIB
162 /* Given a set of TRIALS timings, discard the lowest and highest
163 values and return the mean average of the rest. */
165 static size_t
166 average_time (const size_t *times, size_t trials)
168 size_t imax;
169 size_t max;
170 size_t imin;
171 size_t min;
172 size_t i;
173 size_t sum;
175 imin = 0;
176 imax = 0;
177 min = times[0];
178 max = times[0];
179 for (i = 1; i < trials; ++i)
181 if (times[i] < min)
183 imin = i;
184 min = times[i];
186 if (times[i] > max)
188 imax = i;
189 max = times[i];
193 sum = 0;
194 for (i = 0; i < trials; ++i)
196 if (i != imax && i != imin)
197 sum += times[i];
199 return sum / (trials - 2);
202 #endif
204 /* Test a larger text, if available. */
206 static void
207 test_large (struct backtrace_state *state)
209 #ifdef HAVE_ZLIB
210 unsigned char *orig_buf;
211 size_t orig_bufsize;
212 size_t i;
213 char *compressed_buf;
214 size_t compressed_bufsize;
215 unsigned long compress_sizearg;
216 unsigned char *uncompressed_buf;
217 size_t uncompressed_bufsize;
218 int r;
219 clockid_t cid;
220 struct timespec ts1;
221 struct timespec ts2;
222 size_t ctime;
223 size_t ztime;
224 const size_t trials = 16;
225 size_t ctimes[16];
226 size_t ztimes[16];
227 static const char * const names[] = {
228 "Mark.Twain-Tom.Sawyer.txt",
229 "../libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt"
232 orig_buf = NULL;
233 orig_bufsize = 0;
234 uncompressed_buf = NULL;
235 compressed_buf = NULL;
237 for (i = 0; i < sizeof names / sizeof names[0]; ++i)
239 size_t len;
240 char *namebuf;
241 FILE *e;
242 struct stat st;
243 char *rbuf;
244 size_t got;
246 len = strlen (SRCDIR) + strlen (names[i]) + 2;
247 namebuf = malloc (len);
248 if (namebuf == NULL)
250 perror ("malloc");
251 goto fail;
253 snprintf (namebuf, len, "%s/%s", SRCDIR, names[i]);
254 e = fopen (namebuf, "r");
255 free (namebuf);
256 if (e == NULL)
257 continue;
258 if (fstat (fileno (e), &st) < 0)
260 perror ("fstat");
261 fclose (e);
262 continue;
264 rbuf = malloc (st.st_size);
265 if (rbuf == NULL)
267 perror ("malloc");
268 goto fail;
270 got = fread (rbuf, 1, st.st_size, e);
271 fclose (e);
272 if (got > 0)
274 orig_buf = rbuf;
275 orig_bufsize = got;
276 break;
278 free (rbuf);
281 if (orig_buf == NULL)
283 /* We couldn't find an input file. */
284 printf ("UNSUPPORTED: inflate large\n");
285 return;
288 compressed_bufsize = compressBound (orig_bufsize) + 12;
289 compressed_buf = malloc (compressed_bufsize);
290 if (compressed_buf == NULL)
292 perror ("malloc");
293 goto fail;
296 compress_sizearg = compressed_bufsize - 12;
297 r = compress (compressed_buf + 12, &compress_sizearg,
298 orig_buf, orig_bufsize);
299 if (r != Z_OK)
301 fprintf (stderr, "zlib compress failed: %d\n", r);
302 goto fail;
305 compressed_bufsize = compress_sizearg + 12;
307 /* Prepare the header that our library expects. */
308 memcpy (compressed_buf, "ZLIB", 4);
309 for (i = 0; i < 8; ++i)
310 compressed_buf[i + 4] = (orig_bufsize >> ((7 - i) * 8)) & 0xff;
312 uncompressed_buf = malloc (orig_bufsize);
313 if (uncompressed_buf == NULL)
315 perror ("malloc");
316 goto fail;
318 uncompressed_bufsize = orig_bufsize;
320 if (!backtrace_uncompress_zdebug (state, compressed_buf, compressed_bufsize,
321 error_callback_compress, NULL,
322 &uncompressed_buf, &uncompressed_bufsize))
324 fprintf (stderr, "inflate large: backtrace_uncompress_zdebug failed\n");
325 goto fail;
328 if (uncompressed_bufsize != orig_bufsize)
330 fprintf (stderr,
331 "inflate large: got uncompressed length %zu, want %zu\n",
332 uncompressed_bufsize, orig_bufsize);
333 goto fail;
336 if (memcmp (uncompressed_buf, orig_buf, uncompressed_bufsize) != 0)
338 fprintf (stderr, "inflate large: uncompressed data mismatch\n");
339 goto fail;
342 printf ("PASS: inflate large\n");
344 for (i = 0; i < trials; ++i)
346 cid = CLOCK_REALTIME;
347 #ifdef CLOCK_PROCESS_CPUTIME_ID
348 cid = CLOCK_PROCESS_CPUTIME_ID;
349 #endif
350 if (clock_gettime (cid, &ts1) < 0)
352 perror ("clock_gettime");
353 return;
356 if (!backtrace_uncompress_zdebug (state, compressed_buf,
357 compressed_bufsize,
358 error_callback_compress, NULL,
359 &uncompressed_buf,
360 &uncompressed_bufsize))
362 fprintf (stderr,
363 ("inflate large: "
364 "benchmark backtrace_uncompress_zdebug failed\n"));
365 return;
368 if (clock_gettime (cid, &ts2) < 0)
370 perror ("clock_gettime");
371 return;
374 ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
375 ctime += ts2.tv_nsec - ts1.tv_nsec;
376 ctimes[i] = ctime;
378 if (clock_gettime (cid, &ts1) < 0)
380 perror("clock_gettime");
381 return;
384 r = uncompress (uncompressed_buf, &uncompressed_bufsize,
385 compressed_buf + 12, compressed_bufsize - 12);
387 if (clock_gettime (cid, &ts2) < 0)
389 perror ("clock_gettime");
390 return;
393 if (r != Z_OK)
395 fprintf (stderr,
396 "inflate large: benchmark zlib uncompress failed: %d\n",
398 return;
401 ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
402 ztime += ts2.tv_nsec - ts1.tv_nsec;
403 ztimes[i] = ztime;
406 /* Toss the highest and lowest times and average the rest. */
407 ctime = average_time (ctimes, trials);
408 ztime = average_time (ztimes, trials);
410 printf ("backtrace time: %zu ns\n", ctime);
411 printf ("zlib time: : %zu ns\n", ztime);
412 printf ("percentage : %g\n", (double) ztime / (double) ctime);
414 return;
416 fail:
417 printf ("FAIL: inflate large\n");
418 ++failures;
420 if (orig_buf != NULL)
421 free (orig_buf);
422 if (compressed_buf != NULL)
423 free (compressed_buf);
424 if (uncompressed_buf != NULL)
425 free (uncompressed_buf);
427 #else /* !HAVE_ZLIB */
429 printf ("UNSUPPORTED: inflate large\n");
431 #endif /* !HAVE_ZLIB */
435 main (int argc ATTRIBUTE_UNUSED, char **argv)
437 struct backtrace_state *state;
439 state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
440 error_callback_create, NULL);
442 test_samples (state);
443 test_large (state);
445 exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);