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
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
,
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
));
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
);
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
);
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
);
69 ret
= block_iter_next(&it
, &rec
);
70 check_int(ret
, >=, 0);
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
));
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
,
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
));
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
;
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
);
158 ret
= block_iter_next(&it
, &rec
);
159 check_int(ret
, >=, 0);
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
));
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
,
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
));
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;
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
);
250 ret
= block_iter_next(&it
, &rec
);
251 check_int(ret
, >=, 0);
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
,
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
));
310 for (i
= 0; i
< N
; i
++) {
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
);
334 ret
= block_iter_next(&it
, &rec
);
335 check_int(ret
, >=, 0);
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
));
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");