1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3 #ident "$Id$"
4 /*======
5 This file is part of TokuDB
6 
7 
8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9 
10     TokuDBis is free software: you can redistribute it and/or modify
11     it under the terms of the GNU General Public License, version 2,
12     as published by the Free Software Foundation.
13 
14     TokuDB is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18 
19     You should have received a copy of the GNU General Public License
20     along with TokuDB.  If not, see <http://www.gnu.org/licenses/>.
21 
22 ======= */
23 
24 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <stdint.h>
31 #include <tokudb_buffer.h>
32 
test_null()33 static void test_null() {
34     tokudb::buffer b;
35     assert(b.data() == nullptr);
36     assert(b.size() == 0);
37     assert(b.limit() == 0);
38     b.append(NULL, 0);
39     assert(b.data() == nullptr);
40     assert(b.size() == 0);
41     assert(b.limit() == 0);
42 }
43 
append_az(tokudb::buffer & b)44 static void append_az(tokudb::buffer &b) {
45     for (char c = 'a'; c <= 'z'; c++) {
46         b.append(&c, sizeof c);
47     }
48 }
49 
assert_az(tokudb::buffer & b)50 static void assert_az(tokudb::buffer &b) {
51     unsigned char *bp = NULL;
52     for (size_t i = 0; i < b.size(); i++) {
53         bp = (unsigned char *) b.data() + i;
54         assert(*bp == 'a'+i);
55     }
56     assert(*bp == 'z');
57 }
58 
assert_AZ(tokudb::buffer & b)59 static void assert_AZ(tokudb::buffer &b) {
60     unsigned char *bp = NULL;
61     for (size_t i = 0; i < b.size(); i++) {
62         bp = (unsigned char *) b.data() + i;
63         assert(*bp == 'A'+i);
64     }
65     assert(*bp == 'Z');
66 }
67 
test_append()68 static void test_append() {
69     tokudb::buffer a;
70 
71     a.append(NULL, 0);
72     append_az(a);
73     a.append(NULL, 0);
74     assert(a.size() == 'z'-'a'+1);
75     assert(a.size() <= a.limit());
76     assert_az(a);
77 
78     tokudb::buffer b(a.data(), 0, a.size());
79     for (size_t i = 0; i < b.limit(); i++) {
80         assert(i <= a.size());
81         char *ap = (char *) a.data() + i;
82         assert(i <= b.limit());
83         char *bp = (char *) b.data() + i;
84         assert(*ap == *bp);
85     }
86 }
87 
test_consume()88 static void test_consume() {
89     tokudb::buffer a;
90     append_az(a);
91     tokudb::buffer b(a.data(), 0, a.size());
92     for (size_t i = 0; i < b.limit(); i++) {
93         unsigned char c;
94         b.consume(&c, 1);
95         assert(c == 'a'+i);
96     }
97     assert(b.size() == b.limit());
98 }
99 
test_consume_ptr()100 static void test_consume_ptr() {
101     tokudb::buffer a;
102     append_az(a);
103     tokudb::buffer b(a.data(), 0, a.size());
104     for (size_t i = 0; i < b.limit(); i++) {
105         void *p = b.consume_ptr(1);
106         unsigned char c = *(unsigned char *)p;
107         assert(c == 'a'+i);
108     }
109     assert(b.size() == b.limit());
110     assert(b.consume_ptr(1) == NULL);
111 }
112 
test_replace()113 static void test_replace() {
114     tokudb::buffer a;
115     append_az(a);
116     assert_az(a);
117     for (size_t i = 0; i < a.size(); i++) {
118         unsigned char newc[1] = { (unsigned char)('A' + i) };
119         a.replace(i, 1, newc, 1);
120     }
121     assert_AZ(a);
122 }
123 
test_replace_grow()124 static void test_replace_grow() {
125     tokudb::buffer a;
126     append_az(a);
127     assert_az(a);
128 
129     // grow field
130     size_t orig_s = a.size();
131     for (size_t i = 0; i < orig_s; i++) {
132         unsigned char newc[2] = { (unsigned char)('a'+i), (unsigned char)('a'+i) };
133         size_t old_s = a.size();
134         a.replace(2*i, 1, newc, 2);
135         assert(a.size() == old_s+1);
136     }
137     for (size_t i = 0; i < a.size()/2; i++) {
138         unsigned char *cp = (unsigned char *) a.data() + 2*i;
139         assert(cp[0] == 'a'+i);
140         assert(cp[1] == 'a'+i);
141     }
142 }
143 
test_replace_shrink()144 static void test_replace_shrink() {
145     tokudb::buffer a;
146     for (char c = 'a'; c <= 'z'; c++) {
147         a.append(&c, sizeof c);
148         a.append(&c, sizeof c);
149     }
150 
151     // shrink field
152     for (size_t i = 0; i < a.size(); i++) {
153         unsigned char newc[1] = { (unsigned char)('a'+i) };
154         size_t s = a.size();
155         a.replace(i, 2, newc, 1);
156         assert(a.size() == s-1);
157     }
158     assert_az(a);
159 }
160 
test_replace_null()161 static void test_replace_null() {
162     tokudb::buffer a;
163     append_az(a);
164     assert_az(a);
165 
166     // insert between all
167     size_t n = a.size();
168     for (size_t i = 0; i < n; i++) {
169         unsigned char newc[1] = { (unsigned char)('a'+i) };
170         a.replace(2*i, 0, newc, 1);
171     }
172 
173     a.replace(a.size(), 0, (void *)"!", 1);
174     a.append((void *)"?", 1);
175 }
176 
177 namespace tokudb {
178     template size_t vlq_encode_ui(uint8_t, void *, size_t);
179     template size_t vlq_decode_ui(uint8_t *, void *, size_t);
180     template size_t vlq_encode_ui(uint32_t, void *, size_t);
181     template size_t vlq_decode_ui(uint32_t *, void *, size_t);
182 };
183 
test_ui8()184 static void test_ui8() {
185     tokudb::buffer a;
186     for (uint8_t n = 0; ; n++) {
187         assert(a.append_ui<uint8_t>(n) != 0);
188         if (n == 255)
189             break;
190     }
191     tokudb::buffer b(a.data(), 0, a.size());
192     for (uint8_t n = 0; ; n++) {
193         uint8_t v;
194         if (b.consume_ui<uint8_t>(&v) == 0)
195             break;
196         assert(v == n);
197         if (n == 255)
198             break;
199     }
200     assert(b.size() == b.limit());
201 }
202 
test_ui32()203 static void test_ui32() {
204     tokudb::buffer a;
205     for (uint32_t n = 0; ; n++) {
206         assert(a.append_ui<uint32_t>(n) != 0);
207         if (n == 1<<22)
208             break;
209     }
210     tokudb::buffer b(a.data(), 0, a.size());
211     for (uint32_t n = 0; ; n++) {
212         uint32_t v;
213         if (b.consume_ui<uint32_t>(&v) == 0)
214             break;
215         assert(v == n);
216         if (n == 1<<22)
217             break;
218     }
219     assert(b.size() == b.limit());
220 }
221 
main()222 int main() {
223     test_null();
224     test_append();
225     test_consume();
226     test_consume_ptr();
227     test_replace();
228     test_replace_grow();
229     test_replace_shrink();
230     test_replace_null();
231     test_ui8();
232     test_ui32();
233     return 0;
234 }
235