test_bits.c 9.5 KB

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