test_bits.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /* test harness for bits.h
  2. *
  3. * This file is Copyright 2010 by the GPSD project
  4. * SPDX-License-Identifier: BSD-2-clause
  5. */
  6. #include "../include/gpsd_config.h" // must be before all includes
  7. #include <inttypes.h>
  8. #include <stdbool.h>
  9. #include <stdint.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "../include/bits.h"
  14. // test array of 640 bits
  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. static char *hexdump(const void *binbuf, size_t len)
  27. {
  28. static char hexbuf[BUFSIZ];
  29. size_t i, j = 0;
  30. const char *ibuf = (const char *)binbuf;
  31. const char *hexchar = "0123456789abcdef";
  32. for (i = 0; i < len; i++) {
  33. hexbuf[j++] = hexchar[(ibuf[i] & 0xf0) >> 4];
  34. hexbuf[j++] = hexchar[ibuf[i] & 0x0f];
  35. }
  36. hexbuf[j] = '\0';
  37. return hexbuf;
  38. }
  39. static void bedumpall(void)
  40. {
  41. (void)printf("getsb: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  42. " %016" PRIx64 "\n",
  43. (uint64_t) sb1, (uint64_t) sb2,
  44. (uint64_t) getsb(buf, 0), (uint64_t) getsb(buf, 8));
  45. (void)printf("getub: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  46. " %016" PRIx64 "\n",
  47. (uint64_t) ub1, (uint64_t) ub2,
  48. (uint64_t) getub(buf, 0), (uint64_t) getub(buf, 8));
  49. (void)printf("getbes16: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  50. " %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
  54. " %016" PRIx64 "\n",
  55. (uint64_t) uw1, (uint64_t) uw2,
  56. (uint64_t) getbeu16(buf, 0), (uint64_t) getbeu16(buf, 8));
  57. (void)printf("getbes32: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  58. " %016" PRIx64 "\n",
  59. (uint64_t) sl1, (uint64_t) sl2,
  60. (uint64_t) getbes32(buf, 0), (uint64_t) getbes32(buf, 8));
  61. (void)printf("getbeu32: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  62. " %016" PRIx64 "\n",
  63. (uint64_t) ul1, (uint64_t) ul2,
  64. (uint64_t) getbeu32(buf, 0), (uint64_t) getbeu32(buf, 8));
  65. (void)printf("getbes64: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  66. " %016" PRIx64 "\n",
  67. (uint64_t) sL1, (uint64_t) sL2,
  68. (uint64_t) getbes64(buf, 0), (uint64_t) getbes64(buf, 8));
  69. (void)printf("getbeu64: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  70. " %016" PRIx64 "\n",
  71. (uint64_t) uL1, (uint64_t) uL2,
  72. (uint64_t) getbeu64(buf, 0), (uint64_t) getbeu64(buf, 8));
  73. (void)printf("getbef32: %f %f\n", f1, getbef32((const char *)buf, 24));
  74. (void)printf("getbed64: %.16f %.16f\n", d1,
  75. getbed64((const char *)buf, 16));
  76. }
  77. static void ledumpall(void)
  78. {
  79. (void)printf("getsb: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  80. " %016" PRIx64 "\n",
  81. (uint64_t) sb1, (uint64_t) sb2,
  82. (uint64_t) getsb(buf, 0), (uint64_t) getsb(buf, 8));
  83. (void)printf("getub: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  84. " %016" PRIx64 "\n",
  85. (uint64_t) ub1, (uint64_t) ub2,
  86. (uint64_t) getub(buf, 0), (uint64_t) getub(buf, 8));
  87. (void)printf("getles16: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  88. " %016" PRIx64 "\n",
  89. (uint64_t) sw1, (uint64_t) sw2,
  90. (uint64_t) getles16(buf, 0), (uint64_t) getles16(buf, 8));
  91. (void)printf("getleu16: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  92. " %016" PRIx64 "\n",
  93. (uint64_t) uw1, (uint64_t) uw2,
  94. (uint64_t) getleu16(buf, 0), (uint64_t) getleu16(buf, 8));
  95. (void)printf("getles32: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  96. " %016" PRIx64 "\n",
  97. (uint64_t) sl1, (uint64_t) sl2,
  98. (uint64_t) getles32(buf, 0), (uint64_t) getles32(buf, 8));
  99. (void)printf("getleu32: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  100. " %016" PRIx64 "\n",
  101. (uint64_t) ul1, (uint64_t) ul2,
  102. (uint64_t) getleu32(buf, 0), (uint64_t) getleu32(buf, 8));
  103. (void)printf("getles64: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  104. " %016" PRIx64 "\n",
  105. (uint64_t) sL1, (uint64_t) sL2,
  106. (uint64_t) getles64(buf, 0), (uint64_t) getles64(buf, 8));
  107. (void)printf("getleu64: %016" PRIx64 " %016" PRIx64 " %016" PRIx64
  108. " %016" PRIx64 "\n",
  109. (uint64_t) uL1, (uint64_t) uL2,
  110. (uint64_t) getleu64(buf, 0), (uint64_t) getleu64(buf, 8));
  111. (void)printf("getlef32: %f %f\n", f1, getlef32((const char *)buf, 24));
  112. (void)printf("getled64: %.16f %.16f\n", d1,
  113. getled64((const char *)buf, 16));
  114. }
  115. struct unsigned_test
  116. {
  117. const unsigned char *buf;
  118. unsigned int start, width;
  119. uint64_t expected;
  120. bool le;
  121. char *description;
  122. };
  123. struct bitmask
  124. {
  125. int shift;
  126. unsigned long long mask;
  127. };
  128. static struct bitmask bitmask_tests[] = {
  129. {0, 0},
  130. {1, 1},
  131. {2, 3},
  132. {3, 7},
  133. {15, 0x07fff},
  134. {16, 0x0ffff},
  135. {31, 0x07fffffff},
  136. {32, 0x0ffffffffULL},
  137. {40, 0x0ffffffffffULL},
  138. {255, 0}, // 255 marks end
  139. };
  140. struct uint2int
  141. {
  142. unsigned long long uint;
  143. int bits;
  144. long long res;
  145. };
  146. static struct uint2int uint2_tests[] = {
  147. {0, 2, 0},
  148. {1, 2, 1},
  149. {2, 2, -2},
  150. {3, 2, -1},
  151. {0x1b, 5, -5},
  152. {5, 5, 5},
  153. {0x07f, 8, 127},
  154. {0x080, 8, -128},
  155. {0x0ff, 8, -1},
  156. {0x07fff, 16, 32767},
  157. {0x08000, 16, -32768},
  158. {0x0ffff, 16, -1},
  159. {0x07ffff, 20, 524287},
  160. {0x080000, 20, -524288},
  161. {0x0fffff, 20, -1},
  162. {0x07fffffff, 32, 2147483647},
  163. {0x080000000ULL, 32, -2147483648LL},
  164. {0x0ffffffffULL, 32, -1},
  165. {0x07ffffffffULL, 36, 34359738367LL},
  166. {0x0800000000ULL, 36, -34359738368LL},
  167. {0x0fffffffffULL, 36, -1},
  168. {0, 255, 0}, // 255 marks end
  169. };
  170. int main(int argc, char *argv[])
  171. {
  172. int failures = 0;
  173. bool quiet = (argc > 1) && (strcmp(argv[1], "--quiet") == 0);
  174. struct unsigned_test *up, unsigned_tests[] = {
  175. // tests using the big buffer
  176. {buf, 0, 1, 0, false, "first bit of first byte"},
  177. {buf, 0, 8, 0x01, false, "first 8 bits"},
  178. {buf, 32, 7, 0x02, false, "first seven bits of fifth byte (0x05)"},
  179. {buf, 56, 12, 0x8f, false, "12 bits crossing 7th to 8th bytes (0x08ff)"},
  180. {buf, 78, 4, 0xb, false, "4 bits crossing 8th to 9th byte (0xfefd)"},
  181. {buf, 1, 56, 0x020406080a0c0eULL, false, "56 bits, 1 bit in"},
  182. {buf, 7, 56, 0x81018202830384ULL, false, "56 bits, 7 bit in"},
  183. {buf, 9, 56, 0x0406080a0c0e11ULL, false, "56 bits, 9 bits in"},
  184. // width 56 max, check consistent fail on 64 bits
  185. {buf, 0, 64, 0, false, "64 bits, 0 bit in"},
  186. {buf, 1, 64, 0, false, "64 bits, 1 bit in"},
  187. {buf, 7, 33, 0x102030405, false, "33 bits, 7 bits in"},
  188. {buf, 0, 1, 0, true, "first bit of first byte"},
  189. {buf, 0, 8, 0x80, true, "first 8 bits"},
  190. {buf, 32, 7, 0x20, true, "first seven bits of fifth byte (0x05)"},
  191. {buf, 56, 12, 0xf10,true, "12 bits crossing 7th to 8th bytes (0x08ff)"},
  192. {buf, 78, 4, 0xd, true, "4 bits crossing 8th to 9th byte (0xfefd)"},
  193. // sporadic tests based on found bugs
  194. {(unsigned char *)"\x19\x23\f6",
  195. 7, 2, 2, false, "2 bits crossing 1st to 2nd byte (0x1923)"},
  196. };
  197. struct bitmask *bitm = bitmask_tests;
  198. struct uint2int *uint2 = uint2_tests;
  199. if (!quiet) {
  200. (void)printf("Testing bitfield extraction\n");
  201. }
  202. // test array of 640/232 bits
  203. memcpy(buf,
  204. "\x01\x02\x03\x04\x05\x06\x07\x08"
  205. "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8"
  206. "\x40\x09\x21\xfb\x54\x44\x2d\x18"
  207. "\x40\x49\x0f\xdb", 29);
  208. sb1 = getsb(buf, 0);
  209. sb2 = getsb(buf, 8);
  210. ub1 = getub(buf, 0);
  211. ub2 = getub(buf, 8);
  212. if (!quiet) {
  213. const unsigned char *sp;
  214. (void)fputs("Test data:", stdout);
  215. for (sp = buf; sp < buf + 28; sp++) {
  216. (void)printf(" %02x", *sp);
  217. }
  218. (void)putc('\n', stdout);
  219. // big-endian test
  220. printf("Big-endian:\n");
  221. sw1 = getbes16(buf, 0);
  222. sw2 = getbes16(buf, 8);
  223. uw1 = getbeu16(buf, 0);
  224. uw2 = getbeu16(buf, 8);
  225. sl1 = getbes32(buf, 0);
  226. sl2 = getbes32(buf, 8);
  227. ul1 = getbeu32(buf, 0);
  228. ul2 = getbeu32(buf, 8);
  229. sL1 = getbes64(buf, 0);
  230. sL2 = getbes64(buf, 8);
  231. uL1 = getbeu64(buf, 0);
  232. uL2 = getbeu64(buf, 8);
  233. f1 = getbef32((const char *)buf, 24);
  234. d1 = getbed64((const char *)buf, 16);
  235. bedumpall();
  236. // little-endian test
  237. printf("Little-endian:\n");
  238. sw1 = getles16(buf, 0);
  239. sw2 = getles16(buf, 8);
  240. uw1 = getleu16(buf, 0);
  241. uw2 = getleu16(buf, 8);
  242. sl1 = getles32(buf, 0);
  243. sl2 = getles32(buf, 8);
  244. ul1 = getleu32(buf, 0);
  245. ul2 = getleu32(buf, 8);
  246. sL1 = getles64(buf, 0);
  247. sL2 = getles64(buf, 8);
  248. uL1 = getleu64(buf, 0);
  249. uL2 = getleu64(buf, 8);
  250. f1 = getlef32((const char *)buf, 24);
  251. d1 = getled64((const char *)buf, 16);
  252. ledumpall();
  253. }
  254. if (1 != sb1) {
  255. printf("getsb(buf, 0) FAILED\n");
  256. }
  257. if (-1 != sb2) {
  258. printf("getsb(buf, 8) FAILED\n");
  259. }
  260. if (1 != ub1) {
  261. printf("getub(buf, 0) FAILED\n");
  262. }
  263. if (0xff != ub2) {
  264. printf("getub(buf, 8) FAILED\n");
  265. }
  266. for (up = unsigned_tests;
  267. up <
  268. unsigned_tests + sizeof(unsigned_tests) / sizeof(unsigned_tests[0]);
  269. up++) {
  270. uint64_t res = ubits(buf, up->start, up->width, up->le);
  271. bool success = (res == up->expected);
  272. if (!success) {
  273. failures++;
  274. }
  275. if (!success ||
  276. !quiet) {
  277. (void)printf("ubits(%s, %d, %d, %s) %s should be %" PRIx64
  278. ", is %" PRIx64 ": %s\n",
  279. hexdump(buf, strlen((char *)buf)),
  280. up->start, up->width, up->le ? "true" : "false",
  281. up->description, up->expected, res,
  282. success ? "succeeded" : "FAILED");
  283. }
  284. }
  285. shiftleft(buf, 28, 30);
  286. if (!quiet) {
  287. printf("Left-shifted 30 bits: %s\n", hexdump(buf, 28));
  288. }
  289. /*
  290. * After the 24-bit shift, the bit array loses its first three bytes:
  291. * 0x0405060708 = 00000100 00000101 00000110 00000111 00001000
  292. * By inspection, the results of the 6-bit shift are
  293. * 00000001 01000001 10000001 11000010 00
  294. */
  295. #define LASSERT(n, v) if (buf[n] != v) \
  296. printf("Expected buf[%d] to be %02x, was %02x\n", n, v, buf[n])
  297. LASSERT(0, 0x01);
  298. LASSERT(1, 0x41);
  299. LASSERT(2, 0x81);
  300. LASSERT(3, 0xc1);
  301. #undef LASSERT
  302. if (!quiet) {
  303. (void)printf("Testing BITMASK(N)\n");
  304. }
  305. while (129 > bitm->shift) {
  306. if (bitm->mask != BITMASK(bitm->shift)) {
  307. failures++;
  308. printf("BITMASK(0) FAILED, %llu s/b %llu\n",
  309. bitm->mask, BITMASK(bitm->shift));
  310. }
  311. bitm++;
  312. }
  313. if (!quiet) {
  314. (void)printf("Testing UINT2INT(U, N)\n");
  315. }
  316. while (129 > uint2->bits) {
  317. if (uint2->res != UINT2INT(uint2->uint, uint2->bits)) {
  318. failures++;
  319. printf("UINT2INT(x%llx, %d) FAILED, %lld s/b %lld\n",
  320. uint2->uint, uint2->bits,
  321. uint2->res, UINT2INT(uint2->uint, uint2->bits));
  322. }
  323. uint2++;
  324. }
  325. exit(failures ? EXIT_FAILURE : EXIT_SUCCESS);
  326. }
  327. // vim: set expandtab shiftwidth=4