The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
ztest.c
Go to the documentation of this file.
1/* ztest.c -- Test for libbacktrace inflate code.
2 Copyright (C) 2017-2024 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Google.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
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
15 distribution.
16
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.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE. */
32
33#include "config.h"
34
35#include <errno.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <time.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42
43#ifdef HAVE_ZLIB
44#include <zlib.h>
45#endif
46
47#include "backtrace.h"
48#include "backtrace-supported.h"
49
50#include "internal.h"
51#include "testlib.h"
52
53#ifndef HAVE_CLOCK_GETTIME
54
55typedef int xclockid_t;
56
57static int
58xclock_gettime (xclockid_t id ATTRIBUTE_UNUSED,
59 struct timespec *ts ATTRIBUTE_UNUSED)
60{
61 errno = EINVAL;
62 return -1;
63}
64
65#define clockid_t xclockid_t
66#define clock_gettime xclock_gettime
67#undef CLOCK_REALTIME
68#define CLOCK_REALTIME 0
69
70#endif /* !defined(HAVE_CLOCK_GETTIME) */
71
72#ifdef CLOCK_PROCESS_CPUTIME_ID
73#define ZLIB_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID
74#else
75#define ZLIB_CLOCK_GETTIME_ARG CLOCK_REALTIME
76#endif
77
78/* Some tests for the local zlib inflation code. */
79
81{
82 const char *name;
83 const char *uncompressed;
85 const char *compressed;
87};
88
89/* Error callback. */
90
91static void
93 int errnum)
94{
95 fprintf (stderr, "%s", msg);
96 if (errnum > 0)
97 fprintf (stderr, ": %s", strerror (errnum));
98 fprintf (stderr, "\n");
99 exit (EXIT_FAILURE);
100}
101
102static const struct zlib_test tests[] =
103{
104 {
105 "empty",
106 "",
107 0,
108 "\x78\x9c\x03\x00\x00\x00\x00\x01",
109 8,
110 },
111 {
112 "hello",
113 "hello, world\n",
114 0,
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"),
117 25,
118 },
119 {
120 "goodbye",
121 "goodbye, world",
122 0,
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"),
126 22,
127 },
128 {
129 "ranges",
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"),
172 672,
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"),
183 152,
184 }
185};
186
187/* Test the hand coded samples. */
188
189static void
191{
192 size_t i;
193
194 for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)
195 {
196 char *p;
197 size_t v;
198 size_t j;
199 unsigned char *uncompressed;
200 size_t uncompressed_len;
201
202 p = malloc (12 + tests[i].compressed_len);
203 memcpy (p, "ZLIB", 4);
204 v = tests[i].uncompressed_len;
205 if (v == 0)
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);
210 uncompressed = NULL;
212 if (!backtrace_uncompress_zdebug (state, (unsigned char *) p,
213 tests[i].compressed_len + 12,
216 {
217 fprintf (stderr, "test %s: uncompress failed\n", tests[i].name);
218 ++failures;
219 }
220 else
221 {
222 if (uncompressed_len != v)
223 {
224 fprintf (stderr,
225 "test %s: got uncompressed length %zu, want %zu\n",
227 ++failures;
228 }
229 else if (memcmp (tests[i].uncompressed, uncompressed, v) != 0)
230 {
231 size_t j;
232
233 fprintf (stderr, "test %s: uncompressed data mismatch\n",
234 tests[i].name);
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,
239 ++failures;
240 }
241 else
242 printf ("PASS: inflate %s\n", tests[i].name);
243
246 }
247 }
248}
249
250#ifdef HAVE_ZLIB
251
252/* Given a set of TRIALS timings, discard the lowest and highest
253 values and return the mean average of the rest. */
254
255static size_t
256average_time (const size_t *times, size_t trials)
257{
258 size_t imax;
259 size_t max;
260 size_t imin;
261 size_t min;
262 size_t i;
263 size_t sum;
264
265 imin = 0;
266 imax = 0;
267 min = times[0];
268 max = times[0];
269 for (i = 1; i < trials; ++i)
270 {
271 if (times[i] < min)
272 {
273 imin = i;
274 min = times[i];
275 }
276 if (times[i] > max)
277 {
278 imax = i;
279 max = times[i];
280 }
281 }
282
283 sum = 0;
284 for (i = 0; i < trials; ++i)
285 {
286 if (i != imax && i != imin)
287 sum += times[i];
288 }
289 return sum / (trials - 2);
290}
291
292#endif
293
294/* Test a larger text, if available. */
295
296static void
298{
299#ifdef HAVE_ZLIB
300 unsigned char *orig_buf;
301 size_t orig_bufsize;
302 size_t i;
303 char *compressed_buf;
304 size_t compressed_bufsize;
305 unsigned long compress_sizearg;
306 unsigned char *uncompressed_buf;
307 size_t uncompressed_bufsize;
308 int r;
309 clockid_t cid;
310 struct timespec ts1;
311 struct timespec ts2;
312 size_t ctime;
313 size_t ztime;
314 const size_t trials = 16;
315 size_t ctimes[16];
316 size_t ztimes[16];
317 static const char * const names[] = {
318 "Isaac.Newton-Opticks.txt",
319 "../libgo/go/testdata/Isaac.Newton-Opticks.txt",
320 };
321
322 orig_buf = NULL;
323 orig_bufsize = 0;
324 uncompressed_buf = NULL;
325 compressed_buf = NULL;
326
327 for (i = 0; i < sizeof names / sizeof names[0]; ++i)
328 {
329 size_t len;
330 char *namebuf;
331 FILE *e;
332 struct stat st;
333 char *rbuf;
334 size_t got;
335
336 len = strlen (SRCDIR) + strlen (names[i]) + 2;
337 namebuf = malloc (len);
338 if (namebuf == NULL)
339 {
340 perror ("malloc");
341 goto fail;
342 }
343 snprintf (namebuf, len, "%s/%s", SRCDIR, names[i]);
344 e = fopen (namebuf, "r");
345 free (namebuf);
346 if (e == NULL)
347 continue;
348 if (fstat (fileno (e), &st) < 0)
349 {
350 perror ("fstat");
351 fclose (e);
352 continue;
353 }
354 rbuf = malloc (st.st_size);
355 if (rbuf == NULL)
356 {
357 perror ("malloc");
358 goto fail;
359 }
360 got = fread (rbuf, 1, st.st_size, e);
361 fclose (e);
362 if (got > 0)
363 {
364 orig_buf = (unsigned char *) rbuf;
365 orig_bufsize = got;
366 break;
367 }
368 free (rbuf);
369 }
370
371 if (orig_buf == NULL)
372 {
373 /* We couldn't find an input file. */
374 printf ("UNSUPPORTED: inflate large\n");
375 return;
376 }
377
378 compressed_bufsize = compressBound (orig_bufsize) + 12;
379 compressed_buf = malloc (compressed_bufsize);
380 if (compressed_buf == NULL)
381 {
382 perror ("malloc");
383 goto fail;
384 }
385
386 compress_sizearg = compressed_bufsize - 12;
387 r = compress ((unsigned char *) compressed_buf + 12, &compress_sizearg,
388 orig_buf, orig_bufsize);
389 if (r != Z_OK)
390 {
391 fprintf (stderr, "zlib compress failed: %d\n", r);
392 goto fail;
393 }
394
395 compressed_bufsize = compress_sizearg + 12;
396
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;
401
402 uncompressed_buf = malloc (orig_bufsize);
403 if (uncompressed_buf == NULL)
404 {
405 perror ("malloc");
406 goto fail;
407 }
408 uncompressed_bufsize = orig_bufsize;
409
410 if (!backtrace_uncompress_zdebug (state, (unsigned char *) compressed_buf,
411 compressed_bufsize,
413 &uncompressed_buf, &uncompressed_bufsize))
414 {
415 fprintf (stderr, "inflate large: backtrace_uncompress_zdebug failed\n");
416 goto fail;
417 }
418
419 if (uncompressed_bufsize != orig_bufsize)
420 {
421 fprintf (stderr,
422 "inflate large: got uncompressed length %zu, want %zu\n",
423 uncompressed_bufsize, orig_bufsize);
424 goto fail;
425 }
426
427 if (memcmp (uncompressed_buf, orig_buf, uncompressed_bufsize) != 0)
428 {
429 fprintf (stderr, "inflate large: uncompressed data mismatch\n");
430 goto fail;
431 }
432
433 printf ("PASS: inflate large\n");
434
435 for (i = 0; i < trials; ++i)
436 {
437 unsigned long uncompress_sizearg;
438
440 if (clock_gettime (cid, &ts1) < 0)
441 {
442 if (errno == EINVAL)
443 return;
444 perror ("clock_gettime");
445 return;
446 }
447
449 (unsigned char *) compressed_buf,
450 compressed_bufsize,
452 &uncompressed_buf,
453 &uncompressed_bufsize))
454 {
455 fprintf (stderr,
456 ("inflate large: "
457 "benchmark backtrace_uncompress_zdebug failed\n"));
458 return;
459 }
460
461 if (clock_gettime (cid, &ts2) < 0)
462 {
463 perror ("clock_gettime");
464 return;
465 }
466
467 ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
468 ctime += ts2.tv_nsec - ts1.tv_nsec;
469 ctimes[i] = ctime;
470
471 if (clock_gettime (cid, &ts1) < 0)
472 {
473 perror("clock_gettime");
474 return;
475 }
476
477 uncompress_sizearg = uncompressed_bufsize;
478 r = uncompress ((unsigned char *) uncompressed_buf, &uncompress_sizearg,
479 (unsigned char *) compressed_buf + 12,
480 compressed_bufsize - 12);
481
482 if (clock_gettime (cid, &ts2) < 0)
483 {
484 perror ("clock_gettime");
485 return;
486 }
487
488 if (r != Z_OK)
489 {
490 fprintf (stderr,
491 "inflate large: benchmark zlib uncompress failed: %d\n",
492 r);
493 return;
494 }
495
496 ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
497 ztime += ts2.tv_nsec - ts1.tv_nsec;
498 ztimes[i] = ztime;
499 }
500
501 /* Toss the highest and lowest times and average the rest. */
502 ctime = average_time (ctimes, trials);
503 ztime = average_time (ztimes, trials);
504
505 printf ("backtrace: %zu ns\n", ctime);
506 printf ("zlib : %zu ns\n", ztime);
507 printf ("ratio : %g\n", (double) ztime / (double) ctime);
508
509 return;
510
511 fail:
512 printf ("FAIL: inflate large\n");
513 ++failures;
514
515 if (orig_buf != NULL)
516 free (orig_buf);
517 if (compressed_buf != NULL)
518 free (compressed_buf);
519 if (uncompressed_buf != NULL)
520 free (uncompressed_buf);
521
522#else /* !HAVE_ZLIB */
523
524 printf ("UNSUPPORTED: inflate large\n");
525
526#endif /* !HAVE_ZLIB */
527}
528
529int
530main (int argc ATTRIBUTE_UNUSED, char **argv)
531{
532 struct backtrace_state *state;
533
536
539
540 exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);
541}
log_entry msg
Definition acutest.h:794
void backtrace_free(struct backtrace_state *state ATTRIBUTE_UNUSED, void *p, size_t size ATTRIBUTE_UNUSED, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
Definition alloc.c:69
#define BACKTRACE_SUPPORTS_THREADS
struct backtrace_state * backtrace_create_state(const char *filename, int threaded, backtrace_error_callback error_callback, void *data)
Definition state.c:46
static size_t min(size_t x, size_t y)
Definition dbuff.c:66
int backtrace_uncompress_zdebug(struct backtrace_state *state, const unsigned char *compressed, size_t compressed_size, backtrace_error_callback error_callback, void *data, unsigned char **uncompressed, size_t *uncompressed_size)
Definition elf.c:5146
#define ATTRIBUTE_UNUSED
Definition filenames.h:42
free(array)
#define malloc
static char const * name
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
void * state
Definition testlib.c:46
int failures
Definition testlib.c:50
void error_callback_create(void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
Definition testlib.c:226
static const char * names[8]
Definition time.c:607
Simple time functions.
Functions to help with cleanup.
const char * compressed
Definition ztest.c:85
static void test_large(struct backtrace_state *state ATTRIBUTE_UNUSED)
Definition ztest.c:297
const char * uncompressed
Definition ztest.c:83
static const struct zlib_test tests[]
Definition ztest.c:102
const char * name
Definition ztest.c:82
int main(int argc ATTRIBUTE_UNUSED, char **argv)
Definition ztest.c:530
size_t compressed_len
Definition ztest.c:86
static void test_samples(struct backtrace_state *state)
Definition ztest.c:190
#define ZLIB_CLOCK_GETTIME_ARG
Definition ztest.c:75
size_t uncompressed_len
Definition ztest.c:84
static void error_callback_compress(void *vdata ATTRIBUTE_UNUSED, const char *msg, int errnum)
Definition ztest.c:92
static size_t average_time(const size_t *times, size_t trials)
Definition ztest.c:256