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 size_t uncompressed_len
;
85 const char *compressed
;
86 size_t compressed_len
;
92 error_callback_compress (void *vdata
, const char *msg
, int errnum
)
94 fprintf (stderr
, "%s", msg
);
96 fprintf (stderr
, ": %s", strerror (errnum
));
97 fprintf (stderr
, "\n");
101 static const struct zlib_test tests
[] =
107 "\x78\x9c\x03\x00\x00\x00\x00\x01",
114 ("\x78\x9c\xca\x48\xcd\xc9\xc9\xd7\x51\x28\xcf"
115 "\x2f\xca\x49\xe1\x02\x04\x00\x00\xff\xff\x21\xe7\x04\x93"),
122 ("\x78\x9c\x4b\xcf\xcf\x4f\x49\xaa"
123 "\x4c\xd5\x51\x28\xcf\x2f\xca\x49"
124 "\x01\x00\x28\xa5\x05\x5e"),
129 ("\xcc\x11\x00\x00\x00\x00\x00\x00\xd5\x13\x00\x00\x00\x00\x00\x00"
130 "\x1c\x14\x00\x00\x00\x00\x00\x00\x72\x14\x00\x00\x00\x00\x00\x00"
131 "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
132 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
133 "\xfb\x12\x00\x00\x00\x00\x00\x00\x09\x13\x00\x00\x00\x00\x00\x00"
134 "\x0c\x13\x00\x00\x00\x00\x00\x00\xcb\x13\x00\x00\x00\x00\x00\x00"
135 "\x29\x14\x00\x00\x00\x00\x00\x00\x4e\x14\x00\x00\x00\x00\x00\x00"
136 "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
137 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
138 "\xfb\x12\x00\x00\x00\x00\x00\x00\x09\x13\x00\x00\x00\x00\x00\x00"
139 "\x67\x13\x00\x00\x00\x00\x00\x00\xcb\x13\x00\x00\x00\x00\x00\x00"
140 "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
141 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
142 "\x5f\x0b\x00\x00\x00\x00\x00\x00\x6c\x0b\x00\x00\x00\x00\x00\x00"
143 "\x7d\x0b\x00\x00\x00\x00\x00\x00\x7e\x0c\x00\x00\x00\x00\x00\x00"
144 "\x38\x0f\x00\x00\x00\x00\x00\x00\x5c\x0f\x00\x00\x00\x00\x00\x00"
145 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
146 "\x83\x0c\x00\x00\x00\x00\x00\x00\xfa\x0c\x00\x00\x00\x00\x00\x00"
147 "\xfd\x0d\x00\x00\x00\x00\x00\x00\xef\x0e\x00\x00\x00\x00\x00\x00"
148 "\x14\x0f\x00\x00\x00\x00\x00\x00\x38\x0f\x00\x00\x00\x00\x00\x00"
149 "\x9f\x0f\x00\x00\x00\x00\x00\x00\xac\x0f\x00\x00\x00\x00\x00\x00"
150 "\xdb\x0f\x00\x00\x00\x00\x00\x00\xff\x0f\x00\x00\x00\x00\x00\x00"
151 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
152 "\xfd\x0d\x00\x00\x00\x00\x00\x00\xd8\x0e\x00\x00\x00\x00\x00\x00"
153 "\x9f\x0f\x00\x00\x00\x00\x00\x00\xac\x0f\x00\x00\x00\x00\x00\x00"
154 "\xdb\x0f\x00\x00\x00\x00\x00\x00\xff\x0f\x00\x00\x00\x00\x00\x00"
155 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
156 "\xfa\x0c\x00\x00\x00\x00\x00\x00\xea\x0d\x00\x00\x00\x00\x00\x00"
157 "\xef\x0e\x00\x00\x00\x00\x00\x00\x14\x0f\x00\x00\x00\x00\x00\x00"
158 "\x5c\x0f\x00\x00\x00\x00\x00\x00\x9f\x0f\x00\x00\x00\x00\x00\x00"
159 "\xac\x0f\x00\x00\x00\x00\x00\x00\xdb\x0f\x00\x00\x00\x00\x00\x00"
160 "\xff\x0f\x00\x00\x00\x00\x00\x00\x2c\x10\x00\x00\x00\x00\x00\x00"
161 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
162 "\x60\x11\x00\x00\x00\x00\x00\x00\xd1\x16\x00\x00\x00\x00\x00\x00"
163 "\x40\x0b\x00\x00\x00\x00\x00\x00\x2c\x10\x00\x00\x00\x00\x00\x00"
164 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
165 "\x7a\x00\x00\x00\x00\x00\x00\x00\xb6\x00\x00\x00\x00\x00\x00\x00"
166 "\x9f\x01\x00\x00\x00\x00\x00\x00\xa7\x01\x00\x00\x00\x00\x00\x00"
167 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
168 "\x7a\x00\x00\x00\x00\x00\x00\x00\xa9\x00\x00\x00\x00\x00\x00\x00"
169 "\x9f\x01\x00\x00\x00\x00\x00\x00\xa7\x01\x00\x00\x00\x00\x00\x00"
170 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
172 ("\x78\x9c\x3b\x23\xc8\x00\x06\x57\x85\x21\xb4\x8c\x08\x84\x2e\x82"
173 "\xd2\x73\xa1\xf4\x55\x28\x8d\x0e\x7e\x0b\x41\x68\x4e\xa8\x7e\x1e"
174 "\x28\x7d\x1a\x4a\x6b\x42\xf5\xf9\x91\x69\x5e\x3a\x9a\x79\x84\xf4"
175 "\xc7\x73\x43\xe8\x1c\x28\x5d\x0b\xa5\xeb\x78\x20\xb4\x05\x3f\x84"
176 "\x8e\xe1\xc7\xae\xbf\x19\xaa\xee\x17\x94\xfe\xcb\x0b\xa1\xdf\xf3"
177 "\x41\x68\x11\x7e\x54\x73\xe6\x43\xe9\x35\x50\xfa\x36\x94\xfe\x8f"
178 "\xc3\x7c\x98\x79\x37\xf8\xc8\xd3\x0f\x73\xd7\x2b\x1c\xee\x8a\x21"
179 "\xd2\x5d\x3a\x02\xd8\xcd\x4f\x80\xa6\x87\x8b\x62\x10\xda\x81\x1b"
180 "\xbf\xfa\x2a\x28\xbd\x0d\x4a\xcf\x67\x84\xd0\xcb\x19\xf1\xab\x5f"
181 "\x49\xa4\x7a\x00\x48\x97\x29\xd4"),
186 /* Test the hand coded samples. */
189 test_samples (struct backtrace_state
*state
)
193 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; ++i
)
198 unsigned char *uncompressed
;
199 size_t uncompressed_len
;
201 p
= malloc (12 + tests
[i
].compressed_len
);
202 memcpy (p
, "ZLIB", 4);
203 v
= tests
[i
].uncompressed_len
;
205 v
= strlen (tests
[i
].uncompressed
);
206 for (j
= 0; j
< 8; ++j
)
207 p
[j
+ 4] = (v
>> ((7 - j
) * 8)) & 0xff;
208 memcpy (p
+ 12, tests
[i
].compressed
, tests
[i
].compressed_len
);
210 uncompressed_len
= 0;
211 if (!backtrace_uncompress_zdebug (state
, (unsigned char *) p
,
212 tests
[i
].compressed_len
+ 12,
213 error_callback_compress
, NULL
,
214 &uncompressed
, &uncompressed_len
))
216 fprintf (stderr
, "test %s: uncompress failed\n", tests
[i
].name
);
221 if (uncompressed_len
!= v
)
224 "test %s: got uncompressed length %zu, want %zu\n",
225 tests
[i
].name
, uncompressed_len
, v
);
228 else if (memcmp (tests
[i
].uncompressed
, uncompressed
, v
) != 0)
232 fprintf (stderr
, "test %s: uncompressed data mismatch\n",
234 for (j
= 0; j
< v
; ++j
)
235 if (tests
[i
].uncompressed
[j
] != uncompressed
[j
])
236 fprintf (stderr
, " %zu: got %#x want %#x\n", j
,
237 uncompressed
[j
], tests
[i
].uncompressed
[j
]);
241 printf ("PASS: inflate %s\n", tests
[i
].name
);
243 backtrace_free (state
, uncompressed
, uncompressed_len
,
244 error_callback_compress
, NULL
);
251 /* Given a set of TRIALS timings, discard the lowest and highest
252 values and return the mean average of the rest. */
255 average_time (const size_t *times
, size_t trials
)
268 for (i
= 1; i
< trials
; ++i
)
283 for (i
= 0; i
< trials
; ++i
)
285 if (i
!= imax
&& i
!= imin
)
288 return sum
/ (trials
- 2);
293 /* Test a larger text, if available. */
296 test_large (struct backtrace_state
*state
)
299 unsigned char *orig_buf
;
302 char *compressed_buf
;
303 size_t compressed_bufsize
;
304 unsigned long compress_sizearg
;
305 unsigned char *uncompressed_buf
;
306 size_t uncompressed_bufsize
;
313 const size_t trials
= 16;
316 static const char * const names
[] = {
317 "Mark.Twain-Tom.Sawyer.txt",
318 "../libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt"
323 uncompressed_buf
= NULL
;
324 compressed_buf
= NULL
;
326 for (i
= 0; i
< sizeof names
/ sizeof names
[0]; ++i
)
335 len
= strlen (SRCDIR
) + strlen (names
[i
]) + 2;
336 namebuf
= malloc (len
);
342 snprintf (namebuf
, len
, "%s/%s", SRCDIR
, names
[i
]);
343 e
= fopen (namebuf
, "r");
347 if (fstat (fileno (e
), &st
) < 0)
353 rbuf
= malloc (st
.st_size
);
359 got
= fread (rbuf
, 1, st
.st_size
, e
);
370 if (orig_buf
== NULL
)
372 /* We couldn't find an input file. */
373 printf ("UNSUPPORTED: inflate large\n");
377 compressed_bufsize
= compressBound (orig_bufsize
) + 12;
378 compressed_buf
= malloc (compressed_bufsize
);
379 if (compressed_buf
== NULL
)
385 compress_sizearg
= compressed_bufsize
- 12;
386 r
= compress (compressed_buf
+ 12, &compress_sizearg
,
387 orig_buf
, orig_bufsize
);
390 fprintf (stderr
, "zlib compress failed: %d\n", r
);
394 compressed_bufsize
= compress_sizearg
+ 12;
396 /* Prepare the header that our library expects. */
397 memcpy (compressed_buf
, "ZLIB", 4);
398 for (i
= 0; i
< 8; ++i
)
399 compressed_buf
[i
+ 4] = (orig_bufsize
>> ((7 - i
) * 8)) & 0xff;
401 uncompressed_buf
= malloc (orig_bufsize
);
402 if (uncompressed_buf
== NULL
)
407 uncompressed_bufsize
= orig_bufsize
;
409 if (!backtrace_uncompress_zdebug (state
, compressed_buf
, compressed_bufsize
,
410 error_callback_compress
, NULL
,
411 &uncompressed_buf
, &uncompressed_bufsize
))
413 fprintf (stderr
, "inflate large: backtrace_uncompress_zdebug failed\n");
417 if (uncompressed_bufsize
!= orig_bufsize
)
420 "inflate large: got uncompressed length %zu, want %zu\n",
421 uncompressed_bufsize
, orig_bufsize
);
425 if (memcmp (uncompressed_buf
, orig_buf
, uncompressed_bufsize
) != 0)
427 fprintf (stderr
, "inflate large: uncompressed data mismatch\n");
431 printf ("PASS: inflate large\n");
433 for (i
= 0; i
< trials
; ++i
)
435 unsigned long uncompress_sizearg
;
437 cid
= ZLIB_CLOCK_GETTIME_ARG
;
438 if (clock_gettime (cid
, &ts1
) < 0)
442 perror ("clock_gettime");
446 if (!backtrace_uncompress_zdebug (state
, compressed_buf
,
448 error_callback_compress
, NULL
,
450 &uncompressed_bufsize
))
454 "benchmark backtrace_uncompress_zdebug failed\n"));
458 if (clock_gettime (cid
, &ts2
) < 0)
460 perror ("clock_gettime");
464 ctime
= (ts2
.tv_sec
- ts1
.tv_sec
) * 1000000000;
465 ctime
+= ts2
.tv_nsec
- ts1
.tv_nsec
;
468 if (clock_gettime (cid
, &ts1
) < 0)
470 perror("clock_gettime");
474 uncompress_sizearg
= uncompressed_bufsize
;
475 r
= uncompress (uncompressed_buf
, &uncompress_sizearg
,
476 compressed_buf
+ 12, compressed_bufsize
- 12);
478 if (clock_gettime (cid
, &ts2
) < 0)
480 perror ("clock_gettime");
487 "inflate large: benchmark zlib uncompress failed: %d\n",
492 ztime
= (ts2
.tv_sec
- ts1
.tv_sec
) * 1000000000;
493 ztime
+= ts2
.tv_nsec
- ts1
.tv_nsec
;
497 /* Toss the highest and lowest times and average the rest. */
498 ctime
= average_time (ctimes
, trials
);
499 ztime
= average_time (ztimes
, trials
);
501 printf ("backtrace: %zu ns\n", ctime
);
502 printf ("zlib : %zu ns\n", ztime
);
503 printf ("ratio : %g\n", (double) ztime
/ (double) ctime
);
508 printf ("FAIL: inflate large\n");
511 if (orig_buf
!= NULL
)
513 if (compressed_buf
!= NULL
)
514 free (compressed_buf
);
515 if (uncompressed_buf
!= NULL
)
516 free (uncompressed_buf
);
518 #else /* !HAVE_ZLIB */
520 printf ("UNSUPPORTED: inflate large\n");
522 #endif /* !HAVE_ZLIB */
526 main (int argc ATTRIBUTE_UNUSED
, char **argv
)
528 struct backtrace_state
*state
;
530 state
= backtrace_create_state (argv
[0], BACKTRACE_SUPPORTS_THREADS
,
531 error_callback_create
, NULL
);
533 test_samples (state
);
536 exit (failures
!= 0 ? EXIT_FAILURE
: EXIT_SUCCESS
);