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"
17 #include "test_framework.h"
18 #include "reftable-merged.h"
19 #include "reftable-tests.h"
20 #include "reftable-generic.h"
21 #include "reftable-writer.h"
23 static void write_test_table(struct strbuf
*buf
,
24 struct reftable_ref_record refs
[], int n
)
26 uint64_t min
= 0xffffffff;
31 struct reftable_write_options opts
= {
34 struct reftable_writer
*w
= NULL
;
35 for (i
= 0; i
< n
; i
++) {
36 uint64_t ui
= refs
[i
].update_index
;
45 w
= reftable_new_writer(&strbuf_add_void
, buf
, &opts
);
46 reftable_writer_set_limits(w
, min
, max
);
48 for (i
= 0; i
< n
; i
++) {
49 uint64_t before
= refs
[i
].update_index
;
50 int n
= reftable_writer_add_ref(w
, &refs
[i
]);
52 EXPECT(before
== refs
[i
].update_index
);
55 err
= reftable_writer_close(w
);
58 reftable_writer_free(w
);
61 static void write_test_log_table(struct strbuf
*buf
,
62 struct reftable_log_record logs
[], int n
,
63 uint64_t update_index
)
68 struct reftable_write_options opts
= {
70 .exact_log_message
= 1,
72 struct reftable_writer
*w
= NULL
;
73 w
= reftable_new_writer(&strbuf_add_void
, buf
, &opts
);
74 reftable_writer_set_limits(w
, update_index
, update_index
);
76 for (i
= 0; i
< n
; i
++) {
77 int err
= reftable_writer_add_log(w
, &logs
[i
]);
81 err
= reftable_writer_close(w
);
84 reftable_writer_free(w
);
87 static struct reftable_merged_table
*
88 merged_table_from_records(struct reftable_ref_record
**refs
,
89 struct reftable_block_source
**source
,
90 struct reftable_reader
***readers
, int *sizes
,
91 struct strbuf
*buf
, int n
)
94 struct reftable_merged_table
*mt
= NULL
;
96 struct reftable_table
*tabs
=
97 reftable_calloc(n
* sizeof(struct reftable_table
));
98 *readers
= reftable_calloc(n
* sizeof(struct reftable_reader
*));
99 *source
= reftable_calloc(n
* sizeof(**source
));
100 for (i
= 0; i
< n
; i
++) {
101 write_test_table(&buf
[i
], refs
[i
], sizes
[i
]);
102 block_source_from_strbuf(&(*source
)[i
], &buf
[i
]);
104 err
= reftable_new_reader(&(*readers
)[i
], &(*source
)[i
],
107 reftable_table_from_reader(&tabs
[i
], (*readers
)[i
]);
110 err
= reftable_new_merged_table(&mt
, tabs
, n
, GIT_SHA1_FORMAT_ID
);
115 static void readers_destroy(struct reftable_reader
**readers
, size_t n
)
119 reftable_reader_free(readers
[i
]);
120 reftable_free(readers
);
123 static void test_merged_between(void)
125 struct reftable_ref_record r1
[] = { {
128 .value_type
= REFTABLE_REF_VAL1
,
129 .value
.val1
= { 1, 2, 3, 0 },
131 struct reftable_ref_record r2
[] = { {
134 .value_type
= REFTABLE_REF_DELETION
,
137 struct reftable_ref_record
*refs
[] = { r1
, r2
};
138 int sizes
[] = { 1, 1 };
139 struct strbuf bufs
[2] = { STRBUF_INIT
, STRBUF_INIT
};
140 struct reftable_block_source
*bs
= NULL
;
141 struct reftable_reader
**readers
= NULL
;
142 struct reftable_merged_table
*mt
=
143 merged_table_from_records(refs
, &bs
, &readers
, sizes
, bufs
, 2);
145 struct reftable_ref_record ref
= { NULL
};
146 struct reftable_iterator it
= { NULL
};
147 int err
= reftable_merged_table_seek_ref(mt
, &it
, "a");
150 err
= reftable_iterator_next_ref(&it
, &ref
);
152 EXPECT(ref
.update_index
== 2);
153 reftable_ref_record_release(&ref
);
154 reftable_iterator_destroy(&it
);
155 readers_destroy(readers
, 2);
156 reftable_merged_table_free(mt
);
157 for (i
= 0; i
< ARRAY_SIZE(bufs
); i
++) {
158 strbuf_release(&bufs
[i
]);
163 static void test_merged(void)
165 struct reftable_ref_record r1
[] = {
169 .value_type
= REFTABLE_REF_VAL1
,
175 .value_type
= REFTABLE_REF_VAL1
,
181 .value_type
= REFTABLE_REF_VAL1
,
185 struct reftable_ref_record r2
[] = { {
188 .value_type
= REFTABLE_REF_DELETION
,
190 struct reftable_ref_record r3
[] = {
194 .value_type
= REFTABLE_REF_VAL1
,
200 .value_type
= REFTABLE_REF_VAL1
,
205 struct reftable_ref_record
*want
[] = {
212 struct reftable_ref_record
*refs
[] = { r1
, r2
, r3
};
213 int sizes
[3] = { 3, 1, 2 };
214 struct strbuf bufs
[3] = { STRBUF_INIT
, STRBUF_INIT
, STRBUF_INIT
};
215 struct reftable_block_source
*bs
= NULL
;
216 struct reftable_reader
**readers
= NULL
;
217 struct reftable_merged_table
*mt
=
218 merged_table_from_records(refs
, &bs
, &readers
, sizes
, bufs
, 3);
220 struct reftable_iterator it
= { NULL
};
221 int err
= reftable_merged_table_seek_ref(mt
, &it
, "a");
222 struct reftable_ref_record
*out
= NULL
;
228 EXPECT(reftable_merged_table_hash_id(mt
) == GIT_SHA1_FORMAT_ID
);
229 EXPECT(reftable_merged_table_min_update_index(mt
) == 1);
231 while (len
< 100) { /* cap loops/recursion. */
232 struct reftable_ref_record ref
= { NULL
};
233 int err
= reftable_iterator_next_ref(&it
, &ref
);
239 out
= reftable_realloc(
240 out
, sizeof(struct reftable_ref_record
) * cap
);
244 reftable_iterator_destroy(&it
);
246 EXPECT(ARRAY_SIZE(want
) == len
);
247 for (i
= 0; i
< len
; i
++) {
248 EXPECT(reftable_ref_record_equal(want
[i
], &out
[i
],
251 for (i
= 0; i
< len
; i
++) {
252 reftable_ref_record_release(&out
[i
]);
256 for (i
= 0; i
< 3; i
++) {
257 strbuf_release(&bufs
[i
]);
259 readers_destroy(readers
, 3);
260 reftable_merged_table_free(mt
);
264 static struct reftable_merged_table
*
265 merged_table_from_log_records(struct reftable_log_record
**logs
,
266 struct reftable_block_source
**source
,
267 struct reftable_reader
***readers
, int *sizes
,
268 struct strbuf
*buf
, int n
)
271 struct reftable_merged_table
*mt
= NULL
;
273 struct reftable_table
*tabs
=
274 reftable_calloc(n
* sizeof(struct reftable_table
));
275 *readers
= reftable_calloc(n
* sizeof(struct reftable_reader
*));
276 *source
= reftable_calloc(n
* sizeof(**source
));
277 for (i
= 0; i
< n
; i
++) {
278 write_test_log_table(&buf
[i
], logs
[i
], sizes
[i
], i
+ 1);
279 block_source_from_strbuf(&(*source
)[i
], &buf
[i
]);
281 err
= reftable_new_reader(&(*readers
)[i
], &(*source
)[i
],
284 reftable_table_from_reader(&tabs
[i
], (*readers
)[i
]);
287 err
= reftable_new_merged_table(&mt
, tabs
, n
, GIT_SHA1_FORMAT_ID
);
292 static void test_merged_logs(void)
294 uint8_t hash1
[GIT_SHA1_RAWSZ
] = { 1 };
295 uint8_t hash2
[GIT_SHA1_RAWSZ
] = { 2 };
296 uint8_t hash3
[GIT_SHA1_RAWSZ
] = { 3 };
297 struct reftable_log_record r1
[] = {
301 .value_type
= REFTABLE_LOG_UPDATE
,
306 .email
= "jane@invalid",
307 .message
= "message2",
313 .value_type
= REFTABLE_LOG_UPDATE
,
318 .email
= "jane@invalid",
319 .message
= "message1",
323 struct reftable_log_record r2
[] = {
327 .value_type
= REFTABLE_LOG_UPDATE
,
331 .email
= "jane@invalid",
332 .message
= "message3",
336 struct reftable_log_record r3
[] = {
340 .value_type
= REFTABLE_LOG_DELETION
,
343 struct reftable_log_record
*want
[] = {
349 struct reftable_log_record
*logs
[] = { r1
, r2
, r3
};
350 int sizes
[3] = { 2, 1, 1 };
351 struct strbuf bufs
[3] = { STRBUF_INIT
, STRBUF_INIT
, STRBUF_INIT
};
352 struct reftable_block_source
*bs
= NULL
;
353 struct reftable_reader
**readers
= NULL
;
354 struct reftable_merged_table
*mt
= merged_table_from_log_records(
355 logs
, &bs
, &readers
, sizes
, bufs
, 3);
357 struct reftable_iterator it
= { NULL
};
358 int err
= reftable_merged_table_seek_log(mt
, &it
, "a");
359 struct reftable_log_record
*out
= NULL
;
365 EXPECT(reftable_merged_table_hash_id(mt
) == GIT_SHA1_FORMAT_ID
);
366 EXPECT(reftable_merged_table_min_update_index(mt
) == 1);
368 while (len
< 100) { /* cap loops/recursion. */
369 struct reftable_log_record log
= { NULL
};
370 int err
= reftable_iterator_next_log(&it
, &log
);
376 out
= reftable_realloc(
377 out
, sizeof(struct reftable_log_record
) * cap
);
381 reftable_iterator_destroy(&it
);
383 EXPECT(ARRAY_SIZE(want
) == len
);
384 for (i
= 0; i
< len
; i
++) {
385 EXPECT(reftable_log_record_equal(want
[i
], &out
[i
],
389 err
= reftable_merged_table_seek_log_at(mt
, &it
, "a", 2);
391 reftable_log_record_release(&out
[0]);
392 err
= reftable_iterator_next_log(&it
, &out
[0]);
394 EXPECT(reftable_log_record_equal(&out
[0], &r3
[0], GIT_SHA1_RAWSZ
));
395 reftable_iterator_destroy(&it
);
397 for (i
= 0; i
< len
; i
++) {
398 reftable_log_record_release(&out
[i
]);
402 for (i
= 0; i
< 3; i
++) {
403 strbuf_release(&bufs
[i
]);
405 readers_destroy(readers
, 3);
406 reftable_merged_table_free(mt
);
410 static void test_default_write_opts(void)
412 struct reftable_write_options opts
= { 0 };
413 struct strbuf buf
= STRBUF_INIT
;
414 struct reftable_writer
*w
=
415 reftable_new_writer(&strbuf_add_void
, &buf
, &opts
);
417 struct reftable_ref_record rec
= {
422 struct reftable_block_source source
= { NULL
};
423 struct reftable_table
*tab
= reftable_calloc(sizeof(*tab
) * 1);
425 struct reftable_reader
*rd
= NULL
;
426 struct reftable_merged_table
*merged
= NULL
;
428 reftable_writer_set_limits(w
, 1, 1);
430 err
= reftable_writer_add_ref(w
, &rec
);
433 err
= reftable_writer_close(w
);
435 reftable_writer_free(w
);
437 block_source_from_strbuf(&source
, &buf
);
439 err
= reftable_new_reader(&rd
, &source
, "filename");
442 hash_id
= reftable_reader_hash_id(rd
);
443 EXPECT(hash_id
== GIT_SHA1_FORMAT_ID
);
445 reftable_table_from_reader(&tab
[0], rd
);
446 err
= reftable_new_merged_table(&merged
, tab
, 1, GIT_SHA1_FORMAT_ID
);
449 reftable_reader_free(rd
);
450 reftable_merged_table_free(merged
);
451 strbuf_release(&buf
);
454 /* XXX test refs_for(oid) */
456 int merged_test_main(int argc
, const char *argv
[])
458 RUN_TEST(test_merged_logs
);
459 RUN_TEST(test_merged_between
);
460 RUN_TEST(test_merged
);
461 RUN_TEST(test_default_write_opts
);