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 uint8_t hash1
[GIT_SHA1_RAWSZ
] = { 1, 2, 3, 0 };
127 struct reftable_ref_record r1
[] = { {
130 .value_type
= REFTABLE_REF_VAL1
,
133 struct reftable_ref_record r2
[] = { {
136 .value_type
= REFTABLE_REF_DELETION
,
139 struct reftable_ref_record
*refs
[] = { r1
, r2
};
140 int sizes
[] = { 1, 1 };
141 struct strbuf bufs
[2] = { STRBUF_INIT
, STRBUF_INIT
};
142 struct reftable_block_source
*bs
= NULL
;
143 struct reftable_reader
**readers
= NULL
;
144 struct reftable_merged_table
*mt
=
145 merged_table_from_records(refs
, &bs
, &readers
, sizes
, bufs
, 2);
147 struct reftable_ref_record ref
= { NULL
};
148 struct reftable_iterator it
= { NULL
};
149 int err
= reftable_merged_table_seek_ref(mt
, &it
, "a");
152 err
= reftable_iterator_next_ref(&it
, &ref
);
154 EXPECT(ref
.update_index
== 2);
155 reftable_ref_record_release(&ref
);
156 reftable_iterator_destroy(&it
);
157 readers_destroy(readers
, 2);
158 reftable_merged_table_free(mt
);
159 for (i
= 0; i
< ARRAY_SIZE(bufs
); i
++) {
160 strbuf_release(&bufs
[i
]);
165 static void test_merged(void)
167 uint8_t hash1
[GIT_SHA1_RAWSZ
] = { 1 };
168 uint8_t hash2
[GIT_SHA1_RAWSZ
] = { 2 };
169 struct reftable_ref_record r1
[] = {
173 .value_type
= REFTABLE_REF_VAL1
,
179 .value_type
= REFTABLE_REF_VAL1
,
185 .value_type
= REFTABLE_REF_VAL1
,
189 struct reftable_ref_record r2
[] = { {
192 .value_type
= REFTABLE_REF_DELETION
,
194 struct reftable_ref_record r3
[] = {
198 .value_type
= REFTABLE_REF_VAL1
,
204 .value_type
= REFTABLE_REF_VAL1
,
209 struct reftable_ref_record
*want
[] = {
216 struct reftable_ref_record
*refs
[] = { r1
, r2
, r3
};
217 int sizes
[3] = { 3, 1, 2 };
218 struct strbuf bufs
[3] = { STRBUF_INIT
, STRBUF_INIT
, STRBUF_INIT
};
219 struct reftable_block_source
*bs
= NULL
;
220 struct reftable_reader
**readers
= NULL
;
221 struct reftable_merged_table
*mt
=
222 merged_table_from_records(refs
, &bs
, &readers
, sizes
, bufs
, 3);
224 struct reftable_iterator it
= { NULL
};
225 int err
= reftable_merged_table_seek_ref(mt
, &it
, "a");
226 struct reftable_ref_record
*out
= NULL
;
232 EXPECT(reftable_merged_table_hash_id(mt
) == GIT_SHA1_FORMAT_ID
);
233 EXPECT(reftable_merged_table_min_update_index(mt
) == 1);
235 while (len
< 100) { /* cap loops/recursion. */
236 struct reftable_ref_record ref
= { NULL
};
237 int err
= reftable_iterator_next_ref(&it
, &ref
);
243 out
= reftable_realloc(
244 out
, sizeof(struct reftable_ref_record
) * cap
);
248 reftable_iterator_destroy(&it
);
250 EXPECT(ARRAY_SIZE(want
) == len
);
251 for (i
= 0; i
< len
; i
++) {
252 EXPECT(reftable_ref_record_equal(want
[i
], &out
[i
],
255 for (i
= 0; i
< len
; i
++) {
256 reftable_ref_record_release(&out
[i
]);
260 for (i
= 0; i
< 3; i
++) {
261 strbuf_release(&bufs
[i
]);
263 readers_destroy(readers
, 3);
264 reftable_merged_table_free(mt
);
268 static struct reftable_merged_table
*
269 merged_table_from_log_records(struct reftable_log_record
**logs
,
270 struct reftable_block_source
**source
,
271 struct reftable_reader
***readers
, int *sizes
,
272 struct strbuf
*buf
, int n
)
275 struct reftable_merged_table
*mt
= NULL
;
277 struct reftable_table
*tabs
=
278 reftable_calloc(n
* sizeof(struct reftable_table
));
279 *readers
= reftable_calloc(n
* sizeof(struct reftable_reader
*));
280 *source
= reftable_calloc(n
* sizeof(**source
));
281 for (i
= 0; i
< n
; i
++) {
282 write_test_log_table(&buf
[i
], logs
[i
], sizes
[i
], i
+ 1);
283 block_source_from_strbuf(&(*source
)[i
], &buf
[i
]);
285 err
= reftable_new_reader(&(*readers
)[i
], &(*source
)[i
],
288 reftable_table_from_reader(&tabs
[i
], (*readers
)[i
]);
291 err
= reftable_new_merged_table(&mt
, tabs
, n
, GIT_SHA1_FORMAT_ID
);
296 static void test_merged_logs(void)
298 uint8_t hash1
[GIT_SHA1_RAWSZ
] = { 1 };
299 uint8_t hash2
[GIT_SHA1_RAWSZ
] = { 2 };
300 uint8_t hash3
[GIT_SHA1_RAWSZ
] = { 3 };
301 struct reftable_log_record r1
[] = {
305 .value_type
= REFTABLE_LOG_UPDATE
,
310 .email
= "jane@invalid",
311 .message
= "message2",
317 .value_type
= REFTABLE_LOG_UPDATE
,
322 .email
= "jane@invalid",
323 .message
= "message1",
327 struct reftable_log_record r2
[] = {
331 .value_type
= REFTABLE_LOG_UPDATE
,
335 .email
= "jane@invalid",
336 .message
= "message3",
340 struct reftable_log_record r3
[] = {
344 .value_type
= REFTABLE_LOG_DELETION
,
347 struct reftable_log_record
*want
[] = {
353 struct reftable_log_record
*logs
[] = { r1
, r2
, r3
};
354 int sizes
[3] = { 2, 1, 1 };
355 struct strbuf bufs
[3] = { STRBUF_INIT
, STRBUF_INIT
, STRBUF_INIT
};
356 struct reftable_block_source
*bs
= NULL
;
357 struct reftable_reader
**readers
= NULL
;
358 struct reftable_merged_table
*mt
= merged_table_from_log_records(
359 logs
, &bs
, &readers
, sizes
, bufs
, 3);
361 struct reftable_iterator it
= { NULL
};
362 int err
= reftable_merged_table_seek_log(mt
, &it
, "a");
363 struct reftable_log_record
*out
= NULL
;
369 EXPECT(reftable_merged_table_hash_id(mt
) == GIT_SHA1_FORMAT_ID
);
370 EXPECT(reftable_merged_table_min_update_index(mt
) == 1);
372 while (len
< 100) { /* cap loops/recursion. */
373 struct reftable_log_record log
= { NULL
};
374 int err
= reftable_iterator_next_log(&it
, &log
);
380 out
= reftable_realloc(
381 out
, sizeof(struct reftable_log_record
) * cap
);
385 reftable_iterator_destroy(&it
);
387 EXPECT(ARRAY_SIZE(want
) == len
);
388 for (i
= 0; i
< len
; i
++) {
389 EXPECT(reftable_log_record_equal(want
[i
], &out
[i
],
393 err
= reftable_merged_table_seek_log_at(mt
, &it
, "a", 2);
395 reftable_log_record_release(&out
[0]);
396 err
= reftable_iterator_next_log(&it
, &out
[0]);
398 EXPECT(reftable_log_record_equal(&out
[0], &r3
[0], GIT_SHA1_RAWSZ
));
399 reftable_iterator_destroy(&it
);
401 for (i
= 0; i
< len
; i
++) {
402 reftable_log_record_release(&out
[i
]);
406 for (i
= 0; i
< 3; i
++) {
407 strbuf_release(&bufs
[i
]);
409 readers_destroy(readers
, 3);
410 reftable_merged_table_free(mt
);
414 static void test_default_write_opts(void)
416 struct reftable_write_options opts
= { 0 };
417 struct strbuf buf
= STRBUF_INIT
;
418 struct reftable_writer
*w
=
419 reftable_new_writer(&strbuf_add_void
, &buf
, &opts
);
421 struct reftable_ref_record rec
= {
426 struct reftable_block_source source
= { NULL
};
427 struct reftable_table
*tab
= reftable_calloc(sizeof(*tab
) * 1);
429 struct reftable_reader
*rd
= NULL
;
430 struct reftable_merged_table
*merged
= NULL
;
432 reftable_writer_set_limits(w
, 1, 1);
434 err
= reftable_writer_add_ref(w
, &rec
);
437 err
= reftable_writer_close(w
);
439 reftable_writer_free(w
);
441 block_source_from_strbuf(&source
, &buf
);
443 err
= reftable_new_reader(&rd
, &source
, "filename");
446 hash_id
= reftable_reader_hash_id(rd
);
447 EXPECT(hash_id
== GIT_SHA1_FORMAT_ID
);
449 reftable_table_from_reader(&tab
[0], rd
);
450 err
= reftable_new_merged_table(&merged
, tab
, 1, GIT_SHA1_FORMAT_ID
);
453 reftable_reader_free(rd
);
454 reftable_merged_table_free(merged
);
455 strbuf_release(&buf
);
458 /* XXX test refs_for(oid) */
460 int merged_test_main(int argc
, const char *argv
[])
462 RUN_TEST(test_merged_logs
);
463 RUN_TEST(test_merged_between
);
464 RUN_TEST(test_merged
);
465 RUN_TEST(test_default_write_opts
);