Git fork
1/*
2Copyright 2020 Google LLC
3
4Use of this source code is governed by a BSD-style
5license that can be found in the LICENSE file or at
6https://developers.google.com/open-source/licenses/bsd
7*/
8
9#include "unit-test.h"
10#include "lib-reftable.h"
11#include "reftable/block.h"
12#include "reftable/blocksource.h"
13#include "reftable/constants.h"
14#include "reftable/reftable-error.h"
15#include "strbuf.h"
16
17void test_reftable_block__read_write(void)
18{
19 const int header_off = 21; /* random */
20 struct reftable_record recs[30];
21 const size_t N = ARRAY_SIZE(recs);
22 const size_t block_size = 1024;
23 struct reftable_block_source source = { 0 };
24 struct block_writer bw = {
25 .last_key = REFTABLE_BUF_INIT,
26 };
27 struct reftable_record rec = {
28 .type = REFTABLE_BLOCK_TYPE_REF,
29 };
30 size_t i = 0;
31 int ret;
32 struct reftable_block block = { 0 };
33 struct block_iter it = BLOCK_ITER_INIT;
34 struct reftable_buf want = REFTABLE_BUF_INIT;
35 struct reftable_buf block_data = REFTABLE_BUF_INIT;
36
37 REFTABLE_CALLOC_ARRAY(block_data.buf, block_size);
38 cl_assert(block_data.buf != NULL);
39 block_data.len = block_size;
40
41 ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_REF,
42 (uint8_t *) block_data.buf, block_size,
43 header_off, hash_size(REFTABLE_HASH_SHA1));
44 cl_assert(!ret);
45
46 rec.u.ref.refname = (char *) "";
47 rec.u.ref.value_type = REFTABLE_REF_DELETION;
48 ret = block_writer_add(&bw, &rec);
49 cl_assert_equal_i(ret, REFTABLE_API_ERROR);
50
51 for (i = 0; i < N; i++) {
52 rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i);
53 rec.u.ref.value_type = REFTABLE_REF_VAL1;
54 memset(rec.u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1);
55
56 recs[i] = rec;
57 ret = block_writer_add(&bw, &rec);
58 rec.u.ref.refname = NULL;
59 rec.u.ref.value_type = REFTABLE_REF_DELETION;
60 cl_assert_equal_i(ret, 0);
61 }
62
63 ret = block_writer_finish(&bw);
64 cl_assert(ret > 0);
65
66 block_writer_release(&bw);
67
68 block_source_from_buf(&source ,&block_data);
69 reftable_block_init(&block, &source, 0, header_off, block_size,
70 REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF);
71
72 block_iter_init(&it, &block);
73
74 for (i = 0; ; i++) {
75 ret = block_iter_next(&it, &rec);
76 cl_assert(ret >= 0);
77 if (ret > 0) {
78 cl_assert_equal_i(i, N);
79 break;
80 }
81 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
82 }
83
84 for (i = 0; i < N; i++) {
85 reftable_record_key(&recs[i], &want);
86
87 ret = block_iter_seek_key(&it, &want);
88 cl_assert_equal_i(ret, 0);
89
90 ret = block_iter_next(&it, &rec);
91 cl_assert_equal_i(ret, 0);
92
93 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
94
95 want.len--;
96 ret = block_iter_seek_key(&it, &want);
97 cl_assert_equal_i(ret, 0);
98
99 ret = block_iter_next(&it, &rec);
100 cl_assert_equal_i(ret, 0);
101 cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
102 }
103
104 reftable_block_release(&block);
105 block_iter_close(&it);
106 reftable_record_release(&rec);
107 reftable_buf_release(&want);
108 reftable_buf_release(&block_data);
109 for (i = 0; i < N; i++)
110 reftable_record_release(&recs[i]);
111}
112
113void test_reftable_block__log_read_write(void)
114{
115 const int header_off = 21;
116 struct reftable_record recs[30];
117 const size_t N = ARRAY_SIZE(recs);
118 const size_t block_size = 2048;
119 struct reftable_block_source source = { 0 };
120 struct block_writer bw = {
121 .last_key = REFTABLE_BUF_INIT,
122 };
123 struct reftable_record rec = {
124 .type = REFTABLE_BLOCK_TYPE_LOG,
125 };
126 size_t i = 0;
127 int ret;
128 struct reftable_block block = { 0 };
129 struct block_iter it = BLOCK_ITER_INIT;
130 struct reftable_buf want = REFTABLE_BUF_INIT;
131 struct reftable_buf block_data = REFTABLE_BUF_INIT;
132
133 REFTABLE_CALLOC_ARRAY(block_data.buf, block_size);
134 cl_assert(block_data.buf != NULL);
135 block_data.len = block_size;
136
137 ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_LOG, (uint8_t *) block_data.buf, block_size,
138 header_off, hash_size(REFTABLE_HASH_SHA1));
139 cl_assert(!ret);
140
141 for (i = 0; i < N; i++) {
142 rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i);
143 rec.u.log.update_index = i;
144 rec.u.log.value_type = REFTABLE_LOG_UPDATE;
145
146 recs[i] = rec;
147 ret = block_writer_add(&bw, &rec);
148 rec.u.log.refname = NULL;
149 rec.u.log.value_type = REFTABLE_LOG_DELETION;
150 cl_assert_equal_i(ret, 0);
151 }
152
153 ret = block_writer_finish(&bw);
154 cl_assert(ret > 0);
155
156 block_writer_release(&bw);
157
158 block_source_from_buf(&source, &block_data);
159 reftable_block_init(&block, &source, 0, header_off, block_size,
160 REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_LOG);
161
162 block_iter_init(&it, &block);
163
164 for (i = 0; ; i++) {
165 ret = block_iter_next(&it, &rec);
166 cl_assert(ret >= 0);
167 if (ret > 0) {
168 cl_assert_equal_i(i, N);
169 break;
170 }
171 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
172 }
173
174 for (i = 0; i < N; i++) {
175 reftable_buf_reset(&want);
176 cl_assert(reftable_buf_addstr(&want, recs[i].u.log.refname) == 0);
177
178 ret = block_iter_seek_key(&it, &want);
179 cl_assert_equal_i(ret, 0);
180
181 ret = block_iter_next(&it, &rec);
182 cl_assert_equal_i(ret, 0);
183
184 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
185
186 want.len--;
187 ret = block_iter_seek_key(&it, &want);
188 cl_assert_equal_i(ret, 0);
189
190 ret = block_iter_next(&it, &rec);
191 cl_assert_equal_i(ret, 0);
192 cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
193 }
194
195 reftable_block_release(&block);
196 block_iter_close(&it);
197 reftable_record_release(&rec);
198 reftable_buf_release(&want);
199 reftable_buf_release(&block_data);
200 for (i = 0; i < N; i++)
201 reftable_record_release(&recs[i]);
202}
203
204void test_reftable_block__obj_read_write(void)
205{
206 const int header_off = 21;
207 struct reftable_record recs[30];
208 const size_t N = ARRAY_SIZE(recs);
209 const size_t block_size = 1024;
210 struct reftable_block_source source = { 0 };
211 struct block_writer bw = {
212 .last_key = REFTABLE_BUF_INIT,
213 };
214 struct reftable_record rec = {
215 .type = REFTABLE_BLOCK_TYPE_OBJ,
216 };
217 size_t i = 0;
218 int ret;
219 struct reftable_block block = { 0 };
220 struct block_iter it = BLOCK_ITER_INIT;
221 struct reftable_buf want = REFTABLE_BUF_INIT;
222 struct reftable_buf block_data = REFTABLE_BUF_INIT;
223
224 REFTABLE_CALLOC_ARRAY(block_data.buf, block_size);
225 cl_assert(block_data.buf != NULL);
226 block_data.len = block_size;
227
228 ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_OBJ, (uint8_t *) block_data.buf, block_size,
229 header_off, hash_size(REFTABLE_HASH_SHA1));
230 cl_assert(!ret);
231
232 for (i = 0; i < N; i++) {
233 uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated;
234 DUP_ARRAY(allocated, bytes, ARRAY_SIZE(bytes));
235
236 rec.u.obj.hash_prefix = allocated;
237 rec.u.obj.hash_prefix_len = 5;
238
239 recs[i] = rec;
240 ret = block_writer_add(&bw, &rec);
241 rec.u.obj.hash_prefix = NULL;
242 rec.u.obj.hash_prefix_len = 0;
243 cl_assert_equal_i(ret, 0);
244 }
245
246 ret = block_writer_finish(&bw);
247 cl_assert(ret > 0);
248
249 block_writer_release(&bw);
250
251 block_source_from_buf(&source, &block_data);
252 reftable_block_init(&block, &source, 0, header_off, block_size,
253 REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_OBJ);
254
255 block_iter_init(&it, &block);
256
257 for (i = 0; ; i++) {
258 ret = block_iter_next(&it, &rec);
259 cl_assert(ret >= 0);
260 if (ret > 0) {
261 cl_assert_equal_i(i, N);
262 break;
263 }
264 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
265 }
266
267 for (i = 0; i < N; i++) {
268 reftable_record_key(&recs[i], &want);
269
270 ret = block_iter_seek_key(&it, &want);
271 cl_assert_equal_i(ret, 0);
272
273 ret = block_iter_next(&it, &rec);
274 cl_assert_equal_i(ret, 0);
275
276 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
277 }
278
279 reftable_block_release(&block);
280 block_iter_close(&it);
281 reftable_record_release(&rec);
282 reftable_buf_release(&want);
283 reftable_buf_release(&block_data);
284 for (i = 0; i < N; i++)
285 reftable_record_release(&recs[i]);
286}
287
288void test_reftable_block__ref_read_write(void)
289{
290 const int header_off = 21;
291 struct reftable_record recs[30];
292 const size_t N = ARRAY_SIZE(recs);
293 const size_t block_size = 1024;
294 struct reftable_block_source source = { 0 };
295 struct block_writer bw = {
296 .last_key = REFTABLE_BUF_INIT,
297 };
298 struct reftable_record rec = {
299 .type = REFTABLE_BLOCK_TYPE_INDEX,
300 .u.idx.last_key = REFTABLE_BUF_INIT,
301 };
302 size_t i = 0;
303 int ret;
304 struct reftable_block block = { 0 };
305 struct block_iter it = BLOCK_ITER_INIT;
306 struct reftable_buf want = REFTABLE_BUF_INIT;
307 struct reftable_buf block_data = REFTABLE_BUF_INIT;
308
309 REFTABLE_CALLOC_ARRAY(block_data.buf, block_size);
310 cl_assert(block_data.buf != NULL);
311 block_data.len = block_size;
312
313 ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_INDEX, (uint8_t *) block_data.buf, block_size,
314 header_off, hash_size(REFTABLE_HASH_SHA1));
315 cl_assert(!ret);
316
317 for (i = 0; i < N; i++) {
318 char buf[128];
319
320 snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i);
321
322 reftable_buf_init(&recs[i].u.idx.last_key);
323 recs[i].type = REFTABLE_BLOCK_TYPE_INDEX;
324 cl_assert(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf));
325 recs[i].u.idx.offset = i;
326
327 ret = block_writer_add(&bw, &recs[i]);
328 cl_assert_equal_i(ret, 0);
329 }
330
331 ret = block_writer_finish(&bw);
332 cl_assert(ret > 0);
333
334 block_writer_release(&bw);
335
336 block_source_from_buf(&source, &block_data);
337 reftable_block_init(&block, &source, 0, header_off, block_size,
338 REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_INDEX);
339
340 block_iter_init(&it, &block);
341
342 for (i = 0; ; i++) {
343 ret = block_iter_next(&it, &rec);
344 cl_assert(ret >= 0);
345 if (ret > 0) {
346 cl_assert_equal_i(i, N);
347 break;
348 }
349 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
350 }
351
352 for (i = 0; i < N; i++) {
353 reftable_record_key(&recs[i], &want);
354
355 ret = block_iter_seek_key(&it, &want);
356 cl_assert_equal_i(ret, 0);
357
358 ret = block_iter_next(&it, &rec);
359 cl_assert_equal_i(ret, 0);
360
361 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
362
363 want.len--;
364 ret = block_iter_seek_key(&it, &want);
365 cl_assert_equal_i(ret, 0);
366
367 ret = block_iter_next(&it, &rec);
368 cl_assert_equal_i(ret, 0);
369 cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
370 }
371
372 reftable_block_release(&block);
373 block_iter_close(&it);
374 reftable_record_release(&rec);
375 reftable_buf_release(&want);
376 reftable_buf_release(&block_data);
377 for (i = 0; i < N; i++)
378 reftable_record_release(&recs[i]);
379}
380
381void test_reftable_block__iterator(void)
382{
383 struct reftable_block_source source = { 0 };
384 struct block_writer writer = {
385 .last_key = REFTABLE_BUF_INIT,
386 };
387 struct reftable_record expected_refs[20];
388 struct reftable_ref_record ref = { 0 };
389 struct reftable_iterator it = { 0 };
390 struct reftable_block block = { 0 };
391 struct reftable_buf data;
392 int err;
393
394 data.len = 1024;
395 REFTABLE_CALLOC_ARRAY(data.buf, data.len);
396 cl_assert(data.buf != NULL);
397
398 err = block_writer_init(&writer, REFTABLE_BLOCK_TYPE_REF,
399 (uint8_t *) data.buf, data.len,
400 0, hash_size(REFTABLE_HASH_SHA1));
401 cl_assert(!err);
402
403 for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) {
404 expected_refs[i] = (struct reftable_record) {
405 .type = REFTABLE_BLOCK_TYPE_REF,
406 .u.ref = {
407 .value_type = REFTABLE_REF_VAL1,
408 .refname = xstrfmt("refs/heads/branch-%02"PRIuMAX, (uintmax_t)i),
409 },
410 };
411 memset(expected_refs[i].u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1);
412
413 err = block_writer_add(&writer, &expected_refs[i]);
414 cl_assert_equal_i(err, 0);
415 }
416
417 err = block_writer_finish(&writer);
418 cl_assert(err > 0);
419
420 block_source_from_buf(&source, &data);
421 reftable_block_init(&block, &source, 0, 0, data.len,
422 REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF);
423
424 err = reftable_block_init_iterator(&block, &it);
425 cl_assert_equal_i(err, 0);
426
427 for (size_t i = 0; ; i++) {
428 err = reftable_iterator_next_ref(&it, &ref);
429 if (err > 0) {
430 cl_assert_equal_i(i, ARRAY_SIZE(expected_refs));
431 break;
432 }
433 cl_assert_equal_i(err, 0);
434
435 cl_assert(reftable_ref_record_equal(&ref,
436 &expected_refs[i].u.ref, REFTABLE_HASH_SIZE_SHA1));
437 }
438
439 err = reftable_iterator_seek_ref(&it, "refs/heads/does-not-exist");
440 cl_assert_equal_i(err, 0);
441 err = reftable_iterator_next_ref(&it, &ref);
442 cl_assert_equal_i(err, 1);
443
444 err = reftable_iterator_seek_ref(&it, "refs/heads/branch-13");
445 cl_assert_equal_i(err, 0);
446 err = reftable_iterator_next_ref(&it, &ref);
447 cl_assert_equal_i(err, 0);
448 cl_assert(reftable_ref_record_equal(&ref,
449 &expected_refs[13].u.ref,REFTABLE_HASH_SIZE_SHA1));
450
451 for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++)
452 reftable_free(expected_refs[i].u.ref.refname);
453 reftable_ref_record_release(&ref);
454 reftable_iterator_destroy(&it);
455 reftable_block_release(&block);
456 block_writer_release(&writer);
457 reftable_buf_release(&data);
458}