1 /* vim: set expandtab ts=4 sw=4: */
2 /*
3  * You may redistribute this program and/or modify it under the terms of
4  * the GNU General Public License as published by the Free Software Foundation,
5  * either version 3 of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
14  */
15 #include "memory/MallocAllocator.h"
16 #include "crypto/random/Random.h"
17 #include "util/VarInt.h"
18 #include "util/Assert.h"
19 #include "util/Bits.h"
20 
21 #include <stdio.h>
22 
23 #define BUF_SZ 1024
24 
fidelityTest()25 static void fidelityTest()
26 {
27     struct Allocator* alloc = MallocAllocator_new(1<<20);
28     struct Random* rand = Random_new(alloc, NULL, NULL);
29     uint64_t* buf = Allocator_malloc(alloc, BUF_SZ*8);
30     Random_bytes(rand, (uint8_t*) buf, BUF_SZ*8);
31 
32     // make a mix of different size numbers
33     for (int i = 0; i < BUF_SZ; i++) {
34         uint64_t x = buf[i];
35         switch (x & 3) {
36             case 3: break;
37             case 2: buf[i] = x >> 32; break;
38             case 1: buf[i] = x >> 48; break;
39             case 0: buf[i] = x >> 56; break;
40         }
41     }
42 
43     uint8_t* buf2 = Allocator_malloc(alloc, BUF_SZ*8);
44     struct VarInt_Iter iter;
45     VarInt_mk(&iter, buf2, BUF_SZ*8);
46     VarInt_toEnd(&iter);
47 
48     for (int i = 0; i < BUF_SZ; i++) { Assert_true(!VarInt_push(&iter, buf[i])); }
49     Assert_true(iter.ptr > buf2);
50 
51     for (int i = BUF_SZ - 1; i >= 0; i--) {
52         uint64_t x = ~0;
53         Assert_true(!VarInt_pop(&iter, &x));
54         Assert_true(buf[i] == x);
55     }
56 
57     Assert_true(iter.ptr == iter.end);
58 
59     Allocator_free(alloc);
60 }
61 
test(uint8_t * bytes,int len,uint64_t num,uint8_t * buf)62 static inline void test(uint8_t* bytes, int len, uint64_t num, uint8_t* buf)
63 {
64     struct VarInt_Iter iter = { .ptr = bytes, .end = &bytes[len], .start = bytes };
65     uint64_t out = ~0;
66     Assert_true(!VarInt_pop(&iter, &out));
67     Assert_true(out == num);
68     Assert_true(iter.ptr == iter.end);
69 
70     buf[0] = buf[len+1] = 0xee;
71     struct VarInt_Iter iter2 = { .ptr = &buf[len+1], .end = &buf[len+1], .start = &buf[1] };
72     if (len < 9) { Assert_true(VarInt_push(&iter2, 0xf000000000000000ull)); }
73     if (len < 5) { Assert_true(VarInt_push(&iter2, 0xf0000000)); }
74     if (len < 3) { Assert_true(VarInt_push(&iter2, 0xf000)); }
75     Assert_true(!VarInt_push(&iter2, num));
76     Assert_true(iter2.ptr == iter2.start);
77     Assert_true(buf[0] == 0xee);
78     Assert_true(buf[len+1] == 0xee);
79 }
80 #define TEST(bytes, num) do { \
81     uint8_t data[sizeof(bytes)+1] = {0}; \
82     test(bytes, sizeof(bytes)-1, num, data); \
83 } while (0)
84 // CHECKFILES_IGNORE expecting a ;
85 
simpleTest()86 static void simpleTest()
87 {
88     TEST("\x00", 0x00);
89     TEST("\xAC", 0xAC);
90     TEST("\xFD\xAB\xCD", 0xABCD);
91     TEST("\xFE\xAB\xCD\xEF\x01", 0xABCDEF01);
92     TEST("\xFF\xAB\xCD\xEF\x01\x23\x45\x67\x89", 0xABCDEF0123456789ull);
93 }
94 
main()95 int main()
96 {
97     simpleTest();
98     fidelityTest();
99     return 0;
100 }