1 /* test harness for bits.h
2 *
3 * This file is Copyright (c) 2010 by the GPSD project
4 * SPDX-License-Identifier: BSD-2-clause
5 */
6
7 #include <inttypes.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdint.h>
12 #include <stdbool.h>
13 #include "../bits.h"
14
15 static unsigned char buf[80];
16 static signed char sb1, sb2;
17 static unsigned char ub1, ub2;
18 static short sw1, sw2;
19 static unsigned short uw1, uw2;
20 static int sl1, sl2;
21 static unsigned int ul1, ul2;
22 static int64_t sL1, sL2;
23 static uint64_t uL1, uL2;
24 static float f1;
25 static double d1;
26
hexdump(const void * binbuf,size_t len)27 static char *hexdump(const void *binbuf, size_t len)
28 {
29 static char hexbuf[BUFSIZ];
30 size_t i, j = 0;
31 const char *ibuf = (const char *)binbuf;
32 const char *hexchar = "0123456789abcdef";
33
34 for (i = 0; i < len; i++) {
35 hexbuf[j++] = hexchar[(ibuf[i] & 0xf0) >> 4];
36 hexbuf[j++] = hexchar[ibuf[i] & 0x0f];
37 }
38 hexbuf[j] = '\0';
39 return hexbuf;
40 }
41
bedumpall(void)42 static void bedumpall(void)
43 {
44 (void)printf("getsb: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
45 (uint64_t) sb1, (uint64_t) sb2,
46 (uint64_t) getsb(buf, 0), (uint64_t) getsb(buf, 8));
47 (void)printf("getub: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
48 (uint64_t) ub1, (uint64_t) ub2,
49 (uint64_t) getub(buf, 0), (uint64_t) getub(buf, 8));
50 (void)printf("getbes16: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
51 (uint64_t) sw1, (uint64_t) sw2,
52 (uint64_t) getbes16(buf, 0), (uint64_t) getbes16(buf, 8));
53 (void)printf("getbeu16: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
54 (uint64_t) uw1, (uint64_t) uw2,
55 (uint64_t) getbeu16(buf, 0), (uint64_t) getbeu16(buf, 8));
56 (void)printf("getbes32: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
57 (uint64_t) sl1, (uint64_t) sl2,
58 (uint64_t) getbes32(buf, 0), (uint64_t) getbes32(buf, 8));
59 (void)printf("getbeu32: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
60 (uint64_t) ul1, (uint64_t) ul2,
61 (uint64_t) getbeu32(buf, 0), (uint64_t) getbeu32(buf, 8));
62 (void)printf("getbes64: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
63 (uint64_t) sL1, (uint64_t) sL2,
64 (uint64_t) getbes64(buf, 0), (uint64_t) getbes64(buf, 8));
65 (void)printf("getbeu64: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
66 (uint64_t) uL1, (uint64_t) uL2,
67 (uint64_t) getbeu64(buf, 0), (uint64_t) getbeu64(buf, 8));
68 (void)printf("getbef32: %f %f\n", f1, getbef32((const char *)buf, 24));
69 (void)printf("getbed64: %.16f %.16f\n", d1, getbed64((const char *)buf, 16));
70 }
71
ledumpall(void)72 static void ledumpall(void)
73 {
74 (void)printf("getsb: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
75 (uint64_t) sb1, (uint64_t) sb2,
76 (uint64_t) getsb(buf, 0), (uint64_t) getsb(buf, 8));
77 (void)printf("getub: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
78 (uint64_t) ub1, (uint64_t) ub2,
79 (uint64_t) getub(buf, 0), (uint64_t) getub(buf, 8));
80 (void)printf("getles16: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
81 (uint64_t) sw1, (uint64_t) sw2,
82 (uint64_t) getles16(buf, 0), (uint64_t) getles16(buf, 8));
83 (void)printf("getleu16: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
84 (uint64_t) uw1, (uint64_t) uw2,
85 (uint64_t) getleu16(buf, 0), (uint64_t) getleu16(buf, 8));
86 (void)printf("getles32: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
87 (uint64_t) sl1, (uint64_t) sl2,
88 (uint64_t) getles32(buf, 0), (uint64_t) getles32(buf, 8));
89 (void)printf("getleu32: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
90 (uint64_t) ul1, (uint64_t) ul2,
91 (uint64_t) getleu32(buf, 0), (uint64_t) getleu32(buf, 8));
92 (void)printf("getles64: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
93 (uint64_t) sL1, (uint64_t) sL2,
94 (uint64_t) getles64(buf, 0), (uint64_t) getles64(buf, 8));
95 (void)printf("getleu64: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
96 (uint64_t) uL1, (uint64_t) uL2,
97 (uint64_t) getleu64(buf, 0), (uint64_t) getleu64(buf, 8));
98 (void)printf("getlef32: %f %f\n", f1, getlef32((const char *)buf, 24));
99 (void)printf("getled64: %.16f %.16f\n", d1, getled64((const char *)buf, 16));
100 }
101
102 struct unsigned_test
103 {
104 unsigned char *buf;
105 unsigned int start, width;
106 uint64_t expected;
107 bool le;
108 char *description;
109 };
110
main(int argc,char * argv[])111 int main(int argc, char *argv[])
112 {
113 bool failures = false;
114 bool quiet = (argc > 1) && (strcmp(argv[1], "--quiet") == 0);
115
116 struct unsigned_test *up, unsigned_tests[] = {
117 /* tests using the big buffer */
118 {buf, 0, 1, 0, false, "first bit of first byte"},
119 {buf, 0, 8, 0x01, false, "first 8 bits"},
120 {buf, 32, 7, 0x02, false, "first seven bits of fifth byte (0x05)"},
121 {buf, 56, 12, 0x8f, false, "12 bits crossing 7th to 8th bytes (0x08ff)"},
122 {buf, 78, 4, 0xb, false, "4 bits crossing 8th to 9th byte (0xfefd)"},
123 {buf, 0, 1, 0, true, "first bit of first byte"},
124 {buf, 0, 8, 0x80, true, "first 8 bits"},
125 {buf, 32, 7, 0x20, true, "first seven bits of fifth byte (0x05)"},
126 {buf, 56, 12, 0xf10,true, "12 bits crossing 7th to 8th bytes (0x08ff)"},
127 {buf, 78, 4, 0xd, true, "4 bits crossing 8th to 9th byte (0xfefd)"},
128 /* sporadic tests based on found bugs */
129 {(unsigned char *)"\x19\x23\f6",
130 7, 2, 2, false, "2 bits crossing 1st to 2nd byte (0x1923)"},
131 };
132
133 memcpy(buf, "\x01\x02\x03\x04\x05\x06\x07\x08", 8);
134 memcpy(buf + 8, "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8", 8);
135 memcpy(buf + 16, "\x40\x09\x21\xfb\x54\x44\x2d\x18", 8);
136 memcpy(buf + 24, "\x40\x49\x0f\xdb", 4);
137
138 if (!quiet)
139 (void)printf("Testing bitfield extraction\n");
140
141 sb1 = getsb(buf, 0);
142 sb2 = getsb(buf, 8);
143 ub1 = getub(buf, 0);
144 ub2 = getub(buf, 8);
145
146 if (!quiet) {
147 unsigned char *sp;
148
149 (void)fputs("Test data:", stdout);
150 for (sp = buf; sp < buf + 28; sp++)
151 (void)printf(" %02x", *sp);
152 (void)putc('\n', stdout);
153
154 /* big-endian test */
155 printf("Big-endian:\n");
156 sw1 = getbes16(buf, 0);
157 sw2 = getbes16(buf, 8);
158 uw1 = getbeu16(buf, 0);
159 uw2 = getbeu16(buf, 8);
160 sl1 = getbes32(buf, 0);
161 sl2 = getbes32(buf, 8);
162 ul1 = getbeu32(buf, 0);
163 ul2 = getbeu32(buf, 8);
164 sL1 = getbes64(buf, 0);
165 sL2 = getbes64(buf, 8);
166 uL1 = getbeu64(buf, 0);
167 uL2 = getbeu64(buf, 8);
168 f1 = getbef32((const char *)buf, 24);
169 d1 = getbed64((const char *)buf, 16);
170 bedumpall();
171
172 /* little-endian test */
173 printf("Little-endian:\n");
174 sw1 = getles16(buf, 0);
175 sw2 = getles16(buf, 8);
176 uw1 = getleu16(buf, 0);
177 uw2 = getleu16(buf, 8);
178 sl1 = getles32(buf, 0);
179 sl2 = getles32(buf, 8);
180 ul1 = getleu32(buf, 0);
181 ul2 = getleu32(buf, 8);
182 sL1 = getles64(buf, 0);
183 sL2 = getles64(buf, 8);
184 uL1 = getleu64(buf, 0);
185 uL2 = getleu64(buf, 8);
186 f1 = getlef32((const char *)buf, 24);
187 d1 = getled64((const char *)buf, 16);
188 ledumpall();
189 }
190
191 if (sb1 != 1) printf("getsb(buf, 0) FAILED\n");
192 if (sb2 != -1) printf("getsb(buf, 8) FAILED\n");
193 if (ub1 != 1) printf("getub(buf, 0) FAILED\n");
194 if (ub2 != 0xff) printf("getub(buf, 8) FAILED\n");
195
196 for (up = unsigned_tests;
197 up <
198 unsigned_tests + sizeof(unsigned_tests) / sizeof(unsigned_tests[0]);
199 up++) {
200 uint64_t res = ubits((unsigned char *)buf, up->start, up->width, up->le);
201 bool success = (res == up->expected);
202 if (!success)
203 failures = true;
204 if (!success || !quiet)
205 (void)printf("ubits(%s, %d, %d, %s) %s should be %" PRIx64 ", is %" PRIx64 ": %s\n",
206 hexdump(buf, strlen((char *)buf)),
207 up->start, up->width, up->le ? "true" : "false",
208 up->description, up->expected, res,
209 success ? "succeeded" : "FAILED");
210 }
211
212
213 shiftleft(buf, 28, 30);
214 if (!quiet)
215 printf("Left-shifted 30 bits: %s\n", hexdump(buf, 28));
216 /*
217 * After the 24-bit shift, the bit array loses its first three bytes:
218 * 0x0405060708 = 00000100 00000101 00000110 00000111 00001000
219 * By inspection, the results of the 6-bit shift are
220 * 00000001 01000001 10000001 11000010 00
221 */
222 #define LASSERT(n, v) if (buf[n] != v) printf("Expected buf[%d] to be %02x, was %02x\n", n, v, buf[n])
223 LASSERT(0, 0x01);
224 LASSERT(1, 0x41);
225 LASSERT(2, 0x81);
226 LASSERT(3, 0xc1);
227 #undef LASSERT
228
229
230 exit(failures ? EXIT_FAILURE : EXIT_SUCCESS);
231
232 }
233
234