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
14 #include "blocksource.h"
15 #include "constants.h"
18 #include "test_framework.h"
19 #include "reftable-merged.h"
20 #include "reftable-tests.h"
21 #include "reftable-generic.h"
22 #include "reftable-writer.h"
24 static void write_test_table(struct strbuf
*buf
,
25 struct reftable_ref_record refs
[], int n
)
27 uint64_t min
= 0xffffffff;
32 struct reftable_write_options opts
= {
35 struct reftable_writer
*w
= NULL
;
36 for (i
= 0; i
< n
; i
++) {
37 uint64_t ui
= refs
[i
].update_index
;
46 w
= reftable_new_writer(&strbuf_add_void
, buf
, &opts
);
47 reftable_writer_set_limits(w
, min
, max
);
49 for (i
= 0; i
< n
; i
++) {
50 uint64_t before
= refs
[i
].update_index
;
51 int n
= reftable_writer_add_ref(w
, &refs
[i
]);
53 EXPECT(before
== refs
[i
].update_index
);
56 err
= reftable_writer_close(w
);
59 reftable_writer_free(w
);
62 static void write_test_log_table(struct strbuf
*buf
,
63 struct reftable_log_record logs
[], int n
,
64 uint64_t update_index
)
69 struct reftable_write_options opts
= {
71 .exact_log_message
= 1,
73 struct reftable_writer
*w
= NULL
;
74 w
= reftable_new_writer(&strbuf_add_void
, buf
, &opts
);
75 reftable_writer_set_limits(w
, update_index
, update_index
);
77 for (i
= 0; i
< n
; i
++) {
78 int err
= reftable_writer_add_log(w
, &logs
[i
]);
82 err
= reftable_writer_close(w
);
85 reftable_writer_free(w
);
88 static struct reftable_merged_table
*
89 merged_table_from_records(struct reftable_ref_record
**refs
,
90 struct reftable_block_source
**source
,
91 struct reftable_reader
***readers
, int *sizes
,
92 struct strbuf
*buf
, int n
)
95 struct reftable_merged_table
*mt
= NULL
;
97 struct reftable_table
*tabs
=
98 reftable_calloc(n
* sizeof(struct reftable_table
));
99 *readers
= reftable_calloc(n
* sizeof(struct reftable_reader
*));
100 *source
= reftable_calloc(n
* sizeof(**source
));
101 for (i
= 0; i
< n
; i
++) {
102 write_test_table(&buf
[i
], refs
[i
], sizes
[i
]);
103 block_source_from_strbuf(&(*source
)[i
], &buf
[i
]);
105 err
= reftable_new_reader(&(*readers
)[i
], &(*source
)[i
],
108 reftable_table_from_reader(&tabs
[i
], (*readers
)[i
]);
111 err
= reftable_new_merged_table(&mt
, tabs
, n
, GIT_SHA1_FORMAT_ID
);
116 static void readers_destroy(struct reftable_reader
**readers
, size_t n
)
120 reftable_reader_free(readers
[i
]);
121 reftable_free(readers
);
124 static void test_merged_between(void)
126 uint8_t hash1
[GIT_SHA1_RAWSZ
] = { 1, 2, 3, 0 };
128 struct reftable_ref_record r1
[] = { {
131 .value_type
= REFTABLE_REF_VAL1
,
134 struct reftable_ref_record r2
[] = { {
137 .value_type
= REFTABLE_REF_DELETION
,
140 struct reftable_ref_record
*refs
[] = { r1
, r2
};
141 int sizes
[] = { 1, 1 };
142 struct strbuf bufs
[2] = { STRBUF_INIT
, STRBUF_INIT
};
143 struct reftable_block_source
*bs
= NULL
;
144 struct reftable_reader
**readers
= NULL
;
145 struct reftable_merged_table
*mt
=
146 merged_table_from_records(refs
, &bs
, &readers
, sizes
, bufs
, 2);
148 struct reftable_ref_record ref
= { NULL
};
149 struct reftable_iterator it
= { NULL
};
150 int err
= reftable_merged_table_seek_ref(mt
, &it
, "a");
153 err
= reftable_iterator_next_ref(&it
, &ref
);
155 EXPECT(ref
.update_index
== 2);
156 reftable_ref_record_release(&ref
);
157 reftable_iterator_destroy(&it
);
158 readers_destroy(readers
, 2);
159 reftable_merged_table_free(mt
);
160 for (i
= 0; i
< ARRAY_SIZE(bufs
); i
++) {
161 strbuf_release(&bufs
[i
]);
166 static void test_merged(void)
168 uint8_t hash1
[GIT_SHA1_RAWSZ
] = { 1 };
169 uint8_t hash2
[GIT_SHA1_RAWSZ
] = { 2 };
170 struct reftable_ref_record r1
[] = {
174 .value_type
= REFTABLE_REF_VAL1
,
180 .value_type
= REFTABLE_REF_VAL1
,
186 .value_type
= REFTABLE_REF_VAL1
,
190 struct reftable_ref_record r2
[] = { {
193 .value_type
= REFTABLE_REF_DELETION
,
195 struct reftable_ref_record r3
[] = {
199 .value_type
= REFTABLE_REF_VAL1
,
205 .value_type
= REFTABLE_REF_VAL1
,
210 struct reftable_ref_record
*want
[] = {
217 struct reftable_ref_record
*refs
[] = { r1
, r2
, r3
};
218 int sizes
[3] = { 3, 1, 2 };
219 struct strbuf bufs
[3] = { STRBUF_INIT
, STRBUF_INIT
, STRBUF_INIT
};
220 struct reftable_block_source
*bs
= NULL
;
221 struct reftable_reader
**readers
= NULL
;
222 struct reftable_merged_table
*mt
=
223 merged_table_from_records(refs
, &bs
, &readers
, sizes
, bufs
, 3);
225 struct reftable_iterator it
= { NULL
};
226 int err
= reftable_merged_table_seek_ref(mt
, &it
, "a");
227 struct reftable_ref_record
*out
= NULL
;
233 EXPECT(reftable_merged_table_hash_id(mt
) == GIT_SHA1_FORMAT_ID
);
234 EXPECT(reftable_merged_table_min_update_index(mt
) == 1);
236 while (len
< 100) { /* cap loops/recursion. */
237 struct reftable_ref_record ref
= { NULL
};
238 int err
= reftable_iterator_next_ref(&it
, &ref
);
244 out
= reftable_realloc(
245 out
, sizeof(struct reftable_ref_record
) * cap
);
249 reftable_iterator_destroy(&it
);
251 EXPECT(ARRAY_SIZE(want
) == len
);
252 for (i
= 0; i
< len
; i
++) {
253 EXPECT(reftable_ref_record_equal(want
[i
], &out
[i
],
256 for (i
= 0; i
< len
; i
++) {
257 reftable_ref_record_release(&out
[i
]);
261 for (i
= 0; i
< 3; i
++) {
262 strbuf_release(&bufs
[i
]);
264 readers_destroy(readers
, 3);
265 reftable_merged_table_free(mt
);
269 static struct reftable_merged_table
*
270 merged_table_from_log_records(struct reftable_log_record
**logs
,
271 struct reftable_block_source
**source
,
272 struct reftable_reader
***readers
, int *sizes
,
273 struct strbuf
*buf
, int n
)
276 struct reftable_merged_table
*mt
= NULL
;
278 struct reftable_table
*tabs
=
279 reftable_calloc(n
* sizeof(struct reftable_table
));
280 *readers
= reftable_calloc(n
* sizeof(struct reftable_reader
*));
281 *source
= reftable_calloc(n
* sizeof(**source
));
282 for (i
= 0; i
< n
; i
++) {
283 write_test_log_table(&buf
[i
], logs
[i
], sizes
[i
], i
+ 1);
284 block_source_from_strbuf(&(*source
)[i
], &buf
[i
]);
286 err
= reftable_new_reader(&(*readers
)[i
], &(*source
)[i
],
289 reftable_table_from_reader(&tabs
[i
], (*readers
)[i
]);
292 err
= reftable_new_merged_table(&mt
, tabs
, n
, GIT_SHA1_FORMAT_ID
);
297 static void test_merged_logs(void)
299 uint8_t hash1
[GIT_SHA1_RAWSZ
] = { 1 };
300 uint8_t hash2
[GIT_SHA1_RAWSZ
] = { 2 };
301 uint8_t hash3
[GIT_SHA1_RAWSZ
] = { 3 };
302 struct reftable_log_record r1
[] = {
306 .value_type
= REFTABLE_LOG_UPDATE
,
311 .email
= "jane@invalid",
312 .message
= "message2",
318 .value_type
= REFTABLE_LOG_UPDATE
,
323 .email
= "jane@invalid",
324 .message
= "message1",
328 struct reftable_log_record r2
[] = {
332 .value_type
= REFTABLE_LOG_UPDATE
,
336 .email
= "jane@invalid",
337 .message
= "message3",
341 struct reftable_log_record r3
[] = {
345 .value_type
= REFTABLE_LOG_DELETION
,
348 struct reftable_log_record
*want
[] = {
354 struct reftable_log_record
*logs
[] = { r1
, r2
, r3
};
355 int sizes
[3] = { 2, 1, 1 };
356 struct strbuf bufs
[3] = { STRBUF_INIT
, STRBUF_INIT
, STRBUF_INIT
};
357 struct reftable_block_source
*bs
= NULL
;
358 struct reftable_reader
**readers
= NULL
;
359 struct reftable_merged_table
*mt
= merged_table_from_log_records(
360 logs
, &bs
, &readers
, sizes
, bufs
, 3);
362 struct reftable_iterator it
= { NULL
};
363 int err
= reftable_merged_table_seek_log(mt
, &it
, "a");
364 struct reftable_log_record
*out
= NULL
;
370 EXPECT(reftable_merged_table_hash_id(mt
) == GIT_SHA1_FORMAT_ID
);
371 EXPECT(reftable_merged_table_min_update_index(mt
) == 1);
373 while (len
< 100) { /* cap loops/recursion. */
374 struct reftable_log_record log
= { NULL
};
375 int err
= reftable_iterator_next_log(&it
, &log
);
381 out
= reftable_realloc(
382 out
, sizeof(struct reftable_log_record
) * cap
);
386 reftable_iterator_destroy(&it
);
388 EXPECT(ARRAY_SIZE(want
) == len
);
389 for (i
= 0; i
< len
; i
++) {
390 EXPECT(reftable_log_record_equal(want
[i
], &out
[i
],
394 err
= reftable_merged_table_seek_log_at(mt
, &it
, "a", 2);
396 reftable_log_record_release(&out
[0]);
397 err
= reftable_iterator_next_log(&it
, &out
[0]);
399 EXPECT(reftable_log_record_equal(&out
[0], &r3
[0], GIT_SHA1_RAWSZ
));
400 reftable_iterator_destroy(&it
);
402 for (i
= 0; i
< len
; i
++) {
403 reftable_log_record_release(&out
[i
]);
407 for (i
= 0; i
< 3; i
++) {
408 strbuf_release(&bufs
[i
]);
410 readers_destroy(readers
, 3);
411 reftable_merged_table_free(mt
);
415 static void test_default_write_opts(void)
417 struct reftable_write_options opts
= { 0 };
418 struct strbuf buf
= STRBUF_INIT
;
419 struct reftable_writer
*w
=
420 reftable_new_writer(&strbuf_add_void
, &buf
, &opts
);
422 struct reftable_ref_record rec
= {
427 struct reftable_block_source source
= { NULL
};
428 struct reftable_table
*tab
= reftable_calloc(sizeof(*tab
) * 1);
430 struct reftable_reader
*rd
= NULL
;
431 struct reftable_merged_table
*merged
= NULL
;
433 reftable_writer_set_limits(w
, 1, 1);
435 err
= reftable_writer_add_ref(w
, &rec
);
438 err
= reftable_writer_close(w
);
440 reftable_writer_free(w
);
442 block_source_from_strbuf(&source
, &buf
);
444 err
= reftable_new_reader(&rd
, &source
, "filename");
447 hash_id
= reftable_reader_hash_id(rd
);
448 EXPECT(hash_id
== GIT_SHA1_FORMAT_ID
);
450 reftable_table_from_reader(&tab
[0], rd
);
451 err
= reftable_new_merged_table(&merged
, tab
, 1, GIT_SHA1_FORMAT_ID
);
454 reftable_reader_free(rd
);
455 reftable_merged_table_free(merged
);
456 strbuf_release(&buf
);
459 /* XXX test refs_for(oid) */
461 int merged_test_main(int argc
, const char *argv
[])
463 RUN_TEST(test_merged_logs
);
464 RUN_TEST(test_merged_between
);
465 RUN_TEST(test_merged
);
466 RUN_TEST(test_default_write_opts
);