]> git.ipfire.org Git - thirdparty/gcc.git/blame - libbacktrace/ztest.c
Daily bump.
[thirdparty/gcc.git] / libbacktrace / ztest.c
CommitLineData
8da872d9
ILT
1/* ztest.c -- Test for libbacktrace inflate code.
2 Copyright (C) 2017 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Google.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
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.
16
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.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE. */
32
33#include "config.h"
34
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>
41
42#ifdef HAVE_ZLIB
43#include <zlib.h>
44#endif
45
dbc31f20
TS
46#ifdef HAVE_CLOCK_GETTIME
47# define TEST_TIMING
48#endif
49
8da872d9
ILT
50#include "backtrace.h"
51#include "backtrace-supported.h"
52
53#include "internal.h"
54#include "testlib.h"
55
56/* Some tests for the local zlib inflation code. */
57
58struct zlib_test
59{
60 const char *name;
61 const char *uncompressed;
62 const char *compressed;
63 size_t compressed_len;
64};
65
66/* Error callback. */
67
68static void
69error_callback_compress (void *vdata, const char *msg, int errnum)
70{
71 fprintf (stderr, "%s", msg);
72 if (errnum > 0)
73 fprintf (stderr, ": %s", strerror (errnum));
74 fprintf (stderr, "\n");
75 exit (EXIT_FAILURE);
76}
77
78static const struct zlib_test tests[] =
79{
80 {
81 "empty",
82 "",
83 "\x78\x9c\x03\x00\x00\x00\x00\x01",
84 8,
85 },
86 {
87 "hello",
88 "hello, world\n",
89 ("\x78\x9c\xca\x48\xcd\xc9\xc9\xd7\x51\x28\xcf"
90 "\x2f\xca\x49\xe1\x02\x04\x00\x00\xff\xff\x21\xe7\x04\x93"),
91 25,
92 },
93 {
94 "goodbye",
95 "goodbye, world",
96 ("\x78\x9c\x4b\xcf\xcf\x4f\x49\xaa"
97 "\x4c\xd5\x51\x28\xcf\x2f\xca\x49"
98 "\x01\x00\x28\xa5\x05\x5e"),
99 22,
100 }
101};
102
103/* Test the hand coded samples. */
104
105static void
106test_samples (struct backtrace_state *state)
107{
108 size_t i;
109
110 for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)
111 {
112 char *p;
113 size_t v;
114 size_t j;
115 unsigned char *uncompressed;
116 size_t uncompressed_len;
117
118 p = malloc (12 + tests[i].compressed_len);
119 memcpy (p, "ZLIB", 4);
120 v = strlen (tests[i].uncompressed);
121 for (j = 0; j < 8; ++j)
122 p[j + 4] = (v >> ((7 - j) * 8)) & 0xff;
123 memcpy (p + 12, tests[i].compressed, tests[i].compressed_len);
124 uncompressed = NULL;
125 uncompressed_len = 0;
126 if (!backtrace_uncompress_zdebug (state, (unsigned char *) p,
127 tests[i].compressed_len + 12,
128 error_callback_compress, NULL,
129 &uncompressed, &uncompressed_len))
130 {
131 fprintf (stderr, "test %s: uncompress failed\n", tests[i].name);
132 ++failures;
133 }
134 else
135 {
136 if (uncompressed_len != v)
137 {
138 fprintf (stderr,
139 "test %s: got uncompressed length %zu, want %zu\n",
140 tests[i].name, uncompressed_len, v);
141 ++failures;
142 }
143 else if (memcmp (tests[i].uncompressed, uncompressed, v) != 0)
144 {
145 size_t j;
146
147 fprintf (stderr, "test %s: uncompressed data mismatch\n",
148 tests[i].name);
149 for (j = 0; j < v; ++j)
150 if (tests[i].uncompressed[j] != uncompressed[j])
151 fprintf (stderr, " %zu: got %#x want %#x\n", j,
152 uncompressed[j], tests[i].uncompressed[j]);
153 ++failures;
154 }
155 else
156 printf ("PASS: inflate %s\n", tests[i].name);
157
158 backtrace_free (state, uncompressed, uncompressed_len,
159 error_callback_compress, NULL);
160 }
161 }
162}
163
dbc31f20 164#if defined HAVE_ZLIB && defined TEST_TIMING
8da872d9
ILT
165
166/* Given a set of TRIALS timings, discard the lowest and highest
167 values and return the mean average of the rest. */
168
169static size_t
170average_time (const size_t *times, size_t trials)
171{
172 size_t imax;
173 size_t max;
174 size_t imin;
175 size_t min;
176 size_t i;
177 size_t sum;
178
179 imin = 0;
180 imax = 0;
181 min = times[0];
182 max = times[0];
183 for (i = 1; i < trials; ++i)
184 {
185 if (times[i] < min)
186 {
187 imin = i;
188 min = times[i];
189 }
190 if (times[i] > max)
191 {
192 imax = i;
193 max = times[i];
194 }
195 }
196
197 sum = 0;
198 for (i = 0; i < trials; ++i)
199 {
200 if (i != imax && i != imin)
201 sum += times[i];
202 }
203 return sum / (trials - 2);
204}
205
206#endif
207
208/* Test a larger text, if available. */
209
210static void
211test_large (struct backtrace_state *state)
212{
213#ifdef HAVE_ZLIB
214 unsigned char *orig_buf;
215 size_t orig_bufsize;
216 size_t i;
217 char *compressed_buf;
218 size_t compressed_bufsize;
219 unsigned long compress_sizearg;
220 unsigned char *uncompressed_buf;
221 size_t uncompressed_bufsize;
222 int r;
dbc31f20 223# ifdef TEST_TIMING
8da872d9
ILT
224 clockid_t cid;
225 struct timespec ts1;
226 struct timespec ts2;
227 size_t ctime;
228 size_t ztime;
229 const size_t trials = 16;
230 size_t ctimes[16];
231 size_t ztimes[16];
dbc31f20 232# endif /* TEST_TIMING */
8da872d9
ILT
233 static const char * const names[] = {
234 "Mark.Twain-Tom.Sawyer.txt",
235 "../libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt"
236 };
237
238 orig_buf = NULL;
239 orig_bufsize = 0;
240 uncompressed_buf = NULL;
241 compressed_buf = NULL;
242
243 for (i = 0; i < sizeof names / sizeof names[0]; ++i)
244 {
245 size_t len;
246 char *namebuf;
247 FILE *e;
248 struct stat st;
249 char *rbuf;
250 size_t got;
251
252 len = strlen (SRCDIR) + strlen (names[i]) + 2;
253 namebuf = malloc (len);
254 if (namebuf == NULL)
255 {
256 perror ("malloc");
257 goto fail;
258 }
259 snprintf (namebuf, len, "%s/%s", SRCDIR, names[i]);
260 e = fopen (namebuf, "r");
261 free (namebuf);
262 if (e == NULL)
263 continue;
264 if (fstat (fileno (e), &st) < 0)
265 {
266 perror ("fstat");
267 fclose (e);
268 continue;
269 }
270 rbuf = malloc (st.st_size);
271 if (rbuf == NULL)
272 {
273 perror ("malloc");
274 goto fail;
275 }
276 got = fread (rbuf, 1, st.st_size, e);
277 fclose (e);
278 if (got > 0)
279 {
280 orig_buf = rbuf;
281 orig_bufsize = got;
282 break;
283 }
284 free (rbuf);
285 }
286
287 if (orig_buf == NULL)
288 {
289 /* We couldn't find an input file. */
290 printf ("UNSUPPORTED: inflate large\n");
291 return;
292 }
293
294 compressed_bufsize = compressBound (orig_bufsize) + 12;
295 compressed_buf = malloc (compressed_bufsize);
296 if (compressed_buf == NULL)
297 {
298 perror ("malloc");
299 goto fail;
300 }
301
302 compress_sizearg = compressed_bufsize - 12;
303 r = compress (compressed_buf + 12, &compress_sizearg,
304 orig_buf, orig_bufsize);
305 if (r != Z_OK)
306 {
307 fprintf (stderr, "zlib compress failed: %d\n", r);
308 goto fail;
309 }
310
311 compressed_bufsize = compress_sizearg + 12;
312
313 /* Prepare the header that our library expects. */
314 memcpy (compressed_buf, "ZLIB", 4);
315 for (i = 0; i < 8; ++i)
316 compressed_buf[i + 4] = (orig_bufsize >> ((7 - i) * 8)) & 0xff;
317
318 uncompressed_buf = malloc (orig_bufsize);
319 if (uncompressed_buf == NULL)
320 {
321 perror ("malloc");
322 goto fail;
323 }
324 uncompressed_bufsize = orig_bufsize;
325
326 if (!backtrace_uncompress_zdebug (state, compressed_buf, compressed_bufsize,
327 error_callback_compress, NULL,
328 &uncompressed_buf, &uncompressed_bufsize))
329 {
330 fprintf (stderr, "inflate large: backtrace_uncompress_zdebug failed\n");
331 goto fail;
332 }
333
334 if (uncompressed_bufsize != orig_bufsize)
335 {
336 fprintf (stderr,
337 "inflate large: got uncompressed length %zu, want %zu\n",
338 uncompressed_bufsize, orig_bufsize);
339 goto fail;
340 }
341
342 if (memcmp (uncompressed_buf, orig_buf, uncompressed_bufsize) != 0)
343 {
344 fprintf (stderr, "inflate large: uncompressed data mismatch\n");
345 goto fail;
346 }
347
348 printf ("PASS: inflate large\n");
349
dbc31f20
TS
350# ifdef TEST_TIMING
351
8da872d9
ILT
352 for (i = 0; i < trials; ++i)
353 {
354 cid = CLOCK_REALTIME;
355#ifdef CLOCK_PROCESS_CPUTIME_ID
356 cid = CLOCK_PROCESS_CPUTIME_ID;
357#endif
358 if (clock_gettime (cid, &ts1) < 0)
359 {
360 perror ("clock_gettime");
361 return;
362 }
363
364 if (!backtrace_uncompress_zdebug (state, compressed_buf,
365 compressed_bufsize,
366 error_callback_compress, NULL,
367 &uncompressed_buf,
368 &uncompressed_bufsize))
369 {
370 fprintf (stderr,
371 ("inflate large: "
372 "benchmark backtrace_uncompress_zdebug failed\n"));
373 return;
374 }
375
376 if (clock_gettime (cid, &ts2) < 0)
377 {
378 perror ("clock_gettime");
379 return;
380 }
381
382 ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
383 ctime += ts2.tv_nsec - ts1.tv_nsec;
384 ctimes[i] = ctime;
385
386 if (clock_gettime (cid, &ts1) < 0)
387 {
388 perror("clock_gettime");
389 return;
390 }
391
392 r = uncompress (uncompressed_buf, &uncompressed_bufsize,
393 compressed_buf + 12, compressed_bufsize - 12);
394
395 if (clock_gettime (cid, &ts2) < 0)
396 {
397 perror ("clock_gettime");
398 return;
399 }
400
401 if (r != Z_OK)
402 {
403 fprintf (stderr,
404 "inflate large: benchmark zlib uncompress failed: %d\n",
405 r);
406 return;
407 }
408
409 ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
410 ztime += ts2.tv_nsec - ts1.tv_nsec;
411 ztimes[i] = ztime;
412 }
413
414 /* Toss the highest and lowest times and average the rest. */
415 ctime = average_time (ctimes, trials);
416 ztime = average_time (ztimes, trials);
417
418 printf ("backtrace time: %zu ns\n", ctime);
419 printf ("zlib time: : %zu ns\n", ztime);
420 printf ("percentage : %g\n", (double) ztime / (double) ctime);
421
dbc31f20
TS
422# endif /* TEST_TIMING */
423
8da872d9
ILT
424 return;
425
426 fail:
427 printf ("FAIL: inflate large\n");
428 ++failures;
429
430 if (orig_buf != NULL)
431 free (orig_buf);
432 if (compressed_buf != NULL)
433 free (compressed_buf);
434 if (uncompressed_buf != NULL)
435 free (uncompressed_buf);
436
437#else /* !HAVE_ZLIB */
438
439 printf ("UNSUPPORTED: inflate large\n");
440
441#endif /* !HAVE_ZLIB */
442}
443
444int
445main (int argc ATTRIBUTE_UNUSED, char **argv)
446{
447 struct backtrace_state *state;
448
449 state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
450 error_callback_create, NULL);
451
452 test_samples (state);
453 test_large (state);
454
455 exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);
456}