1 /* ztest.c -- Test for libbacktrace inflate code.
2 Copyright (C) 2017-2018 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
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
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. */
40 #include <sys/types.h>
47 #include "backtrace.h"
48 #include "backtrace-supported.h"
53 #ifndef HAVE_CLOCK_GETTIME
55 typedef int xclockid_t
;
58 xclock_gettime (xclockid_t id ATTRIBUTE_UNUSED
,
59 struct timespec
*ts ATTRIBUTE_UNUSED
)
65 #define clockid_t xclockid_t
66 #define clock_gettime xclock_gettime
68 #define CLOCK_REALTIME 0
70 #endif /* !defined(HAVE_CLOCK_GETTIME) */
72 #ifdef CLOCK_PROCESS_CPUTIME_ID
73 #define ZLIB_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID
75 #define ZLIB_CLOCK_GETTIME_ARG CLOCK_REALTIME
78 /* Some tests for the local zlib inflation code. */
83 const char *uncompressed
;
84 const char *compressed
;
85 size_t compressed_len
;
91 error_callback_compress (void *vdata
, const char *msg
, int errnum
)
93 fprintf (stderr
, "%s", msg
);
95 fprintf (stderr
, ": %s", strerror (errnum
));
96 fprintf (stderr
, "\n");
100 static const struct zlib_test tests
[] =
105 "\x78\x9c\x03\x00\x00\x00\x00\x01",
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"),
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"),
125 /* Test the hand coded samples. */
128 test_samples (struct backtrace_state
*state
)
132 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; ++i
)
137 unsigned char *uncompressed
;
138 size_t uncompressed_len
;
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
);
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
))
153 fprintf (stderr
, "test %s: uncompress failed\n", tests
[i
].name
);
158 if (uncompressed_len
!= v
)
161 "test %s: got uncompressed length %zu, want %zu\n",
162 tests
[i
].name
, uncompressed_len
, v
);
165 else if (memcmp (tests
[i
].uncompressed
, uncompressed
, v
) != 0)
169 fprintf (stderr
, "test %s: uncompressed data mismatch\n",
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
]);
178 printf ("PASS: inflate %s\n", tests
[i
].name
);
180 backtrace_free (state
, uncompressed
, uncompressed_len
,
181 error_callback_compress
, NULL
);
188 /* Given a set of TRIALS timings, discard the lowest and highest
189 values and return the mean average of the rest. */
192 average_time (const size_t *times
, size_t trials
)
205 for (i
= 1; i
< trials
; ++i
)
220 for (i
= 0; i
< trials
; ++i
)
222 if (i
!= imax
&& i
!= imin
)
225 return sum
/ (trials
- 2);
230 /* Test a larger text, if available. */
233 test_large (struct backtrace_state
*state
)
236 unsigned char *orig_buf
;
239 char *compressed_buf
;
240 size_t compressed_bufsize
;
241 unsigned long compress_sizearg
;
242 unsigned char *uncompressed_buf
;
243 size_t uncompressed_bufsize
;
250 const size_t trials
= 16;
253 static const char * const names
[] = {
254 "Mark.Twain-Tom.Sawyer.txt",
255 "../libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt"
260 uncompressed_buf
= NULL
;
261 compressed_buf
= NULL
;
263 for (i
= 0; i
< sizeof names
/ sizeof names
[0]; ++i
)
272 len
= strlen (SRCDIR
) + strlen (names
[i
]) + 2;
273 namebuf
= malloc (len
);
279 snprintf (namebuf
, len
, "%s/%s", SRCDIR
, names
[i
]);
280 e
= fopen (namebuf
, "r");
284 if (fstat (fileno (e
), &st
) < 0)
290 rbuf
= malloc (st
.st_size
);
296 got
= fread (rbuf
, 1, st
.st_size
, e
);
307 if (orig_buf
== NULL
)
309 /* We couldn't find an input file. */
310 printf ("UNSUPPORTED: inflate large\n");
314 compressed_bufsize
= compressBound (orig_bufsize
) + 12;
315 compressed_buf
= malloc (compressed_bufsize
);
316 if (compressed_buf
== NULL
)
322 compress_sizearg
= compressed_bufsize
- 12;
323 r
= compress (compressed_buf
+ 12, &compress_sizearg
,
324 orig_buf
, orig_bufsize
);
327 fprintf (stderr
, "zlib compress failed: %d\n", r
);
331 compressed_bufsize
= compress_sizearg
+ 12;
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;
338 uncompressed_buf
= malloc (orig_bufsize
);
339 if (uncompressed_buf
== NULL
)
344 uncompressed_bufsize
= orig_bufsize
;
346 if (!backtrace_uncompress_zdebug (state
, compressed_buf
, compressed_bufsize
,
347 error_callback_compress
, NULL
,
348 &uncompressed_buf
, &uncompressed_bufsize
))
350 fprintf (stderr
, "inflate large: backtrace_uncompress_zdebug failed\n");
354 if (uncompressed_bufsize
!= orig_bufsize
)
357 "inflate large: got uncompressed length %zu, want %zu\n",
358 uncompressed_bufsize
, orig_bufsize
);
362 if (memcmp (uncompressed_buf
, orig_buf
, uncompressed_bufsize
) != 0)
364 fprintf (stderr
, "inflate large: uncompressed data mismatch\n");
368 printf ("PASS: inflate large\n");
370 for (i
= 0; i
< trials
; ++i
)
372 unsigned long uncompress_sizearg
;
374 cid
= ZLIB_CLOCK_GETTIME_ARG
;
375 if (clock_gettime (cid
, &ts1
) < 0)
379 perror ("clock_gettime");
383 if (!backtrace_uncompress_zdebug (state
, compressed_buf
,
385 error_callback_compress
, NULL
,
387 &uncompressed_bufsize
))
391 "benchmark backtrace_uncompress_zdebug failed\n"));
395 if (clock_gettime (cid
, &ts2
) < 0)
397 perror ("clock_gettime");
401 ctime
= (ts2
.tv_sec
- ts1
.tv_sec
) * 1000000000;
402 ctime
+= ts2
.tv_nsec
- ts1
.tv_nsec
;
405 if (clock_gettime (cid
, &ts1
) < 0)
407 perror("clock_gettime");
411 uncompress_sizearg
= uncompressed_bufsize
;
412 r
= uncompress (uncompressed_buf
, &uncompress_sizearg
,
413 compressed_buf
+ 12, compressed_bufsize
- 12);
415 if (clock_gettime (cid
, &ts2
) < 0)
417 perror ("clock_gettime");
424 "inflate large: benchmark zlib uncompress failed: %d\n",
429 ztime
= (ts2
.tv_sec
- ts1
.tv_sec
) * 1000000000;
430 ztime
+= ts2
.tv_nsec
- ts1
.tv_nsec
;
434 /* Toss the highest and lowest times and average the rest. */
435 ctime
= average_time (ctimes
, trials
);
436 ztime
= average_time (ztimes
, trials
);
438 printf ("backtrace: %zu ns\n", ctime
);
439 printf ("zlib : %zu ns\n", ztime
);
440 printf ("ratio : %g\n", (double) ztime
/ (double) ctime
);
445 printf ("FAIL: inflate large\n");
448 if (orig_buf
!= NULL
)
450 if (compressed_buf
!= NULL
)
451 free (compressed_buf
);
452 if (uncompressed_buf
!= NULL
)
453 free (uncompressed_buf
);
455 #else /* !HAVE_ZLIB */
457 printf ("UNSUPPORTED: inflate large\n");
459 #endif /* !HAVE_ZLIB */
463 main (int argc ATTRIBUTE_UNUSED
, char **argv
)
465 struct backtrace_state
*state
;
467 state
= backtrace_create_state (argv
[0], BACKTRACE_SUPPORTS_THREADS
,
468 error_callback_create
, NULL
);
470 test_samples (state
);
473 exit (failures
!= 0 ? EXIT_FAILURE
: EXIT_SUCCESS
);