1 /* ztest.c -- Test for libbacktrace inflate code.
2 Copyright (C) 2017 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. */
39 #include <sys/types.h>
46 #include "backtrace.h"
47 #include "backtrace-supported.h"
52 /* Some tests for the local zlib inflation code. */
57 const char *uncompressed
;
58 const char *compressed
;
59 size_t compressed_len
;
65 error_callback_compress (void *vdata
, const char *msg
, int errnum
)
67 fprintf (stderr
, "%s", msg
);
69 fprintf (stderr
, ": %s", strerror (errnum
));
70 fprintf (stderr
, "\n");
74 static const struct zlib_test tests
[] =
79 "\x78\x9c\x03\x00\x00\x00\x00\x01",
85 ("\x78\x9c\xca\x48\xcd\xc9\xc9\xd7\x51\x28\xcf"
86 "\x2f\xca\x49\xe1\x02\x04\x00\x00\xff\xff\x21\xe7\x04\x93"),
92 ("\x78\x9c\x4b\xcf\xcf\x4f\x49\xaa"
93 "\x4c\xd5\x51\x28\xcf\x2f\xca\x49"
94 "\x01\x00\x28\xa5\x05\x5e"),
99 /* Test the hand coded samples. */
102 test_samples (struct backtrace_state
*state
)
106 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; ++i
)
111 unsigned char *uncompressed
;
112 size_t uncompressed_len
;
114 p
= malloc (12 + tests
[i
].compressed_len
);
115 memcpy (p
, "ZLIB", 4);
116 v
= strlen (tests
[i
].uncompressed
);
117 for (j
= 0; j
< 8; ++j
)
118 p
[j
+ 4] = (v
>> ((7 - j
) * 8)) & 0xff;
119 memcpy (p
+ 12, tests
[i
].compressed
, tests
[i
].compressed_len
);
121 uncompressed_len
= 0;
122 if (!backtrace_uncompress_zdebug (state
, (unsigned char *) p
,
123 tests
[i
].compressed_len
+ 12,
124 error_callback_compress
, NULL
,
125 &uncompressed
, &uncompressed_len
))
127 fprintf (stderr
, "test %s: uncompress failed\n", tests
[i
].name
);
132 if (uncompressed_len
!= v
)
135 "test %s: got uncompressed length %zu, want %zu\n",
136 tests
[i
].name
, uncompressed_len
, v
);
139 else if (memcmp (tests
[i
].uncompressed
, uncompressed
, v
) != 0)
143 fprintf (stderr
, "test %s: uncompressed data mismatch\n",
145 for (j
= 0; j
< v
; ++j
)
146 if (tests
[i
].uncompressed
[j
] != uncompressed
[j
])
147 fprintf (stderr
, " %zu: got %#x want %#x\n", j
,
148 uncompressed
[j
], tests
[i
].uncompressed
[j
]);
152 printf ("PASS: inflate %s\n", tests
[i
].name
);
154 backtrace_free (state
, uncompressed
, uncompressed_len
,
155 error_callback_compress
, NULL
);
162 /* Given a set of TRIALS timings, discard the lowest and highest
163 values and return the mean average of the rest. */
166 average_time (const size_t *times
, size_t trials
)
179 for (i
= 1; i
< trials
; ++i
)
194 for (i
= 0; i
< trials
; ++i
)
196 if (i
!= imax
&& i
!= imin
)
199 return sum
/ (trials
- 2);
204 /* Test a larger text, if available. */
207 test_large (struct backtrace_state
*state
)
210 unsigned char *orig_buf
;
213 char *compressed_buf
;
214 size_t compressed_bufsize
;
215 unsigned long compress_sizearg
;
216 unsigned char *uncompressed_buf
;
217 size_t uncompressed_bufsize
;
224 const size_t trials
= 16;
227 static const char * const names
[] = {
228 "Mark.Twain-Tom.Sawyer.txt",
229 "../libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt"
234 uncompressed_buf
= NULL
;
235 compressed_buf
= NULL
;
237 for (i
= 0; i
< sizeof names
/ sizeof names
[0]; ++i
)
246 len
= strlen (SRCDIR
) + strlen (names
[i
]) + 2;
247 namebuf
= malloc (len
);
253 snprintf (namebuf
, len
, "%s/%s", SRCDIR
, names
[i
]);
254 e
= fopen (namebuf
, "r");
258 if (fstat (fileno (e
), &st
) < 0)
264 rbuf
= malloc (st
.st_size
);
270 got
= fread (rbuf
, 1, st
.st_size
, e
);
281 if (orig_buf
== NULL
)
283 /* We couldn't find an input file. */
284 printf ("UNSUPPORTED: inflate large\n");
288 compressed_bufsize
= compressBound (orig_bufsize
) + 12;
289 compressed_buf
= malloc (compressed_bufsize
);
290 if (compressed_buf
== NULL
)
296 compress_sizearg
= compressed_bufsize
- 12;
297 r
= compress (compressed_buf
+ 12, &compress_sizearg
,
298 orig_buf
, orig_bufsize
);
301 fprintf (stderr
, "zlib compress failed: %d\n", r
);
305 compressed_bufsize
= compress_sizearg
+ 12;
307 /* Prepare the header that our library expects. */
308 memcpy (compressed_buf
, "ZLIB", 4);
309 for (i
= 0; i
< 8; ++i
)
310 compressed_buf
[i
+ 4] = (orig_bufsize
>> ((7 - i
) * 8)) & 0xff;
312 uncompressed_buf
= malloc (orig_bufsize
);
313 if (uncompressed_buf
== NULL
)
318 uncompressed_bufsize
= orig_bufsize
;
320 if (!backtrace_uncompress_zdebug (state
, compressed_buf
, compressed_bufsize
,
321 error_callback_compress
, NULL
,
322 &uncompressed_buf
, &uncompressed_bufsize
))
324 fprintf (stderr
, "inflate large: backtrace_uncompress_zdebug failed\n");
328 if (uncompressed_bufsize
!= orig_bufsize
)
331 "inflate large: got uncompressed length %zu, want %zu\n",
332 uncompressed_bufsize
, orig_bufsize
);
336 if (memcmp (uncompressed_buf
, orig_buf
, uncompressed_bufsize
) != 0)
338 fprintf (stderr
, "inflate large: uncompressed data mismatch\n");
342 printf ("PASS: inflate large\n");
344 for (i
= 0; i
< trials
; ++i
)
346 cid
= CLOCK_REALTIME
;
347 #ifdef CLOCK_PROCESS_CPUTIME_ID
348 cid
= CLOCK_PROCESS_CPUTIME_ID
;
350 if (clock_gettime (cid
, &ts1
) < 0)
352 perror ("clock_gettime");
356 if (!backtrace_uncompress_zdebug (state
, compressed_buf
,
358 error_callback_compress
, NULL
,
360 &uncompressed_bufsize
))
364 "benchmark backtrace_uncompress_zdebug failed\n"));
368 if (clock_gettime (cid
, &ts2
) < 0)
370 perror ("clock_gettime");
374 ctime
= (ts2
.tv_sec
- ts1
.tv_sec
) * 1000000000;
375 ctime
+= ts2
.tv_nsec
- ts1
.tv_nsec
;
378 if (clock_gettime (cid
, &ts1
) < 0)
380 perror("clock_gettime");
384 r
= uncompress (uncompressed_buf
, &uncompressed_bufsize
,
385 compressed_buf
+ 12, compressed_bufsize
- 12);
387 if (clock_gettime (cid
, &ts2
) < 0)
389 perror ("clock_gettime");
396 "inflate large: benchmark zlib uncompress failed: %d\n",
401 ztime
= (ts2
.tv_sec
- ts1
.tv_sec
) * 1000000000;
402 ztime
+= ts2
.tv_nsec
- ts1
.tv_nsec
;
406 /* Toss the highest and lowest times and average the rest. */
407 ctime
= average_time (ctimes
, trials
);
408 ztime
= average_time (ztimes
, trials
);
410 printf ("backtrace time: %zu ns\n", ctime
);
411 printf ("zlib time: : %zu ns\n", ztime
);
412 printf ("percentage : %g\n", (double) ztime
/ (double) ctime
);
417 printf ("FAIL: inflate large\n");
420 if (orig_buf
!= NULL
)
422 if (compressed_buf
!= NULL
)
423 free (compressed_buf
);
424 if (uncompressed_buf
!= NULL
)
425 free (uncompressed_buf
);
427 #else /* !HAVE_ZLIB */
429 printf ("UNSUPPORTED: inflate large\n");
431 #endif /* !HAVE_ZLIB */
435 main (int argc ATTRIBUTE_UNUSED
, char **argv
)
437 struct backtrace_state
*state
;
439 state
= backtrace_create_state (argv
[0], BACKTRACE_SUPPORTS_THREADS
,
440 error_callback_create
, NULL
);
442 test_samples (state
);
445 exit (failures
!= 0 ? EXIT_FAILURE
: EXIT_SUCCESS
);