summaryrefslogtreecommitdiffstats
path: root/testutil/test-search.c
blob: 93d6d039884c8b6fefdff2e9b352b2a02e651a26 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* See LICENSE file for copyright and license details. */
#include "../libsyscalls.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if defined(__clang__)
# pragma clang diagnostic ignored "-Wunsafe-buffer-usage" /* clang is just being silly */
#endif


static struct libsyscalls_named_number not_found;
static size_t not_found_count = 0;
static char **argv;

static void
check(unsigned long long int key, const struct libsyscalls_named_number *base, size_t n, int is_signed)
{
	static int first = 1;

	const struct libsyscalls_named_number *found;
	found = libsyscalls_find_named_number(key, is_signed, base, n);
	if (found) {
		if (first)
			not_found.number.u = key + 1;
		if (found->number.u != key) {
			fprintf(stderr, "test-search %s %s %s: found incorrect element: %llu instead of %llu\n",
			        argv[1], argv[4], argv[5], found->number.u, key);
			exit(1);
		}
	} else {
		if (first) {
			fprintf(stderr, "test-search %s %s %s: did not find first element\n", argv[1], argv[4], argv[5]);
			exit(1);
		}
		not_found.number.u = key;
		not_found_count += 1;
	}

	first = 0;
}


int
main(int argc, char **argv_)
{
	int os, arch, search_singals, is_signed;
	enum libsyscalls_error err;
	const struct libsyscalls_named_number *base, *min, *max;
	unsigned long long int ukey;
	signed long long int skey;
	size_t n, expected_not_found_count;

	argv = argv_;

	if (argc != 6) {
	usage:
		fprintf(stderr, "usage error\n");
		return 1;
	}

	if (!strcmp(argv[1], "signals"))
		search_singals = 1;
	else if (!strcmp(argv[1], "errors"))
		search_singals = 0;
	else
		goto usage;
	os = atoi(argv[2]);
	arch = atoi(argv[3]);

	if (search_singals)
		err = libsyscalls_get_signals((enum libsyscalls_os)os, (enum libsyscalls_arch)arch, &base, &n, &is_signed);
	else
		err = libsyscalls_get_syscall_errors((enum libsyscalls_os)os, (enum libsyscalls_arch)arch, &base, &n, &is_signed);
	if (err) {
		fprintf(stderr, "test-search %s %s %s: ", argv[1], argv[4], argv[5]);
		libsyscalls_perror(NULL, err);
		return 1;
	}

	if (!n)
		return 0;

	min = &base[0];
	max = &base[n - 1];

	if (is_signed) {
		skey = min->number.s;
		do {
			check(*(unsigned long long int *)&skey, base, n, is_signed);
		} while (skey++ != max->number.s);
		expected_not_found_count = (size_t)((unsigned long long int)max->number.s -
		                                    (unsigned long long int)min->number.s -
		                                    (unsigned long long int)n + 1);
	} else {
		ukey = min->number.u;
		do {
			check(ukey, base, n, is_signed);
		} while (ukey++ != max->number.u);
		expected_not_found_count = (size_t)(max->number.u - min->number.u - (unsigned long long int)n + 1);
	}

	if (not_found.number.u == max->number.u) {
		fprintf(stderr, "test-search %s %s %s: did not find last element\n", argv[1], argv[4], argv[5]);
		return 1;
	}
	if (not_found_count != expected_not_found_count) {
		fprintf(stderr, "test-search %s %s %s: did not find all elements\n", argv[1], argv[4], argv[5]);
		return 1;
	}

	return 0;
}