1 /* xztest.c -- Test for libbacktrace LZMA decoder.
2 Copyright (C) 2020-2023 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. */
41 #include <sys/types.h>
48 #include "backtrace.h"
49 #include "backtrace-supported.h"
54 #ifndef HAVE_CLOCK_GETTIME
56 typedef int xclockid_t
;
59 xclock_gettime (xclockid_t id ATTRIBUTE_UNUSED
,
60 struct timespec
*ts ATTRIBUTE_UNUSED
)
66 #define clockid_t xclockid_t
67 #define clock_gettime xclock_gettime
69 #define CLOCK_REALTIME 0
71 #endif /* !defined(HAVE_CLOCK_GETTIME) */
73 #ifdef CLOCK_PROCESS_CPUTIME_ID
74 #define LIBLZMA_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID
76 #define LIBLZMA_CLOCK_GETTIME_ARG CLOCK_REALTIME
79 /* Some tests for the local lzma inflation code. */
84 const char *uncompressed
;
85 size_t uncompressed_len
;
86 const char *compressed
;
87 size_t compressed_len
;
93 error_callback_compress (void *vdata ATTRIBUTE_UNUSED
, const char *msg
,
96 fprintf (stderr
, "%s", msg
);
98 fprintf (stderr
, ": %s", strerror (errnum
));
99 fprintf (stderr
, "\n");
103 static const struct lzma_test tests
[] =
109 ("\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x00\x00\x00\x00"
110 "\x1c\xdf\x44\x21\x1f\xb6\xf3\x7d\x01\x00\x00\x00\x00\x04\x59\x5a"),
117 ("\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21\x01"
118 "\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x0c\x68\x65\x6c\x6c\x6f"
119 "\x2c\x20\x77\x6f\x72\x6c\x64\x0a\x00\x00\x00\x00\x7b\x46\x5a\x81"
120 "\xc9\x12\xb8\xea\x00\x01\x25\x0d\x71\x19\xc4\xb6\x1f\xb6\xf3\x7d"
121 "\x01\x00\x00\x00\x00\x04\x59\x5a"),
128 ("\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21\x01"
129 "\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x0d\x67\x6f\x6f\x64\x62"
130 "\x79\x65\x2c\x20\x77\x6f\x72\x6c\x64\x00\x00\x00\xf6\xf8\xa3\x33"
131 "\x8c\x4e\xc9\x68\x00\x01\x26\x0e\x08\x1b\xe0\x04\x1f\xb6\xf3\x7d"
132 "\x01\x00\x00\x00\x00\x04\x59\x5a"),
137 /* Test the hand coded samples. */
140 test_samples (struct backtrace_state
*state
)
144 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; ++i
)
146 unsigned char *uncompressed
;
147 size_t uncompressed_len
;
150 uncompressed_len
= 0;
151 if (!backtrace_uncompress_lzma (state
,
152 ((const unsigned char *)
153 tests
[i
].compressed
),
154 tests
[i
].compressed_len
,
155 error_callback_compress
, NULL
,
156 &uncompressed
, &uncompressed_len
))
158 fprintf (stderr
, "test %s: uncompress failed\n", tests
[i
].name
);
165 v
= tests
[i
].uncompressed_len
;
167 v
= strlen (tests
[i
].uncompressed
);
168 if (uncompressed_len
!= v
)
171 "test %s: got uncompressed length %zu, want %zu\n",
172 tests
[i
].name
, uncompressed_len
, v
);
175 else if (v
> 0 && memcmp (tests
[i
].uncompressed
, uncompressed
, v
) != 0)
179 fprintf (stderr
, "test %s: uncompressed data mismatch\n",
181 for (j
= 0; j
< v
; ++j
)
182 if (tests
[i
].uncompressed
[j
] != uncompressed
[j
])
183 fprintf (stderr
, " %zu: got %#x want %#x\n", j
,
184 uncompressed
[j
], tests
[i
].uncompressed
[j
]);
188 printf ("PASS: lzma %s\n", tests
[i
].name
);
190 backtrace_free (state
, uncompressed
, uncompressed_len
,
191 error_callback_compress
, NULL
);
198 /* Given a set of TRIALS timings, discard the lowest and highest
199 values and return the mean average of the rest. */
202 average_time (const size_t *times
, size_t trials
)
215 for (i
= 1; i
< trials
; ++i
)
230 for (i
= 0; i
< trials
; ++i
)
232 if (i
!= imax
&& i
!= imin
)
235 return sum
/ (trials
- 2);
240 /* Test a larger text, if available. */
243 test_large (struct backtrace_state
*state ATTRIBUTE_UNUSED
)
246 unsigned char *orig_buf
;
249 lzma_stream initial_stream
= LZMA_STREAM_INIT
;
251 unsigned char *compressed_buf
;
252 size_t compressed_bufsize
;
253 unsigned char *uncompressed_buf
;
254 size_t uncompressed_bufsize
;
255 unsigned char *spare_buf
;
262 const size_t trials
= 16;
265 static const char * const names
[] = {
266 "Isaac.Newton-Opticks.txt",
267 "../libgo/go/testdata/Isaac.Newton-Opticks.txt",
272 uncompressed_buf
= NULL
;
273 compressed_buf
= NULL
;
275 for (i
= 0; i
< sizeof names
/ sizeof names
[0]; ++i
)
284 len
= strlen (SRCDIR
) + strlen (names
[i
]) + 2;
285 namebuf
= malloc (len
);
291 snprintf (namebuf
, len
, "%s/%s", SRCDIR
, names
[i
]);
292 e
= fopen (namebuf
, "r");
296 if (fstat (fileno (e
), &st
) < 0)
302 rbuf
= malloc (st
.st_size
);
308 got
= fread (rbuf
, 1, st
.st_size
, e
);
312 orig_buf
= (unsigned char *) rbuf
;
319 if (orig_buf
== NULL
)
321 /* We couldn't find an input file. */
322 printf ("UNSUPPORTED: lzma large\n");
326 stream
= initial_stream
;
327 r
= lzma_easy_encoder (&stream
, 6, LZMA_CHECK_CRC32
);
330 fprintf (stderr
, "lzma_easy_encoder failed: %d\n", r
);
334 compressed_bufsize
= orig_bufsize
+ 100;
335 compressed_buf
= malloc (compressed_bufsize
);
336 if (compressed_buf
== NULL
)
342 stream
.next_in
= orig_buf
;
343 stream
.avail_in
= orig_bufsize
;
344 stream
.next_out
= compressed_buf
;
345 stream
.avail_out
= compressed_bufsize
;
349 r
= lzma_code (&stream
, LZMA_FINISH
);
350 if (r
!= LZMA_OK
&& r
!= LZMA_STREAM_END
)
352 fprintf (stderr
, "lzma_code failed: %d\n", r
);
356 while (r
!= LZMA_STREAM_END
);
358 compressed_bufsize
= stream
.total_out
;
360 if (!backtrace_uncompress_lzma (state
, (unsigned char *) compressed_buf
,
362 error_callback_compress
, NULL
,
363 &uncompressed_buf
, &uncompressed_bufsize
))
365 fprintf (stderr
, "lzma large: backtrace_uncompress_lzma failed\n");
369 if (uncompressed_bufsize
!= orig_bufsize
)
372 "lzma large: got uncompressed length %zu, want %zu\n",
373 uncompressed_bufsize
, orig_bufsize
);
377 if (memcmp (uncompressed_buf
, orig_buf
, uncompressed_bufsize
) != 0)
379 fprintf (stderr
, "lzma large: uncompressed data mismatch\n");
383 printf ("PASS: lzma large\n");
385 spare_buf
= malloc (orig_bufsize
);
386 if (spare_buf
== NULL
)
392 for (i
= 0; i
< trials
; ++i
)
394 cid
= LIBLZMA_CLOCK_GETTIME_ARG
;
395 if (clock_gettime (cid
, &ts1
) < 0)
399 perror ("clock_gettime");
403 if (!backtrace_uncompress_lzma (state
,
404 (unsigned char *) compressed_buf
,
406 error_callback_compress
, NULL
,
408 &uncompressed_bufsize
))
412 "benchmark backtrace_uncompress_lzma failed\n"));
416 if (clock_gettime (cid
, &ts2
) < 0)
418 perror ("clock_gettime");
422 ctime
= (ts2
.tv_sec
- ts1
.tv_sec
) * 1000000000;
423 ctime
+= ts2
.tv_nsec
- ts1
.tv_nsec
;
426 stream
= initial_stream
;
428 r
= lzma_auto_decoder (&stream
, UINT64_MAX
, 0);
431 fprintf (stderr
, "lzma_stream_decoder failed: %d\n", r
);
435 stream
.next_in
= compressed_buf
;
436 stream
.avail_in
= compressed_bufsize
;
437 stream
.next_out
= spare_buf
;
438 stream
.avail_out
= orig_bufsize
;
440 if (clock_gettime (cid
, &ts1
) < 0)
442 perror("clock_gettime");
448 r
= lzma_code (&stream
, LZMA_FINISH
);
449 if (r
!= LZMA_OK
&& r
!= LZMA_STREAM_END
)
451 fprintf (stderr
, "lzma_code failed: %d\n", r
);
455 while (r
!= LZMA_STREAM_END
);
457 if (clock_gettime (cid
, &ts2
) < 0)
459 perror ("clock_gettime");
463 ztime
= (ts2
.tv_sec
- ts1
.tv_sec
) * 1000000000;
464 ztime
+= ts2
.tv_nsec
- ts1
.tv_nsec
;
468 /* Toss the highest and lowest times and average the rest. */
469 ctime
= average_time (ctimes
, trials
);
470 ztime
= average_time (ztimes
, trials
);
472 printf ("backtrace: %zu ns\n", ctime
);
473 printf ("liblzma : %zu ns\n", ztime
);
474 printf ("ratio : %g\n", (double) ztime
/ (double) ctime
);
479 printf ("FAIL: lzma large\n");
482 if (orig_buf
!= NULL
)
484 if (compressed_buf
!= NULL
)
485 free (compressed_buf
);
486 if (uncompressed_buf
!= NULL
)
487 free (uncompressed_buf
);
489 #else /* !HAVE_LIBLZMA */
491 printf ("UNSUPPORTED: lzma large\n");
493 #endif /* !HAVE_LIBLZMA */
497 main (int argc ATTRIBUTE_UNUSED
, char **argv
)
499 struct backtrace_state
*state
;
501 state
= backtrace_create_state (argv
[0], BACKTRACE_SUPPORTS_THREADS
,
502 error_callback_create
, NULL
);
504 test_samples (state
);
507 exit (failures
!= 0 ? EXIT_FAILURE
: EXIT_SUCCESS
);