]> git.ipfire.org Git - thirdparty/gcc.git/blame - libbacktrace/ztest.c
re PR ada/82393 (Compilation error on cygwin64)
[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
8398c1df 35#include <errno.h>
8da872d9
ILT
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <time.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42
43#ifdef HAVE_ZLIB
44#include <zlib.h>
45#endif
46
47#include "backtrace.h"
48#include "backtrace-supported.h"
49
50#include "internal.h"
51#include "testlib.h"
52
8398c1df
ILT
53#ifndef HAVE_CLOCK_GETTIME
54
55typedef int xclockid_t;
56
57static int
58xclock_gettime (xclockid_t id ATTRIBUTE_UNUSED,
59 struct timespec *ts ATTRIBUTE_UNUSED)
60{
61 errno = EINVAL;
62 return -1;
63}
64
65#define clockid_t xclockid_t
66#define clock_gettime xclock_gettime
67#undef CLOCK_REALTIME
68#define CLOCK_REALTIME 0
69
70#endif /* !defined(HAVE_CLOCK_GETTIME) */
71
72#ifdef CLOCK_PROCESS_CPUTIME_ID
73#define ZLIB_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID
74#else
75#define ZLIB_CLOCK_GETTIME_ARG CLOCK_REALTIME
76#endif
77
8da872d9
ILT
78/* Some tests for the local zlib inflation code. */
79
80struct zlib_test
81{
82 const char *name;
83 const char *uncompressed;
84 const char *compressed;
85 size_t compressed_len;
86};
87
88/* Error callback. */
89
90static void
91error_callback_compress (void *vdata, const char *msg, int errnum)
92{
93 fprintf (stderr, "%s", msg);
94 if (errnum > 0)
95 fprintf (stderr, ": %s", strerror (errnum));
96 fprintf (stderr, "\n");
97 exit (EXIT_FAILURE);
98}
99
100static const struct zlib_test tests[] =
101{
102 {
103 "empty",
104 "",
105 "\x78\x9c\x03\x00\x00\x00\x00\x01",
106 8,
107 },
108 {
109 "hello",
110 "hello, world\n",
111 ("\x78\x9c\xca\x48\xcd\xc9\xc9\xd7\x51\x28\xcf"
112 "\x2f\xca\x49\xe1\x02\x04\x00\x00\xff\xff\x21\xe7\x04\x93"),
113 25,
114 },
115 {
116 "goodbye",
117 "goodbye, world",
118 ("\x78\x9c\x4b\xcf\xcf\x4f\x49\xaa"
119 "\x4c\xd5\x51\x28\xcf\x2f\xca\x49"
120 "\x01\x00\x28\xa5\x05\x5e"),
121 22,
122 }
123};
124
125/* Test the hand coded samples. */
126
127static void
128test_samples (struct backtrace_state *state)
129{
130 size_t i;
131
132 for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)
133 {
134 char *p;
135 size_t v;
136 size_t j;
137 unsigned char *uncompressed;
138 size_t uncompressed_len;
139
140 p = malloc (12 + tests[i].compressed_len);
141 memcpy (p, "ZLIB", 4);
142 v = strlen (tests[i].uncompressed);
143 for (j = 0; j < 8; ++j)
144 p[j + 4] = (v >> ((7 - j) * 8)) & 0xff;
145 memcpy (p + 12, tests[i].compressed, tests[i].compressed_len);
146 uncompressed = NULL;
147 uncompressed_len = 0;
148 if (!backtrace_uncompress_zdebug (state, (unsigned char *) p,
149 tests[i].compressed_len + 12,
150 error_callback_compress, NULL,
151 &uncompressed, &uncompressed_len))
152 {
153 fprintf (stderr, "test %s: uncompress failed\n", tests[i].name);
154 ++failures;
155 }
156 else
157 {
158 if (uncompressed_len != v)
159 {
160 fprintf (stderr,
161 "test %s: got uncompressed length %zu, want %zu\n",
162 tests[i].name, uncompressed_len, v);
163 ++failures;
164 }
165 else if (memcmp (tests[i].uncompressed, uncompressed, v) != 0)
166 {
167 size_t j;
168
169 fprintf (stderr, "test %s: uncompressed data mismatch\n",
170 tests[i].name);
171 for (j = 0; j < v; ++j)
172 if (tests[i].uncompressed[j] != uncompressed[j])
173 fprintf (stderr, " %zu: got %#x want %#x\n", j,
174 uncompressed[j], tests[i].uncompressed[j]);
175 ++failures;
176 }
177 else
178 printf ("PASS: inflate %s\n", tests[i].name);
179
180 backtrace_free (state, uncompressed, uncompressed_len,
181 error_callback_compress, NULL);
182 }
183 }
184}
185
8398c1df 186#ifdef HAVE_ZLIB
8da872d9
ILT
187
188/* Given a set of TRIALS timings, discard the lowest and highest
189 values and return the mean average of the rest. */
190
191static size_t
192average_time (const size_t *times, size_t trials)
193{
194 size_t imax;
195 size_t max;
196 size_t imin;
197 size_t min;
198 size_t i;
199 size_t sum;
200
201 imin = 0;
202 imax = 0;
203 min = times[0];
204 max = times[0];
205 for (i = 1; i < trials; ++i)
206 {
207 if (times[i] < min)
208 {
209 imin = i;
210 min = times[i];
211 }
212 if (times[i] > max)
213 {
214 imax = i;
215 max = times[i];
216 }
217 }
218
219 sum = 0;
220 for (i = 0; i < trials; ++i)
221 {
222 if (i != imax && i != imin)
223 sum += times[i];
224 }
225 return sum / (trials - 2);
226}
227
228#endif
229
230/* Test a larger text, if available. */
231
232static void
233test_large (struct backtrace_state *state)
234{
235#ifdef HAVE_ZLIB
236 unsigned char *orig_buf;
237 size_t orig_bufsize;
238 size_t i;
239 char *compressed_buf;
240 size_t compressed_bufsize;
241 unsigned long compress_sizearg;
242 unsigned char *uncompressed_buf;
243 size_t uncompressed_bufsize;
244 int r;
245 clockid_t cid;
246 struct timespec ts1;
247 struct timespec ts2;
248 size_t ctime;
249 size_t ztime;
250 const size_t trials = 16;
251 size_t ctimes[16];
252 size_t ztimes[16];
253 static const char * const names[] = {
254 "Mark.Twain-Tom.Sawyer.txt",
255 "../libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt"
256 };
257
258 orig_buf = NULL;
259 orig_bufsize = 0;
260 uncompressed_buf = NULL;
261 compressed_buf = NULL;
262
263 for (i = 0; i < sizeof names / sizeof names[0]; ++i)
264 {
265 size_t len;
266 char *namebuf;
267 FILE *e;
268 struct stat st;
269 char *rbuf;
270 size_t got;
271
272 len = strlen (SRCDIR) + strlen (names[i]) + 2;
273 namebuf = malloc (len);
274 if (namebuf == NULL)
275 {
276 perror ("malloc");
277 goto fail;
278 }
279 snprintf (namebuf, len, "%s/%s", SRCDIR, names[i]);
280 e = fopen (namebuf, "r");
281 free (namebuf);
282 if (e == NULL)
283 continue;
284 if (fstat (fileno (e), &st) < 0)
285 {
286 perror ("fstat");
287 fclose (e);
288 continue;
289 }
290 rbuf = malloc (st.st_size);
291 if (rbuf == NULL)
292 {
293 perror ("malloc");
294 goto fail;
295 }
296 got = fread (rbuf, 1, st.st_size, e);
297 fclose (e);
298 if (got > 0)
299 {
300 orig_buf = rbuf;
301 orig_bufsize = got;
302 break;
303 }
304 free (rbuf);
305 }
306
307 if (orig_buf == NULL)
308 {
309 /* We couldn't find an input file. */
310 printf ("UNSUPPORTED: inflate large\n");
311 return;
312 }
313
314 compressed_bufsize = compressBound (orig_bufsize) + 12;
315 compressed_buf = malloc (compressed_bufsize);
316 if (compressed_buf == NULL)
317 {
318 perror ("malloc");
319 goto fail;
320 }
321
322 compress_sizearg = compressed_bufsize - 12;
323 r = compress (compressed_buf + 12, &compress_sizearg,
324 orig_buf, orig_bufsize);
325 if (r != Z_OK)
326 {
327 fprintf (stderr, "zlib compress failed: %d\n", r);
328 goto fail;
329 }
330
331 compressed_bufsize = compress_sizearg + 12;
332
333 /* Prepare the header that our library expects. */
334 memcpy (compressed_buf, "ZLIB", 4);
335 for (i = 0; i < 8; ++i)
336 compressed_buf[i + 4] = (orig_bufsize >> ((7 - i) * 8)) & 0xff;
337
338 uncompressed_buf = malloc (orig_bufsize);
339 if (uncompressed_buf == NULL)
340 {
341 perror ("malloc");
342 goto fail;
343 }
344 uncompressed_bufsize = orig_bufsize;
345
346 if (!backtrace_uncompress_zdebug (state, compressed_buf, compressed_bufsize,
347 error_callback_compress, NULL,
348 &uncompressed_buf, &uncompressed_bufsize))
349 {
350 fprintf (stderr, "inflate large: backtrace_uncompress_zdebug failed\n");
351 goto fail;
352 }
353
354 if (uncompressed_bufsize != orig_bufsize)
355 {
356 fprintf (stderr,
357 "inflate large: got uncompressed length %zu, want %zu\n",
358 uncompressed_bufsize, orig_bufsize);
359 goto fail;
360 }
361
362 if (memcmp (uncompressed_buf, orig_buf, uncompressed_bufsize) != 0)
363 {
364 fprintf (stderr, "inflate large: uncompressed data mismatch\n");
365 goto fail;
366 }
367
368 printf ("PASS: inflate large\n");
369
370 for (i = 0; i < trials; ++i)
371 {
8398c1df 372 cid = ZLIB_CLOCK_GETTIME_ARG;
8da872d9
ILT
373 if (clock_gettime (cid, &ts1) < 0)
374 {
8398c1df
ILT
375 if (errno == EINVAL)
376 return;
8da872d9
ILT
377 perror ("clock_gettime");
378 return;
379 }
380
381 if (!backtrace_uncompress_zdebug (state, compressed_buf,
382 compressed_bufsize,
383 error_callback_compress, NULL,
384 &uncompressed_buf,
385 &uncompressed_bufsize))
386 {
387 fprintf (stderr,
388 ("inflate large: "
389 "benchmark backtrace_uncompress_zdebug failed\n"));
390 return;
391 }
392
393 if (clock_gettime (cid, &ts2) < 0)
394 {
395 perror ("clock_gettime");
396 return;
397 }
398
399 ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
400 ctime += ts2.tv_nsec - ts1.tv_nsec;
401 ctimes[i] = ctime;
402
403 if (clock_gettime (cid, &ts1) < 0)
404 {
405 perror("clock_gettime");
406 return;
407 }
408
409 r = uncompress (uncompressed_buf, &uncompressed_bufsize,
410 compressed_buf + 12, compressed_bufsize - 12);
411
412 if (clock_gettime (cid, &ts2) < 0)
413 {
414 perror ("clock_gettime");
415 return;
416 }
417
418 if (r != Z_OK)
419 {
420 fprintf (stderr,
421 "inflate large: benchmark zlib uncompress failed: %d\n",
422 r);
423 return;
424 }
425
426 ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
427 ztime += ts2.tv_nsec - ts1.tv_nsec;
428 ztimes[i] = ztime;
429 }
430
431 /* Toss the highest and lowest times and average the rest. */
432 ctime = average_time (ctimes, trials);
433 ztime = average_time (ztimes, trials);
434
435 printf ("backtrace time: %zu ns\n", ctime);
436 printf ("zlib time: : %zu ns\n", ztime);
437 printf ("percentage : %g\n", (double) ztime / (double) ctime);
438
439 return;
440
441 fail:
442 printf ("FAIL: inflate large\n");
443 ++failures;
444
445 if (orig_buf != NULL)
446 free (orig_buf);
447 if (compressed_buf != NULL)
448 free (compressed_buf);
449 if (uncompressed_buf != NULL)
450 free (uncompressed_buf);
451
452#else /* !HAVE_ZLIB */
453
454 printf ("UNSUPPORTED: inflate large\n");
455
456#endif /* !HAVE_ZLIB */
457}
458
459int
460main (int argc ATTRIBUTE_UNUSED, char **argv)
461{
462 struct backtrace_state *state;
463
464 state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
465 error_callback_create, NULL);
466
467 test_samples (state);
468 test_large (state);
469
470 exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);
471}