Sync with Git 2.47.1
[git/gitster.git] / t / unit-tests / t-reftable-block.c
blobf9af907117bce3f1bc282547d67651e189ce6c97
1 /*
2 Copyright 2020 Google LLC
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file or at
6 https://developers.google.com/open-source/licenses/bsd
7 */
9 #include "test-lib.h"
10 #include "reftable/block.h"
11 #include "reftable/blocksource.h"
12 #include "reftable/constants.h"
13 #include "reftable/reftable-error.h"
15 static void t_ref_block_read_write(void)
17 const int header_off = 21; /* random */
18 struct reftable_record recs[30];
19 const size_t N = ARRAY_SIZE(recs);
20 const size_t block_size = 1024;
21 struct reftable_block block = { 0 };
22 struct block_writer bw = {
23 .last_key = REFTABLE_BUF_INIT,
25 struct reftable_record rec = {
26 .type = BLOCK_TYPE_REF,
28 size_t i = 0;
29 int ret;
30 struct block_reader br = { 0 };
31 struct block_iter it = BLOCK_ITER_INIT;
32 struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;
34 REFTABLE_CALLOC_ARRAY(block.data, block_size);
35 check(block.data != NULL);
36 block.len = block_size;
37 block_source_from_buf(&block.source ,&buf);
38 ret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size,
39 header_off, hash_size(GIT_SHA1_FORMAT_ID));
40 check(!ret);
42 rec.u.ref.refname = (char *) "";
43 rec.u.ref.value_type = REFTABLE_REF_DELETION;
44 ret = block_writer_add(&bw, &rec);
45 check_int(ret, ==, REFTABLE_API_ERROR);
47 for (i = 0; i < N; i++) {
48 rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i);
49 rec.u.ref.value_type = REFTABLE_REF_VAL1;
50 memset(rec.u.ref.value.val1, i, GIT_SHA1_RAWSZ);
52 recs[i] = rec;
53 ret = block_writer_add(&bw, &rec);
54 rec.u.ref.refname = NULL;
55 rec.u.ref.value_type = REFTABLE_REF_DELETION;
56 check_int(ret, ==, 0);
59 ret = block_writer_finish(&bw);
60 check_int(ret, >, 0);
62 block_writer_release(&bw);
64 block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ);
66 block_iter_seek_start(&it, &br);
68 for (i = 0; ; i++) {
69 ret = block_iter_next(&it, &rec);
70 check_int(ret, >=, 0);
71 if (ret > 0) {
72 check_int(i, ==, N);
73 break;
75 check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ));
78 for (i = 0; i < N; i++) {
79 block_iter_reset(&it);
80 reftable_record_key(&recs[i], &want);
82 ret = block_iter_seek_key(&it, &br, &want);
83 check_int(ret, ==, 0);
85 ret = block_iter_next(&it, &rec);
86 check_int(ret, ==, 0);
88 check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ));
90 want.len--;
91 ret = block_iter_seek_key(&it, &br, &want);
92 check_int(ret, ==, 0);
94 ret = block_iter_next(&it, &rec);
95 check_int(ret, ==, 0);
96 check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ));
99 block_reader_release(&br);
100 block_iter_close(&it);
101 reftable_record_release(&rec);
102 reftable_block_done(&br.block);
103 reftable_buf_release(&want);
104 reftable_buf_release(&buf);
105 for (i = 0; i < N; i++)
106 reftable_record_release(&recs[i]);
109 static void t_log_block_read_write(void)
111 const int header_off = 21;
112 struct reftable_record recs[30];
113 const size_t N = ARRAY_SIZE(recs);
114 const size_t block_size = 2048;
115 struct reftable_block block = { 0 };
116 struct block_writer bw = {
117 .last_key = REFTABLE_BUF_INIT,
119 struct reftable_record rec = {
120 .type = BLOCK_TYPE_LOG,
122 size_t i = 0;
123 int ret;
124 struct block_reader br = { 0 };
125 struct block_iter it = BLOCK_ITER_INIT;
126 struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;
128 REFTABLE_CALLOC_ARRAY(block.data, block_size);
129 check(block.data != NULL);
130 block.len = block_size;
131 block_source_from_buf(&block.source ,&buf);
132 ret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size,
133 header_off, hash_size(GIT_SHA1_FORMAT_ID));
134 check(!ret);
136 for (i = 0; i < N; i++) {
137 rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i);
138 rec.u.log.update_index = i;
139 rec.u.log.value_type = REFTABLE_LOG_UPDATE;
141 recs[i] = rec;
142 ret = block_writer_add(&bw, &rec);
143 rec.u.log.refname = NULL;
144 rec.u.log.value_type = REFTABLE_LOG_DELETION;
145 check_int(ret, ==, 0);
148 ret = block_writer_finish(&bw);
149 check_int(ret, >, 0);
151 block_writer_release(&bw);
153 block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ);
155 block_iter_seek_start(&it, &br);
157 for (i = 0; ; i++) {
158 ret = block_iter_next(&it, &rec);
159 check_int(ret, >=, 0);
160 if (ret > 0) {
161 check_int(i, ==, N);
162 break;
164 check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ));
167 for (i = 0; i < N; i++) {
168 block_iter_reset(&it);
169 reftable_buf_reset(&want);
170 check(!reftable_buf_addstr(&want, recs[i].u.log.refname));
172 ret = block_iter_seek_key(&it, &br, &want);
173 check_int(ret, ==, 0);
175 ret = block_iter_next(&it, &rec);
176 check_int(ret, ==, 0);
178 check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ));
180 want.len--;
181 ret = block_iter_seek_key(&it, &br, &want);
182 check_int(ret, ==, 0);
184 ret = block_iter_next(&it, &rec);
185 check_int(ret, ==, 0);
186 check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ));
189 block_reader_release(&br);
190 block_iter_close(&it);
191 reftable_record_release(&rec);
192 reftable_block_done(&br.block);
193 reftable_buf_release(&want);
194 reftable_buf_release(&buf);
195 for (i = 0; i < N; i++)
196 reftable_record_release(&recs[i]);
199 static void t_obj_block_read_write(void)
201 const int header_off = 21;
202 struct reftable_record recs[30];
203 const size_t N = ARRAY_SIZE(recs);
204 const size_t block_size = 1024;
205 struct reftable_block block = { 0 };
206 struct block_writer bw = {
207 .last_key = REFTABLE_BUF_INIT,
209 struct reftable_record rec = {
210 .type = BLOCK_TYPE_OBJ,
212 size_t i = 0;
213 int ret;
214 struct block_reader br = { 0 };
215 struct block_iter it = BLOCK_ITER_INIT;
216 struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;
218 REFTABLE_CALLOC_ARRAY(block.data, block_size);
219 check(block.data != NULL);
220 block.len = block_size;
221 block_source_from_buf(&block.source, &buf);
222 ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size,
223 header_off, hash_size(GIT_SHA1_FORMAT_ID));
224 check(!ret);
226 for (i = 0; i < N; i++) {
227 uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated;
228 DUP_ARRAY(allocated, bytes, ARRAY_SIZE(bytes));
230 rec.u.obj.hash_prefix = allocated;
231 rec.u.obj.hash_prefix_len = 5;
233 recs[i] = rec;
234 ret = block_writer_add(&bw, &rec);
235 rec.u.obj.hash_prefix = NULL;
236 rec.u.obj.hash_prefix_len = 0;
237 check_int(ret, ==, 0);
240 ret = block_writer_finish(&bw);
241 check_int(ret, >, 0);
243 block_writer_release(&bw);
245 block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ);
247 block_iter_seek_start(&it, &br);
249 for (i = 0; ; i++) {
250 ret = block_iter_next(&it, &rec);
251 check_int(ret, >=, 0);
252 if (ret > 0) {
253 check_int(i, ==, N);
254 break;
256 check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ));
259 for (i = 0; i < N; i++) {
260 block_iter_reset(&it);
261 reftable_record_key(&recs[i], &want);
263 ret = block_iter_seek_key(&it, &br, &want);
264 check_int(ret, ==, 0);
266 ret = block_iter_next(&it, &rec);
267 check_int(ret, ==, 0);
269 check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ));
272 block_reader_release(&br);
273 block_iter_close(&it);
274 reftable_record_release(&rec);
275 reftable_block_done(&br.block);
276 reftable_buf_release(&want);
277 reftable_buf_release(&buf);
278 for (i = 0; i < N; i++)
279 reftable_record_release(&recs[i]);
282 static void t_index_block_read_write(void)
284 const int header_off = 21;
285 struct reftable_record recs[30];
286 const size_t N = ARRAY_SIZE(recs);
287 const size_t block_size = 1024;
288 struct reftable_block block = { 0 };
289 struct block_writer bw = {
290 .last_key = REFTABLE_BUF_INIT,
292 struct reftable_record rec = {
293 .type = BLOCK_TYPE_INDEX,
294 .u.idx.last_key = REFTABLE_BUF_INIT,
296 size_t i = 0;
297 int ret;
298 struct block_reader br = { 0 };
299 struct block_iter it = BLOCK_ITER_INIT;
300 struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT;
302 REFTABLE_CALLOC_ARRAY(block.data, block_size);
303 check(block.data != NULL);
304 block.len = block_size;
305 block_source_from_buf(&block.source, &buf);
306 ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size,
307 header_off, hash_size(GIT_SHA1_FORMAT_ID));
308 check(!ret);
310 for (i = 0; i < N; i++) {
311 char buf[128];
313 snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i);
315 reftable_buf_init(&recs[i].u.idx.last_key);
316 recs[i].type = BLOCK_TYPE_INDEX;
317 check(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf));
318 recs[i].u.idx.offset = i;
320 ret = block_writer_add(&bw, &recs[i]);
321 check_int(ret, ==, 0);
324 ret = block_writer_finish(&bw);
325 check_int(ret, >, 0);
327 block_writer_release(&bw);
329 block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ);
331 block_iter_seek_start(&it, &br);
333 for (i = 0; ; i++) {
334 ret = block_iter_next(&it, &rec);
335 check_int(ret, >=, 0);
336 if (ret > 0) {
337 check_int(i, ==, N);
338 break;
340 check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ));
343 for (i = 0; i < N; i++) {
344 block_iter_reset(&it);
345 reftable_record_key(&recs[i], &want);
347 ret = block_iter_seek_key(&it, &br, &want);
348 check_int(ret, ==, 0);
350 ret = block_iter_next(&it, &rec);
351 check_int(ret, ==, 0);
353 check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ));
355 want.len--;
356 ret = block_iter_seek_key(&it, &br, &want);
357 check_int(ret, ==, 0);
359 ret = block_iter_next(&it, &rec);
360 check_int(ret, ==, 0);
361 check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ));
364 block_reader_release(&br);
365 block_iter_close(&it);
366 reftable_record_release(&rec);
367 reftable_block_done(&br.block);
368 reftable_buf_release(&want);
369 reftable_buf_release(&buf);
370 for (i = 0; i < N; i++)
371 reftable_record_release(&recs[i]);
374 int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
376 TEST(t_index_block_read_write(), "read-write operations on index blocks work");
377 TEST(t_log_block_read_write(), "read-write operations on log blocks work");
378 TEST(t_obj_block_read_write(), "read-write operations on obj blocks work");
379 TEST(t_ref_block_read_write(), "read-write operations on ref blocks work");
381 return test_done();