1 /* ztest.c -- Test for libbacktrace inflate code.
2 Copyright (C) 2017-2024 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 ATTRIBUTE_UNUSED
, const char *msg
,
95 fprintf (stderr
, "%s", msg
);
97 fprintf (stderr
, ": %s", strerror (errnum
));
98 fprintf (stderr
, "\n");
102 static const struct zlib_test tests
[] =
108 "\x78\x9c\x03\x00\x00\x00\x00\x01",
115 ("\x78\x9c\xca\x48\xcd\xc9\xc9\xd7\x51\x28\xcf"
116 "\x2f\xca\x49\xe1\x02\x04\x00\x00\xff\xff\x21\xe7\x04\x93"),
123 ("\x78\x9c\x4b\xcf\xcf\x4f\x49\xaa"
124 "\x4c\xd5\x51\x28\xcf\x2f\xca\x49"
125 "\x01\x00\x28\xa5\x05\x5e"),
130 ("\xcc\x11\x00\x00\x00\x00\x00\x00\xd5\x13\x00\x00\x00\x00\x00\x00"
131 "\x1c\x14\x00\x00\x00\x00\x00\x00\x72\x14\x00\x00\x00\x00\x00\x00"
132 "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
133 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
134 "\xfb\x12\x00\x00\x00\x00\x00\x00\x09\x13\x00\x00\x00\x00\x00\x00"
135 "\x0c\x13\x00\x00\x00\x00\x00\x00\xcb\x13\x00\x00\x00\x00\x00\x00"
136 "\x29\x14\x00\x00\x00\x00\x00\x00\x4e\x14\x00\x00\x00\x00\x00\x00"
137 "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
138 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
139 "\xfb\x12\x00\x00\x00\x00\x00\x00\x09\x13\x00\x00\x00\x00\x00\x00"
140 "\x67\x13\x00\x00\x00\x00\x00\x00\xcb\x13\x00\x00\x00\x00\x00\x00"
141 "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
142 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
143 "\x5f\x0b\x00\x00\x00\x00\x00\x00\x6c\x0b\x00\x00\x00\x00\x00\x00"
144 "\x7d\x0b\x00\x00\x00\x00\x00\x00\x7e\x0c\x00\x00\x00\x00\x00\x00"
145 "\x38\x0f\x00\x00\x00\x00\x00\x00\x5c\x0f\x00\x00\x00\x00\x00\x00"
146 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
147 "\x83\x0c\x00\x00\x00\x00\x00\x00\xfa\x0c\x00\x00\x00\x00\x00\x00"
148 "\xfd\x0d\x00\x00\x00\x00\x00\x00\xef\x0e\x00\x00\x00\x00\x00\x00"
149 "\x14\x0f\x00\x00\x00\x00\x00\x00\x38\x0f\x00\x00\x00\x00\x00\x00"
150 "\x9f\x0f\x00\x00\x00\x00\x00\x00\xac\x0f\x00\x00\x00\x00\x00\x00"
151 "\xdb\x0f\x00\x00\x00\x00\x00\x00\xff\x0f\x00\x00\x00\x00\x00\x00"
152 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
153 "\xfd\x0d\x00\x00\x00\x00\x00\x00\xd8\x0e\x00\x00\x00\x00\x00\x00"
154 "\x9f\x0f\x00\x00\x00\x00\x00\x00\xac\x0f\x00\x00\x00\x00\x00\x00"
155 "\xdb\x0f\x00\x00\x00\x00\x00\x00\xff\x0f\x00\x00\x00\x00\x00\x00"
156 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
157 "\xfa\x0c\x00\x00\x00\x00\x00\x00\xea\x0d\x00\x00\x00\x00\x00\x00"
158 "\xef\x0e\x00\x00\x00\x00\x00\x00\x14\x0f\x00\x00\x00\x00\x00\x00"
159 "\x5c\x0f\x00\x00\x00\x00\x00\x00\x9f\x0f\x00\x00\x00\x00\x00\x00"
160 "\xac\x0f\x00\x00\x00\x00\x00\x00\xdb\x0f\x00\x00\x00\x00\x00\x00"
161 "\xff\x0f\x00\x00\x00\x00\x00\x00\x2c\x10\x00\x00\x00\x00\x00\x00"
162 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
163 "\x60\x11\x00\x00\x00\x00\x00\x00\xd1\x16\x00\x00\x00\x00\x00\x00"
164 "\x40\x0b\x00\x00\x00\x00\x00\x00\x2c\x10\x00\x00\x00\x00\x00\x00"
165 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
166 "\x7a\x00\x00\x00\x00\x00\x00\x00\xb6\x00\x00\x00\x00\x00\x00\x00"
167 "\x9f\x01\x00\x00\x00\x00\x00\x00\xa7\x01\x00\x00\x00\x00\x00\x00"
168 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
169 "\x7a\x00\x00\x00\x00\x00\x00\x00\xa9\x00\x00\x00\x00\x00\x00\x00"
170 "\x9f\x01\x00\x00\x00\x00\x00\x00\xa7\x01\x00\x00\x00\x00\x00\x00"
171 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
173 ("\x78\x9c\x3b\x23\xc8\x00\x06\x57\x85\x21\xb4\x8c\x08\x84\x2e\x82"
174 "\xd2\x73\xa1\xf4\x55\x28\x8d\x0e\x7e\x0b\x41\x68\x4e\xa8\x7e\x1e"
175 "\x28\x7d\x1a\x4a\x6b\x42\xf5\xf9\x91\x69\x5e\x3a\x9a\x79\x84\xf4"
176 "\xc7\x73\x43\xe8\x1c\x28\x5d\x0b\xa5\xeb\x78\x20\xb4\x05\x3f\x84"
177 "\x8e\xe1\xc7\xae\xbf\x19\xaa\xee\x17\x94\xfe\xcb\x0b\xa1\xdf\xf3"
178 "\x41\x68\x11\x7e\x54\x73\xe6\x43\xe9\x35\x50\xfa\x36\x94\xfe\x8f"
179 "\xc3\x7c\x98\x79\x37\xf8\xc8\xd3\x0f\x73\xd7\x2b\x1c\xee\x8a\x21"
180 "\xd2\x5d\x3a\x02\xd8\xcd\x4f\x80\xa6\x87\x8b\x62\x10\xda\x81\x1b"
181 "\xbf\xfa\x2a\x28\xbd\x0d\x4a\xcf\x67\x84\xd0\xcb\x19\xf1\xab\x5f"
182 "\x49\xa4\x7a\x00\x48\x97\x29\xd4"),
187 /* Test the hand coded samples. */
190 test_samples (struct backtrace_state
*state
)
194 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; ++i
)
199 unsigned char *uncompressed
;
200 size_t uncompressed_len
;
202 p
= malloc (12 + tests
[i
].compressed_len
);
203 memcpy (p
, "ZLIB", 4);
204 v
= tests
[i
].uncompressed_len
;
206 v
= strlen (tests
[i
].uncompressed
);
207 for (j
= 0; j
< 8; ++j
)
208 p
[j
+ 4] = (v
>> ((7 - j
) * 8)) & 0xff;
209 memcpy (p
+ 12, tests
[i
].compressed
, tests
[i
].compressed_len
);
211 uncompressed_len
= 0;
212 if (!backtrace_uncompress_zdebug (state
, (unsigned char *) p
,
213 tests
[i
].compressed_len
+ 12,
214 error_callback_compress
, NULL
,
215 &uncompressed
, &uncompressed_len
))
217 fprintf (stderr
, "test %s: uncompress failed\n", tests
[i
].name
);
222 if (uncompressed_len
!= v
)
225 "test %s: got uncompressed length %zu, want %zu\n",
226 tests
[i
].name
, uncompressed_len
, v
);
229 else if (memcmp (tests
[i
].uncompressed
, uncompressed
, v
) != 0)
233 fprintf (stderr
, "test %s: uncompressed data mismatch\n",
235 for (j
= 0; j
< v
; ++j
)
236 if (tests
[i
].uncompressed
[j
] != uncompressed
[j
])
237 fprintf (stderr
, " %zu: got %#x want %#x\n", j
,
238 uncompressed
[j
], tests
[i
].uncompressed
[j
]);
242 printf ("PASS: inflate %s\n", tests
[i
].name
);
244 backtrace_free (state
, uncompressed
, uncompressed_len
,
245 error_callback_compress
, NULL
);
252 /* Given a set of TRIALS timings, discard the lowest and highest
253 values and return the mean average of the rest. */
256 average_time (const size_t *times
, size_t trials
)
269 for (i
= 1; i
< trials
; ++i
)
284 for (i
= 0; i
< trials
; ++i
)
286 if (i
!= imax
&& i
!= imin
)
289 return sum
/ (trials
- 2);
294 /* Test a larger text, if available. */
297 test_large (struct backtrace_state
*state ATTRIBUTE_UNUSED
)
300 unsigned char *orig_buf
;
303 char *compressed_buf
;
304 size_t compressed_bufsize
;
305 unsigned long compress_sizearg
;
306 unsigned char *uncompressed_buf
;
307 size_t uncompressed_bufsize
;
314 const size_t trials
= 16;
317 static const char * const names
[] = {
318 "Isaac.Newton-Opticks.txt",
319 "../libgo/go/testdata/Isaac.Newton-Opticks.txt",
324 uncompressed_buf
= NULL
;
325 compressed_buf
= NULL
;
327 for (i
= 0; i
< sizeof names
/ sizeof names
[0]; ++i
)
336 len
= strlen (SRCDIR
) + strlen (names
[i
]) + 2;
337 namebuf
= malloc (len
);
343 snprintf (namebuf
, len
, "%s/%s", SRCDIR
, names
[i
]);
344 e
= fopen (namebuf
, "r");
348 if (fstat (fileno (e
), &st
) < 0)
354 rbuf
= malloc (st
.st_size
);
360 got
= fread (rbuf
, 1, st
.st_size
, e
);
364 orig_buf
= (unsigned char *) rbuf
;
371 if (orig_buf
== NULL
)
373 /* We couldn't find an input file. */
374 printf ("UNSUPPORTED: inflate large\n");
378 compressed_bufsize
= compressBound (orig_bufsize
) + 12;
379 compressed_buf
= malloc (compressed_bufsize
);
380 if (compressed_buf
== NULL
)
386 compress_sizearg
= compressed_bufsize
- 12;
387 r
= compress ((unsigned char *) compressed_buf
+ 12, &compress_sizearg
,
388 orig_buf
, orig_bufsize
);
391 fprintf (stderr
, "zlib compress failed: %d\n", r
);
395 compressed_bufsize
= compress_sizearg
+ 12;
397 /* Prepare the header that our library expects. */
398 memcpy (compressed_buf
, "ZLIB", 4);
399 for (i
= 0; i
< 8; ++i
)
400 compressed_buf
[i
+ 4] = (orig_bufsize
>> ((7 - i
) * 8)) & 0xff;
402 uncompressed_buf
= malloc (orig_bufsize
);
403 if (uncompressed_buf
== NULL
)
408 uncompressed_bufsize
= orig_bufsize
;
410 if (!backtrace_uncompress_zdebug (state
, (unsigned char *) compressed_buf
,
412 error_callback_compress
, NULL
,
413 &uncompressed_buf
, &uncompressed_bufsize
))
415 fprintf (stderr
, "inflate large: backtrace_uncompress_zdebug failed\n");
419 if (uncompressed_bufsize
!= orig_bufsize
)
422 "inflate large: got uncompressed length %zu, want %zu\n",
423 uncompressed_bufsize
, orig_bufsize
);
427 if (memcmp (uncompressed_buf
, orig_buf
, uncompressed_bufsize
) != 0)
429 fprintf (stderr
, "inflate large: uncompressed data mismatch\n");
433 printf ("PASS: inflate large\n");
435 for (i
= 0; i
< trials
; ++i
)
437 unsigned long uncompress_sizearg
;
439 cid
= ZLIB_CLOCK_GETTIME_ARG
;
440 if (clock_gettime (cid
, &ts1
) < 0)
444 perror ("clock_gettime");
448 if (!backtrace_uncompress_zdebug (state
,
449 (unsigned char *) compressed_buf
,
451 error_callback_compress
, NULL
,
453 &uncompressed_bufsize
))
457 "benchmark backtrace_uncompress_zdebug failed\n"));
461 if (clock_gettime (cid
, &ts2
) < 0)
463 perror ("clock_gettime");
467 ctime
= (ts2
.tv_sec
- ts1
.tv_sec
) * 1000000000;
468 ctime
+= ts2
.tv_nsec
- ts1
.tv_nsec
;
471 if (clock_gettime (cid
, &ts1
) < 0)
473 perror("clock_gettime");
477 uncompress_sizearg
= uncompressed_bufsize
;
478 r
= uncompress ((unsigned char *) uncompressed_buf
, &uncompress_sizearg
,
479 (unsigned char *) compressed_buf
+ 12,
480 compressed_bufsize
- 12);
482 if (clock_gettime (cid
, &ts2
) < 0)
484 perror ("clock_gettime");
491 "inflate large: benchmark zlib uncompress failed: %d\n",
496 ztime
= (ts2
.tv_sec
- ts1
.tv_sec
) * 1000000000;
497 ztime
+= ts2
.tv_nsec
- ts1
.tv_nsec
;
501 /* Toss the highest and lowest times and average the rest. */
502 ctime
= average_time (ctimes
, trials
);
503 ztime
= average_time (ztimes
, trials
);
505 printf ("backtrace: %zu ns\n", ctime
);
506 printf ("zlib : %zu ns\n", ztime
);
507 printf ("ratio : %g\n", (double) ztime
/ (double) ctime
);
512 printf ("FAIL: inflate large\n");
515 if (orig_buf
!= NULL
)
517 if (compressed_buf
!= NULL
)
518 free (compressed_buf
);
519 if (uncompressed_buf
!= NULL
)
520 free (uncompressed_buf
);
522 #else /* !HAVE_ZLIB */
524 printf ("UNSUPPORTED: inflate large\n");
526 #endif /* !HAVE_ZLIB */
530 main (int argc ATTRIBUTE_UNUSED
, char **argv
)
532 struct backtrace_state
*state
;
534 state
= backtrace_create_state (argv
[0], BACKTRACE_SUPPORTS_THREADS
,
535 error_callback_create
, NULL
);
537 test_samples (state
);
540 exit (failures
!= 0 ? EXIT_FAILURE
: EXIT_SUCCESS
);