1
2 #include <stdio.h>
3 #include "upb/pb/varint.int.h"
4 #include "tests/upb_test.h"
5
6 #include "upb/port_def.inc"
7
8 /* Test that we can round-trip from int->varint->int. */
test_varint_for_num(upb_decoderet (* decoder)(const char *),uint64_t num)9 static void test_varint_for_num(upb_decoderet (*decoder)(const char*),
10 uint64_t num) {
11 char buf[16];
12 size_t bytes;
13 upb_decoderet r;
14
15 memset(buf, 0xff, sizeof(buf));
16 bytes = upb_vencode64(num, buf);
17
18 if (num <= UINT32_MAX) {
19 uint64_t encoded = upb_vencode32((uint32_t)num);
20 char buf2[16];
21 upb_decoderet r;
22
23 memset(buf2, 0, sizeof(buf2));
24 memcpy(&buf2, &encoded, 8);
25 #ifdef UPB_BIG_ENDIAN
26 char swap[8];
27 swap[0] = buf2[7];
28 swap[1] = buf2[6];
29 swap[2] = buf2[5];
30 swap[3] = buf2[4];
31 swap[4] = buf2[3];
32 swap[5] = buf2[2];
33 swap[6] = buf2[1];
34 swap[7] = buf2[0];
35 buf2[0] = swap[0];
36 buf2[1] = swap[1];
37 buf2[2] = swap[2];
38 buf2[3] = swap[3];
39 buf2[4] = swap[4];
40 buf2[5] = swap[5];
41 buf2[6] = swap[6];
42 buf2[7] = swap[7];
43 #endif
44 r = decoder(buf2);
45 ASSERT(r.val == num);
46 ASSERT(r.p == buf2 + upb_value_size(encoded));
47 ASSERT(upb_zzenc_32(upb_zzdec_32((uint32_t)num)) == num);
48 }
49
50 r = decoder(buf);
51 ASSERT(r.val == num);
52 ASSERT(r.p == buf + bytes);
53 ASSERT(upb_zzenc_64(upb_zzdec_64(num)) == num);
54 }
55
56 /* Making up for the lack of 64-bit constants in C89. */
make_u64(uint32_t high,uint32_t low)57 static uint64_t make_u64(uint32_t high, uint32_t low) {
58 uint64_t ret = high;
59 ret = (ret << 32) | low;
60 return ret;
61 }
62
test_varint_decoder(upb_decoderet (* decoder)(const char *))63 static void test_varint_decoder(upb_decoderet (*decoder)(const char*)) {
64 #define TEST(bytes, expected_val) {\
65 size_t n = sizeof(bytes) - 1; /* for NULL */ \
66 char buf[UPB_PB_VARINT_MAX_LEN]; \
67 upb_decoderet r; \
68 memset(buf, 0xff, sizeof(buf)); \
69 memcpy(buf, bytes, n); \
70 r = decoder(buf); \
71 ASSERT(r.val == expected_val); \
72 ASSERT(r.p == buf + n); \
73 }
74
75 uint64_t num;
76
77 char twelvebyte[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1};
78 const char *twelvebyte_buf = twelvebyte;
79 /* A varint that terminates before hitting the end of the provided buffer,
80 * but in too many bytes (11 instead of 10). */
81 upb_decoderet r = decoder(twelvebyte_buf);
82 ASSERT(r.p == NULL);
83
84 TEST("\x00", 0UL);
85 TEST("\x01", 1UL);
86 TEST("\x81\x14", 0xa01UL);
87 TEST("\x81\x03", 0x181UL);
88 TEST("\x81\x83\x07", 0x1c181UL);
89 TEST("\x81\x83\x87\x0f", 0x1e1c181UL);
90 TEST("\x81\x83\x87\x8f\x1f", make_u64(0x1, 0xf1e1c181UL));
91 TEST("\x81\x83\x87\x8f\x9f\x3f", make_u64(0x1f9, 0xf1e1c181UL));
92 TEST("\x81\x83\x87\x8f\x9f\xbf\x7f", make_u64(0x1fdf9, 0xf1e1c181UL));
93 TEST("\x81\x83\x87\x8f\x9f\xbf\xff\x01", make_u64(0x3fdf9, 0xf1e1c181UL));
94 TEST("\x81\x83\x87\x8f\x9f\xbf\xff\x81\x03",
95 make_u64(0x303fdf9, 0xf1e1c181UL));
96 TEST("\x81\x83\x87\x8f\x9f\xbf\xff\x81\x83\x07",
97 make_u64(0x8303fdf9, 0xf1e1c181UL));
98 #undef TEST
99
100 for (num = 5; num * 1.5 < UINT64_MAX; num *= 1.5) {
101 test_varint_for_num(decoder, num);
102 }
103 test_varint_for_num(decoder, 0);
104 }
105
106
107 #define TEST_VARINT_DECODER(decoder) \
108 /* Create non-inline versions for convenient inspection of assembly language \
109 * output. */ \
110 upb_decoderet _upb_vdecode_ ## decoder(const char *p) { \
111 return upb_vdecode_ ## decoder(p); \
112 } \
113 void test_ ## decoder(void) { \
114 test_varint_decoder(&_upb_vdecode_ ## decoder); \
115 } \
116
117 TEST_VARINT_DECODER(check2_branch32)
TEST_VARINT_DECODER(check2_branch64)118 TEST_VARINT_DECODER(check2_branch64)
119
120 int run_tests(int argc, char *argv[]) {
121 UPB_UNUSED(argc);
122 UPB_UNUSED(argv);
123 test_check2_branch32();
124 test_check2_branch64();
125 return 0;
126 }
127