diff options
73 files changed, 2333 insertions, 1986 deletions
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index 528b42d1dd..f474120425 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -301,6 +301,14 @@ For C programs: . since late 2023 with 8277dbe987 we have been using the bool type from <stdbool.h>. + C99 features we have test balloons for: + + . since late 2024 with v2.48.0-rc0~20, we have test balloons for + compound literal syntax, e.g., (struct foo){ .member = value }; + our hope is that no platforms we care about have trouble using + them, and officially adopt its wider use in mid 2026. Do not add + more use of the syntax until that happens. + New C99 features that we cannot use yet: . %z and %zu as a printf() argument for a size_t (the %z being for diff --git a/Documentation/RelNotes/2.51.0.adoc b/Documentation/RelNotes/2.51.0.adoc index 1a874e6b46..78b4918533 100644 --- a/Documentation/RelNotes/2.51.0.adoc +++ b/Documentation/RelNotes/2.51.0.adoc @@ -53,6 +53,17 @@ UI, Workflows & Features * Clean up the way how signature on commit objects are exported to and imported from fast-import stream. + * Remove unsupported, unused, and unsupportable old option from "git + log". + + * Document recently added "git imap-send --list" with an example. + + * "git pull" learned to pay attention to pull.autostash configuration + variable, which overrides rebase/merge.autostash. + + * "git for-each-ref" learns "--start-after" option to help + applications that want to page its output. + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -103,6 +114,25 @@ Performance, Internal Implementation, Development Support etc. * GIT_TEST_INSTALLED was not honored in the recent topic related to SHA256 hashes, which has been corrected. + * The pop_most_recent_commit() function can have quite expensive + worst case performance characteristics, which has been optimized by + using prio-queue data structure. + + * Move structure definition from unrelated header file to where it + belongs. + + * To help our developers, document what C99 language features are + being considered for adoption, in addition to what past experiments + have already decided. + + * The reftable unit tests are now ported to the "clar" unit testing + framework. + + * Redefine where the multi-pack-index sits in the object subsystem, + which recently was restructured to allow multiple backends that + support a single object source that belongs to one repository. A + midx does span mulitple "object sources". + Fixes since v2.50 ----------------- @@ -225,6 +255,20 @@ including security updates, are included in this release. patches off. (merge 1f0fed312a bc/contribution-under-non-real-names later to maint). + * "git commit" that concludes a conflicted merge failed to notice and remove + existing comment added automatically (like "# Conflicts:") when the + core.commentstring is set to 'auto'. + (merge 92b7c7c9f5 ac/auto-comment-char-fix later to maint). + + * "git rebase -i" with bogus rebase.instructionFormat configuration + failed to produce the todo file after recording the state files, + leading to confused "git status"; this has been corrected. + (merge ade14bffd7 ow/rebase-verify-insn-fmt-before-initializing-state later to maint). + + * A few file descriptors left unclosed upon program completion in a + few test helper programs are now closed. + (merge 0f1b33815b hl/test-helper-fd-close later to maint). + * Other code cleanup, docfix, build fix, etc. (merge b257adb571 lo/my-first-ow-doc-update later to maint). (merge 8b34b6a220 ly/sequencer-update-squash-is-fixup-only later to maint). @@ -251,3 +295,7 @@ including security updates, are included in this release. (merge f4fa8a3687 rh/doc-glob-pathspec-fix later to maint). (merge b27be108c8 ja/doc-git-log-markup later to maint). (merge 14d7583beb pw/config-kvi-remove-path later to maint). + (merge f31abb421d jc/do-not-scan-argv-without-parsing later to maint). + (merge 26552cb62a jk/unleak-reflog-expire-entry later to maint). + (merge 339d95fda9 jc/ci-print-test-failures-fix later to maint). + (merge 8c3add51a8 cb/meson-avoid-broken-macos-pcre2 later to maint). diff --git a/Documentation/config/pull.adoc b/Documentation/config/pull.adoc index 9349e09261..125c930f72 100644 --- a/Documentation/config/pull.adoc +++ b/Documentation/config/pull.adoc @@ -29,5 +29,21 @@ pull.octopus:: The default merge strategy to use when pulling multiple branches at once. +pull.autoStash:: + When set to true, automatically create a temporary stash entry + to record the local changes before the operation begins, and + restore them after the operation completes. When your "git + pull" rebases (instead of merges), this may be convenient, since + unlike merging pull that tolerates local changes that do not + interfere with the merge, rebasing pull refuses to work with any + local changes. ++ +If `pull.autostash` is set (either to true or false), +`merge.autostash` and `rebase.autostash` are ignored. If +`pull.autostash` is not set at all, depending on the value of +`pull.rebase`, `merge.autostash` or `rebase.autostash` is used +instead. Can be overridden by the `--[no-]autostash` command line +option. + pull.twohead:: The default merge strategy to use when pulling a single branch. diff --git a/Documentation/git-for-each-ref.adoc b/Documentation/git-for-each-ref.adoc index 5ef89fc0fe..ae61ba642a 100644 --- a/Documentation/git-for-each-ref.adoc +++ b/Documentation/git-for-each-ref.adoc @@ -14,7 +14,7 @@ SYNOPSIS [--points-at=<object>] [--merged[=<object>]] [--no-merged[=<object>]] [--contains[=<object>]] [--no-contains[=<object>]] - [--exclude=<pattern> ...] + [--exclude=<pattern> ...] [--start-after=<marker>] DESCRIPTION ----------- @@ -108,6 +108,14 @@ TAB %(refname)`. --include-root-refs:: List root refs (HEAD and pseudorefs) apart from regular refs. +--start-after=<marker>:: + Allows paginating the output by skipping references up to and including the + specified marker. When paging, it should be noted that references may be + deleted, modified or added between invocations. Output will only yield those + references which follow the marker lexicographically. Output begins from the + first reference that would come after the marker alphabetically. Cannot be + used with general pattern matching or custom sort options. + FIELD NAMES ----------- diff --git a/Documentation/git-imap-send.adoc b/Documentation/git-imap-send.adoc index 17147f93c3..278e5ccd36 100644 --- a/Documentation/git-imap-send.adoc +++ b/Documentation/git-imap-send.adoc @@ -68,6 +68,34 @@ include::includes/cmd-config-section-rest.adoc[] include::config/imap.adoc[] +GETTING A LIST OF AVAILABLE FOLDERS +----------------------------------- + +In order to send an email to a specific folder, you need to know the correct name of +intended folder in your mailbox. The names like "Junk", "Trash" etc. displayed by +various email clients need not be the actual names of the folders stored in the mail +server of your email provider. + +In order to get the correct folder name to be used with `git imap-send`, you can run +`git imap-send --list`. This will display a list of valid folder names. An example +of such an output when run on a Gmail account is: + +......................... +* LIST (\HasNoChildren) "/" "INBOX" +* LIST (\HasChildren \Noselect) "/" "[Gmail]" +* LIST (\All \HasNoChildren) "/" "[Gmail]/All Mail" +* LIST (\Drafts \HasNoChildren) "/" "[Gmail]/Drafts" +* LIST (\HasNoChildren \Important) "/" "[Gmail]/Important" +* LIST (\HasNoChildren \Sent) "/" "[Gmail]/Sent Mail" +* LIST (\HasNoChildren \Junk) "/" "[Gmail]/Spam" +* LIST (\Flagged \HasNoChildren) "/" "[Gmail]/Starred" +* LIST (\HasNoChildren \Trash) "/" "[Gmail]/Trash" +......................... + +Here, you can observe that the correct name for the "Junk" folder is `[Gmail]/Spam` +and for the "Trash" folder is `[Gmail]/Trash`. Similar logic can be used to determine +other folders as well. + EXAMPLES -------- Using tunnel mode: @@ -1362,6 +1362,13 @@ CLAR_TEST_SUITES += u-oid-array CLAR_TEST_SUITES += u-oidmap CLAR_TEST_SUITES += u-oidtree CLAR_TEST_SUITES += u-prio-queue +CLAR_TEST_SUITES += u-reftable-basics +CLAR_TEST_SUITES += u-reftable-block +CLAR_TEST_SUITES += u-reftable-merged +CLAR_TEST_SUITES += u-reftable-pq +CLAR_TEST_SUITES += u-reftable-readwrite +CLAR_TEST_SUITES += u-reftable-stack +CLAR_TEST_SUITES += u-reftable-table CLAR_TEST_SUITES += u-reftable-tree CLAR_TEST_SUITES += u-strbuf CLAR_TEST_SUITES += u-strcmp-offset @@ -1372,20 +1379,11 @@ CLAR_TEST_SUITES += u-urlmatch-normalization CLAR_TEST_PROG = $(UNIT_TEST_BIN)/unit-tests$(X) CLAR_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(CLAR_TEST_SUITES)) CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/clar/clar.o -CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/lib-oid.o +CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/lib-reftable.o +CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o -UNIT_TEST_PROGRAMS += t-reftable-basics -UNIT_TEST_PROGRAMS += t-reftable-block -UNIT_TEST_PROGRAMS += t-reftable-merged -UNIT_TEST_PROGRAMS += t-reftable-pq -UNIT_TEST_PROGRAMS += t-reftable-readwrite -UNIT_TEST_PROGRAMS += t-reftable-record -UNIT_TEST_PROGRAMS += t-reftable-stack -UNIT_TEST_PROGRAMS += t-reftable-table -UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS)) UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o -UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-reftable.o # xdiff and reftable libs may in turn depend on what is in libgit.a GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE) @@ -27,14 +27,6 @@ struct commit_list *filter_skipped(struct commit_list *list, #define FIND_BISECTION_ALL (1u<<0) #define FIND_BISECTION_FIRST_PARENT_ONLY (1u<<1) -struct rev_list_info { - struct rev_info *revs; - int flags; - int show_timestamp; - int hdr_termination; - const char *header_prefix; -}; - /* * enum bisect_error represents the following return codes: * BISECT_OK: success code. Internally, it means that next diff --git a/builtin/commit.c b/builtin/commit.c index fba0dded64..63e7158e98 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -688,6 +688,10 @@ static void adjust_comment_line_char(const struct strbuf *sb) char candidates[] = "#;@!$%^&|:"; char *candidate; const char *p; + size_t cutoff; + + /* Ignore comment chars in trailing comments (e.g., Conflicts:) */ + cutoff = sb->len - ignored_log_message_bytes(sb->buf, sb->len); if (!memchr(sb->buf, candidates[0], sb->len)) { free(comment_line_str_to_free); @@ -700,7 +704,7 @@ static void adjust_comment_line_char(const struct strbuf *sb) candidate = strchr(candidates, *p); if (candidate) *candidate = ' '; - for (p = sb->buf; *p; p++) { + for (p = sb->buf; p + 1 < sb->buf + cutoff; p++) { if ((p[0] == '\n' || p[0] == '\r') && p[1]) { candidate = strchr(candidates, p[1]); if (candidate) diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 3d2207ec77..3f21598046 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -13,6 +13,7 @@ static char const * const for_each_ref_usage[] = { N_("git for-each-ref [--points-at <object>]"), N_("git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"), N_("git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"), + N_("git for-each-ref [--start-after <marker>]"), NULL }; @@ -44,6 +45,7 @@ int cmd_for_each_ref(int argc, OPT_GROUP(""), OPT_INTEGER( 0 , "count", &format.array_opts.max_count, N_("show only <n> matched refs")), OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")), + OPT_STRING( 0 , "start-after", &filter.start_after, N_("start-start"), N_("start iteration after the provided marker")), OPT__COLOR(&format.use_color, N_("respect format colors")), OPT_REF_FILTER_EXCLUDE(&filter), OPT_REF_SORT(&sorting_options), @@ -79,6 +81,9 @@ int cmd_for_each_ref(int argc, if (verify_ref_format(&format)) usage_with_options(for_each_ref_usage, opts); + if (filter.start_after && sorting_options.nr > 1) + die(_("cannot use --start-after with custom sort options")); + sorting = ref_sorting_options(&sorting_options); ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase); filter.ignore_case = icase; @@ -100,6 +105,9 @@ int cmd_for_each_ref(int argc, filter.name_patterns = argv; } + if (filter.start_after && filter.name_patterns && filter.name_patterns[0]) + die(_("cannot use --start-after with patterns")); + if (include_root_refs) flags |= FILTER_REFS_ROOT_REFS | FILTER_REFS_DETACHED_HEAD; diff --git a/builtin/gc.c b/builtin/gc.c index fab8f4dd4f..a02d6b7806 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -346,6 +346,7 @@ static int reflog_expire_condition(struct gc_config *cfg UNUSED) count_reflog_entries, &data); reflog_expiry_cleanup(&data.policy); + reflog_clear_expire_config(&data.policy.opts); return data.count >= data.limit; } diff --git a/builtin/log.c b/builtin/log.c index 24a57c20a4..fb42e094af 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -391,129 +391,6 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, cmd_log_init_finish(argc, argv, prefix, rev, opt, cfg); } -/* - * This gives a rough estimate for how many commits we - * will print out in the list. - */ -static int estimate_commit_count(struct commit_list *list) -{ - int n = 0; - - while (list) { - struct commit *commit = list->item; - unsigned int flags = commit->object.flags; - list = list->next; - if (!(flags & (TREESAME | UNINTERESTING))) - n++; - } - return n; -} - -static void show_early_header(struct rev_info *rev, const char *stage, int nr) -{ - if (rev->shown_one) { - rev->shown_one = 0; - if (rev->commit_format != CMIT_FMT_ONELINE) - putchar(rev->diffopt.line_termination); - } - fprintf(rev->diffopt.file, _("Final output: %d %s\n"), nr, stage); -} - -static struct itimerval early_output_timer; - -static void log_show_early(struct rev_info *revs, struct commit_list *list) -{ - int i = revs->early_output; - int show_header = 1; - int no_free = revs->diffopt.no_free; - - revs->diffopt.no_free = 0; - sort_in_topological_order(&list, revs->sort_order); - while (list && i) { - struct commit *commit = list->item; - switch (simplify_commit(revs, commit)) { - case commit_show: - if (show_header) { - int n = estimate_commit_count(list); - show_early_header(revs, "incomplete", n); - show_header = 0; - } - log_tree_commit(revs, commit); - i--; - break; - case commit_ignore: - break; - case commit_error: - revs->diffopt.no_free = no_free; - diff_free(&revs->diffopt); - return; - } - list = list->next; - } - - /* Did we already get enough commits for the early output? */ - if (!i) { - revs->diffopt.no_free = 0; - diff_free(&revs->diffopt); - return; - } - - /* - * ..if no, then repeat it twice a second until we - * do. - * - * NOTE! We don't use "it_interval", because if the - * reader isn't listening, we want our output to be - * throttled by the writing, and not have the timer - * trigger every second even if we're blocked on a - * reader! - */ - early_output_timer.it_value.tv_sec = 0; - early_output_timer.it_value.tv_usec = 500000; - setitimer(ITIMER_REAL, &early_output_timer, NULL); -} - -static void early_output(int signal UNUSED) -{ - show_early_output = log_show_early; -} - -static void setup_early_output(void) -{ - struct sigaction sa; - - /* - * Set up the signal handler, minimally intrusively: - * we only set a single volatile integer word (not - * using sigatomic_t - trying to avoid unnecessary - * system dependencies and headers), and using - * SA_RESTART. - */ - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = early_output; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sigaction(SIGALRM, &sa, NULL); - - /* - * If we can get the whole output in less than a - * tenth of a second, don't even bother doing the - * early-output thing.. - * - * This is a one-time-only trigger. - */ - early_output_timer.it_value.tv_sec = 0; - early_output_timer.it_value.tv_usec = 100000; - setitimer(ITIMER_REAL, &early_output_timer, NULL); -} - -static void finish_early_output(struct rev_info *rev) -{ - int n = estimate_commit_count(rev->commits); - signal(SIGALRM, SIG_IGN); - show_early_header(rev, "done", n); -} - static int cmd_log_walk_no_free(struct rev_info *rev) { struct commit *commit; @@ -521,15 +398,9 @@ static int cmd_log_walk_no_free(struct rev_info *rev) int saved_dcctc = 0; int result; - if (rev->early_output) - setup_early_output(); - if (prepare_revision_walk(rev)) die(_("revision walk setup failed")); - if (rev->early_output) - finish_early_output(rev); - /* * For --check and --exit-code, the exit code is based on CHECK_FAILED * and HAS_CHANGES being accumulated in rev->diffopt, so be careful to diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 067b9e322a..3dd84495b8 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1706,8 +1706,8 @@ static int want_object_in_pack_mtime(const struct object_id *oid, uint32_t found_mtime) { int want; + struct odb_source *source; struct list_head *pos; - struct multi_pack_index *m; if (!exclude && local && has_loose_object_nonlocal(oid)) return 0; @@ -1727,9 +1727,13 @@ static int want_object_in_pack_mtime(const struct object_id *oid, *found_offset = 0; } - for (m = get_multi_pack_index(the_repository); m; m = m->next) { + odb_prepare_alternates(the_repository->objects); + + for (source = the_repository->objects->sources; source; source = source->next) { + struct multi_pack_index *m = get_multi_pack_index(source); struct pack_entry e; - if (fill_midx_entry(the_repository, oid, &e, m)) { + + if (m && fill_midx_entry(the_repository, oid, &e, m)) { want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime); if (want != -1) return want; diff --git a/builtin/pull.c b/builtin/pull.c index c593f324fe..2a6c2e4a37 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -90,7 +90,8 @@ static char *opt_ff; static const char *opt_verify_signatures; static const char *opt_verify; static int opt_autostash = -1; -static int config_autostash; +static int config_rebase_autostash; +static int config_pull_autostash = -1; static int check_trust_level = 1; static struct strvec opt_strategies = STRVEC_INIT; static struct strvec opt_strategy_opts = STRVEC_INIT; @@ -367,7 +368,18 @@ static int git_pull_config(const char *var, const char *value, const struct config_context *ctx, void *cb) { if (!strcmp(var, "rebase.autostash")) { - config_autostash = git_config_bool(var, value); + /* + * run_rebase() also reads this option. The reason we handle it here is + * that when pull.rebase is true, a fast-forward may occur without + * invoking run_rebase(). We need to ensure that autostash is set even + * in the fast-forward case. + * + * run_merge() handles merge.autostash, so we don't handle it here. + */ + config_rebase_autostash = git_config_bool(var, value); + return 0; + } else if (!strcmp(var, "pull.autostash")) { + config_pull_autostash = git_config_bool(var, value); return 0; } else if (!strcmp(var, "submodule.recurse")) { recurse_submodules = git_config_bool(var, value) ? @@ -1006,6 +1018,8 @@ int cmd_pull(int argc, } argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0); + if (opt_autostash == -1) + opt_autostash = config_pull_autostash; if (recurse_submodules_cli != RECURSE_SUBMODULES_DEFAULT) recurse_submodules = recurse_submodules_cli; @@ -1052,7 +1066,7 @@ int cmd_pull(int argc, if (opt_rebase) { if (opt_autostash == -1) - opt_autostash = config_autostash; + opt_autostash = config_rebase_autostash; if (is_null_oid(&orig_head) && !is_index_unborn(the_repository->index)) die(_("Updating an unborn branch with changes added to the index.")); diff --git a/builtin/rebase.c b/builtin/rebase.c index e90562a3b8..08024e133c 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -293,15 +293,6 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags) &revisions, &shortrevisions)) goto cleanup; - if (init_basic_state(&replay, - opts->head_name ? opts->head_name : "detached HEAD", - opts->onto, &opts->orig_head->object.oid)) - goto cleanup; - - if (!opts->upstream && opts->squash_onto) - write_file(path_squash_onto(), "%s\n", - oid_to_hex(opts->squash_onto)); - strvec_pushl(&make_script_args, "", revisions, NULL); if (opts->restrict_revision) strvec_pushf(&make_script_args, "^%s", @@ -310,21 +301,30 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags) ret = sequencer_make_script(the_repository, &todo_list.buf, make_script_args.nr, make_script_args.v, flags); - - if (ret) + if (ret) { error(_("could not generate todo list")); - else { - discard_index(the_repository->index); - if (todo_list_parse_insn_buffer(the_repository, &replay, - todo_list.buf.buf, &todo_list)) - BUG("unusable todo list"); - - ret = complete_action(the_repository, &replay, flags, - shortrevisions, opts->onto_name, opts->onto, - &opts->orig_head->object.oid, &opts->exec, - opts->autosquash, opts->update_refs, &todo_list); + goto cleanup; } + if (init_basic_state(&replay, + opts->head_name ? opts->head_name : "detached HEAD", + opts->onto, &opts->orig_head->object.oid)) + goto cleanup; + + if (!opts->upstream && opts->squash_onto) + write_file(path_squash_onto(), "%s\n", + oid_to_hex(opts->squash_onto)); + + discard_index(the_repository->index); + if (todo_list_parse_insn_buffer(the_repository, &replay, + todo_list.buf.buf, &todo_list)) + BUG("unusable todo list"); + + ret = complete_action(the_repository, &replay, flags, + shortrevisions, opts->onto_name, opts->onto, + &opts->orig_head->object.oid, &opts->exec, + opts->autosquash, opts->update_refs, &todo_list); + cleanup: replay_opts_release(&replay); free(revisions); diff --git a/builtin/reflog.c b/builtin/reflog.c index 3acaf3e32c..d4da41aaea 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -283,6 +283,9 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, &cb); free(ref); } + + reflog_clear_expire_config(&opts); + return status; } diff --git a/builtin/repack.c b/builtin/repack.c index 75158d7776..21723866b9 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -223,9 +223,9 @@ static void mark_packs_for_deletion(struct existing_packs *existing, static void remove_redundant_pack(const char *dir_name, const char *base_name) { struct strbuf buf = STRBUF_INIT; - struct multi_pack_index *m = get_local_multi_pack_index(the_repository); + struct multi_pack_index *m = get_multi_pack_index(the_repository->objects->sources); strbuf_addf(&buf, "%s.pack", base_name); - if (m && midx_contains_pack(m, buf.buf)) + if (m && m->local && midx_contains_pack(m, buf.buf)) clear_midx_file(the_repository); strbuf_insertf(&buf, 0, "%s/", dir_name); unlink_pack_path(buf.buf, 1); @@ -1531,7 +1531,7 @@ int cmd_repack(int argc, * midx_has_unknown_packs() will make the decision for * us. */ - if (!get_local_multi_pack_index(the_repository)) + if (!get_multi_pack_index(the_repository->objects->sources)) midx_must_contain_cruft = 1; } @@ -1614,9 +1614,9 @@ int cmd_repack(int argc, string_list_sort(&names); - if (get_local_multi_pack_index(the_repository)) { + if (get_multi_pack_index(the_repository->objects->sources)) { struct multi_pack_index *m = - get_local_multi_pack_index(the_repository); + get_multi_pack_index(the_repository->objects->sources); ALLOC_ARRAY(midx_pack_names, m->num_packs + m->num_packs_in_base); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 4d0c460f18..97a3af36ec 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -28,6 +28,14 @@ #include "quote.h" #include "strbuf.h" +struct rev_list_info { + struct rev_info *revs; + int flags; + int show_timestamp; + int hdr_termination; + const char *header_prefix; +}; + static const char rev_list_usage[] = "git rev-list [<options>] <commit>... [--] [<path>...]\n" "\n" @@ -652,17 +660,21 @@ int cmd_rev_list(int argc, * * Let "--missing" to conditionally set fetch_if_missing. */ + /* - * NEEDSWORK: These loops that attempt to find presence of - * options without understanding that the options they are - * skipping are broken (e.g., it would not know "--grep + * NEEDSWORK: The next loop is utterly broken. It tries to + * notice an option is used, but without understanding if each + * option takes an argument, which fundamentally would not + * work. It would not know "--grep * --exclude-promisor-objects" is not triggering - * "--exclude-promisor-objects" option). We really need - * setup_revisions() to have a mechanism to allow and disallow - * some sets of options for different commands (like rev-list, - * replay, etc). Such a mechanism should do an early parsing - * of options and be able to manage the `--missing=...` and - * `--exclude-promisor-objects` options below. + * "--exclude-promisor-objects" option, for example. + * + * We really need setup_revisions() to have a mechanism to + * allow and disallow some sets of options for different + * commands (like rev-list, replay, etc). Such a mechanism + * should do an early parsing of options and be able to manage + * the `--missing=...` and `--exclude-promisor-objects` + * options below. */ for (i = 1; i < argc; i++) { const char *arg = argv[i]; diff --git a/ci/print-test-failures.sh b/ci/print-test-failures.sh index dc910e5160..5545e77c13 100755 --- a/ci/print-test-failures.sh +++ b/ci/print-test-failures.sh @@ -41,7 +41,7 @@ do case "$CI_TYPE" in github-actions) mkdir -p failed-test-artifacts - echo "FAILED_TEST_ARTIFACTS=${TEST_OUTPUT_DIRECTORY:t}/failed-test-artifacts" >>$GITHUB_ENV + echo "FAILED_TEST_ARTIFACTS=${TEST_OUTPUT_DIRECTORY:-t}/failed-test-artifacts" >>$GITHUB_ENV cp "${TEST_EXIT%.exit}.out" failed-test-artifacts/ tar czf failed-test-artifacts/"$test_name".trash.tar.gz "$trash_dir" continue @@ -31,6 +31,7 @@ #include "parse.h" #include "object-file.h" #include "object-file-convert.h" +#include "prio-queue.h" static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **); @@ -739,20 +740,27 @@ void commit_list_sort_by_date(struct commit_list **list) commit_list_sort(list, commit_list_compare_by_date); } -struct commit *pop_most_recent_commit(struct commit_list **list, +struct commit *pop_most_recent_commit(struct prio_queue *queue, unsigned int mark) { - struct commit *ret = pop_commit(list); + struct commit *ret = prio_queue_peek(queue); + int get_pending = 1; struct commit_list *parents = ret->parents; while (parents) { struct commit *commit = parents->item; if (!repo_parse_commit(the_repository, commit) && !(commit->object.flags & mark)) { commit->object.flags |= mark; - commit_list_insert_by_date(commit, list); + if (get_pending) + prio_queue_replace(queue, commit); + else + prio_queue_put(queue, commit); + get_pending = 0; } parents = parents->next; } + if (get_pending) + prio_queue_get(queue); return ret; } @@ -201,10 +201,10 @@ const char *repo_logmsg_reencode(struct repository *r, const char *skip_blank_lines(const char *msg); -/** Removes the first commit from a list sorted by date, and adds all - * of its parents. - **/ -struct commit *pop_most_recent_commit(struct commit_list **list, +struct prio_queue; + +/* Removes the first commit from a prio_queue and adds its parents. */ +struct commit *pop_most_recent_commit(struct prio_queue *queue, unsigned int mark); struct commit *pop_commit(struct commit_list **stack); @@ -1534,9 +1534,11 @@ static int git_default_core_config(const char *var, const char *value, !strcmp(var, "core.commentstring")) { if (!value) return config_error_nonbool(var); - else if (!strcasecmp(value, "auto")) + else if (!strcasecmp(value, "auto")) { auto_comment_line_char = 1; - else if (value[0]) { + FREE_AND_NULL(comment_line_str_to_free); + comment_line_str = "#"; + } else if (value[0]) { if (strchr(value, '\n')) return error(_("%s cannot contain newline"), var); comment_line_str = value; diff --git a/fetch-pack.c b/fetch-pack.c index 01d3699c4b..c1be9b76eb 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -34,6 +34,7 @@ #include "commit-graph.h" #include "sigchain.h" #include "mergesort.h" +#include "prio-queue.h" static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; @@ -601,7 +602,7 @@ done: return count ? retval : 0; } -static struct commit_list *complete; +static struct prio_queue complete = { compare_commits_by_commit_date }; static int mark_complete(const struct object_id *oid) { @@ -609,7 +610,7 @@ static int mark_complete(const struct object_id *oid) if (commit && !(commit->object.flags & COMPLETE)) { commit->object.flags |= COMPLETE; - commit_list_insert(commit, &complete); + prio_queue_put(&complete, commit); } return 0; } @@ -626,9 +627,12 @@ static int mark_complete_oid(const char *refname UNUSED, static void mark_recent_complete_commits(struct fetch_pack_args *args, timestamp_t cutoff) { - while (complete && cutoff <= complete->item->date) { + while (complete.nr) { + struct commit *item = prio_queue_peek(&complete); + if (item->date < cutoff) + break; print_verbose(args, _("Marking %s as complete"), - oid_to_hex(&complete->item->object.oid)); + oid_to_hex(&item->object.oid)); pop_most_recent_commit(&complete, COMPLETE); } } @@ -798,7 +802,6 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator, refs_for_each_rawref(get_main_ref_store(the_repository), mark_complete_oid, NULL); for_each_cached_alternate(NULL, mark_alternate_complete); - commit_list_sort_by_date(&complete); if (cutoff) mark_recent_complete_commits(args, cutoff); } diff --git a/meson.build b/meson.build index 9bc1826cb6..c043a79dca 100644 --- a/meson.build +++ b/meson.build @@ -1057,7 +1057,33 @@ else build_options_config.set('NO_ICONV', '1') endif -pcre2 = dependency('libpcre2-8', required: get_option('pcre2'), default_options: ['default_library=static', 'test=false']) +# can't use enable_auto_if() because it is only available in meson 1.1 +if host_machine.system() == 'windows' and get_option('pcre2').allowed() + pcre2_feature = true +else + pcre2_feature = get_option('pcre2') +endif +pcre2 = dependency('libpcre2-8', required: pcre2_feature, default_options: ['default_library=static', 'test=false']) +if pcre2.found() and pcre2.type_name() != 'internal' and host_machine.system() == 'darwin' + # macOS installs a broken system package, double check + if not compiler.has_header('pcre2.h', dependencies: pcre2) + if pcre2_feature.enabled() + pcre2_fallback = ['pcre2', 'libpcre2_8'] + else + pcre2_fallback = [] + endif + # Attempt to fallback or replace with not-found-dependency + pcre2 = dependency('', required: false, fallback: pcre2_fallback, default_options: ['default_library=static', 'test=false']) + if not pcre2.found() + if pcre2_feature.enabled() + error('only a broken pcre2 install found and pcre2 is required') + else + warning('broken pcre2 install found, disabling pcre2 feature') + endif + endif + endif +endif + if pcre2.found() libgit_dependencies += pcre2 libgit_c_args += '-DUSE_LIBPCRE2' diff --git a/meson_options.txt b/meson_options.txt index e7f768df24..1668f260a1 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -45,7 +45,7 @@ option('gitweb', type: 'feature', value: 'auto', description: 'Build Git web interface. Requires Perl.') option('iconv', type: 'feature', value: 'auto', description: 'Support reencoding strings with different encodings.') -option('pcre2', type: 'feature', value: 'enabled', +option('pcre2', type: 'feature', value: 'auto', description: 'Support Perl-compatible regular expressions in e.g. git-grep(1).') option('perl', type: 'feature', value: 'auto', description: 'Build tools written in Perl.') diff --git a/midx-write.c b/midx-write.c index f2cfb85476..c1ae62d354 100644 --- a/midx-write.c +++ b/midx-write.c @@ -916,26 +916,8 @@ cleanup: static struct multi_pack_index *lookup_multi_pack_index(struct repository *r, const char *object_dir) { - struct multi_pack_index *result = NULL; - struct multi_pack_index *cur; - char *obj_dir_real = real_pathdup(object_dir, 1); - struct strbuf cur_path_real = STRBUF_INIT; - - /* Ensure the given object_dir is local, or a known alternate. */ - odb_find_source(r->objects, obj_dir_real); - - for (cur = get_multi_pack_index(r); cur; cur = cur->next) { - strbuf_realpath(&cur_path_real, cur->object_dir, 1); - if (!strcmp(obj_dir_real, cur_path_real.buf)) { - result = cur; - goto cleanup; - } - } - -cleanup: - free(obj_dir_real); - strbuf_release(&cur_path_real); - return result; + struct odb_source *source = odb_find_source(r->objects, object_dir); + return get_multi_pack_index(source); } static int fill_packs_from_midx(struct write_midx_context *ctx, @@ -401,7 +401,6 @@ void close_midx(struct multi_pack_index *m) if (!m) return; - close_midx(m->next); close_midx(m->base_midx); munmap((unsigned char *)m->data, m->data_len); @@ -724,32 +723,20 @@ int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id) return 0; } -int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local) +int prepare_multi_pack_index_one(struct odb_source *source, int local) { - struct multi_pack_index *m; - struct multi_pack_index *m_search; + struct repository *r = source->odb->repo; prepare_repo_settings(r); if (!r->settings.core_multi_pack_index) return 0; - for (m_search = r->objects->multi_pack_index; m_search; m_search = m_search->next) - if (!strcmp(object_dir, m_search->object_dir)) - return 1; - - m = load_multi_pack_index(r, object_dir, local); - - if (m) { - struct multi_pack_index *mp = r->objects->multi_pack_index; - if (mp) { - m->next = mp->next; - mp->next = m; - } else - r->objects->multi_pack_index = m; + if (source->midx) return 1; - } - return 0; + source->midx = load_multi_pack_index(r, source->path, local); + + return !!source->midx; } int midx_checksum_valid(struct multi_pack_index *m) @@ -834,9 +821,14 @@ void clear_midx_file(struct repository *r) get_midx_filename(r->hash_algo, &midx, r->objects->sources->path); - if (r->objects && r->objects->multi_pack_index) { - close_midx(r->objects->multi_pack_index); - r->objects->multi_pack_index = NULL; + if (r->objects) { + struct odb_source *source; + + for (source = r->objects->sources; source; source = source->next) { + if (source->midx) + close_midx(source->midx); + source->midx = NULL; + } } if (remove_path(midx.buf)) @@ -8,6 +8,7 @@ struct pack_entry; struct repository; struct bitmapped_pack; struct git_hash_algo; +struct odb_source; #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */ #define MIDX_VERSION 1 @@ -34,8 +35,6 @@ struct git_hash_algo; "GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL" struct multi_pack_index { - struct multi_pack_index *next; - const unsigned char *data; size_t data_len; @@ -123,7 +122,7 @@ int fill_midx_entry(struct repository *r, const struct object_id *oid, struct pa int midx_contains_pack(struct multi_pack_index *m, const char *idx_or_pack_name); int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id); -int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local); +int prepare_multi_pack_index_one(struct odb_source *source, int local); /* * Variant of write_midx_file which writes a MIDX containing only the packs diff --git a/object-name.c b/object-name.c index ddafe7f9b1..11aa0e6afc 100644 --- a/object-name.c +++ b/object-name.c @@ -28,6 +28,7 @@ #include "commit-reach.h" #include "date.h" #include "object-file-convert.h" +#include "prio-queue.h" static int get_oid_oneline(struct repository *r, const char *, struct object_id *, const struct commit_list *); @@ -198,16 +199,20 @@ static void unique_in_pack(struct packed_git *p, static void find_short_packed_object(struct disambiguate_state *ds) { - struct multi_pack_index *m; + struct odb_source *source; struct packed_git *p; /* Skip, unless oids from the storage hash algorithm are wanted */ if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo)) return; - for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous; - m = m->next) - unique_in_midx(m, ds); + odb_prepare_alternates(ds->repo->objects); + for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) { + struct multi_pack_index *m = get_multi_pack_index(source); + if (m) + unique_in_midx(m, ds); + } + for (p = get_packed_git(ds->repo); p && !ds->ambiguous; p = p->next) unique_in_pack(p, ds); @@ -792,11 +797,15 @@ static void find_abbrev_len_for_pack(struct packed_git *p, static void find_abbrev_len_packed(struct min_abbrev_data *mad) { - struct multi_pack_index *m; struct packed_git *p; - for (m = get_multi_pack_index(mad->repo); m; m = m->next) - find_abbrev_len_for_midx(m, mad); + odb_prepare_alternates(mad->repo->objects); + for (struct odb_source *source = mad->repo->objects->sources; source; source = source->next) { + struct multi_pack_index *m = get_multi_pack_index(source); + if (m) + find_abbrev_len_for_midx(m, mad); + } + for (p = get_packed_git(mad->repo); p; p = p->next) find_abbrev_len_for_pack(p, mad); } @@ -1461,7 +1470,7 @@ static int get_oid_oneline(struct repository *r, const char *prefix, struct object_id *oid, const struct commit_list *list) { - struct commit_list *copy = NULL, **copy_tail = © + struct prio_queue copy = { compare_commits_by_commit_date }; const struct commit_list *l; int found = 0; int negative = 0; @@ -1483,9 +1492,9 @@ static int get_oid_oneline(struct repository *r, for (l = list; l; l = l->next) { l->item->object.flags |= ONELINE_SEEN; - copy_tail = &commit_list_insert(l->item, copy_tail)->next; + prio_queue_put(©, l->item); } - while (copy) { + while (copy.nr) { const char *p, *buf; struct commit *commit; int matches; @@ -1507,7 +1516,7 @@ static int get_oid_oneline(struct repository *r, regfree(®ex); for (l = list; l; l = l->next) clear_commit_marks(l->item, ONELINE_SEEN); - free_commit_list(copy); + clear_prio_queue(©); return found ? 0 : -1; } @@ -2061,7 +2070,6 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo, cb.list = &list; refs_for_each_ref(get_main_ref_store(repo), handle_one_ref, &cb); refs_head_ref(get_main_ref_store(repo), handle_one_ref, &cb); - commit_list_sort_by_date(&list); ret = get_oid_oneline(repo, name + 2, oid, list); free_commit_list(list); @@ -13,6 +13,7 @@ struct oidmap; struct oidtree; struct strbuf; struct repository; +struct multi_pack_index; /* * Compute the exact path an alternate is at and returns it. In case of @@ -56,6 +57,13 @@ struct odb_source { struct loose_object_map *loose_map; /* + * private data + * + * should only be accessed directly by packfile.c and midx.c + */ + struct multi_pack_index *midx; + + /* * This is a temporary object store created by the tmp_objdir * facility. Disable ref updates since the objects in the store * might be discarded on rollback. @@ -75,7 +83,6 @@ struct odb_source { }; struct packed_git; -struct multi_pack_index; struct cached_object_entry; /* @@ -119,13 +126,6 @@ struct object_database { /* * private data * - * should only be accessed directly by packfile.c and midx.c - */ - struct multi_pack_index *multi_pack_index; - - /* - * private data - * * should only be accessed directly by packfile.c */ diff --git a/pack-bitmap.c b/pack-bitmap.c index 15cf51166e..d14421ee20 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -683,13 +683,15 @@ static int open_pack_bitmap(struct repository *r, static int open_midx_bitmap(struct repository *r, struct bitmap_index *bitmap_git) { + struct odb_source *source; int ret = -1; - struct multi_pack_index *midx; assert(!bitmap_git->map); - for (midx = get_multi_pack_index(r); midx; midx = midx->next) { - if (!open_midx_bitmap_1(bitmap_git, midx)) + odb_prepare_alternates(r->objects); + for (source = r->objects->sources; source; source = source->next) { + struct multi_pack_index *midx = get_multi_pack_index(source); + if (midx && !open_midx_bitmap_1(bitmap_git, midx)) ret = 0; } return ret; @@ -3345,11 +3347,18 @@ static int verify_bitmap_file(const struct git_hash_algo *algop, int verify_bitmap_files(struct repository *r) { + struct odb_source *source; int res = 0; - for (struct multi_pack_index *m = get_multi_pack_index(r); - m; m = m->next) { - char *midx_bitmap_name = midx_bitmap_filename(m); + odb_prepare_alternates(r->objects); + for (source = r->objects->sources; source; source = source->next) { + struct multi_pack_index *m = get_multi_pack_index(source); + char *midx_bitmap_name; + + if (!m) + continue; + + midx_bitmap_name = midx_bitmap_filename(m); res |= verify_bitmap_file(r->hash_algo, midx_bitmap_name); free(midx_bitmap_name); } diff --git a/packfile.c b/packfile.c index af9ccfdba6..5d73932f50 100644 --- a/packfile.c +++ b/packfile.c @@ -361,6 +361,7 @@ void close_pack(struct packed_git *p) void close_object_store(struct object_database *o) { + struct odb_source *source; struct packed_git *p; for (p = o->packed_git; p; p = p->next) @@ -369,9 +370,10 @@ void close_object_store(struct object_database *o) else close_pack(p); - if (o->multi_pack_index) { - close_midx(o->multi_pack_index); - o->multi_pack_index = NULL; + for (source = o->sources; source; source = source->next) { + if (source->midx) + close_midx(source->midx); + source->midx = NULL; } close_commit_graph(o); @@ -933,22 +935,17 @@ static void prepare_pack(const char *full_name, size_t full_name_len, report_garbage(PACKDIR_FILE_GARBAGE, full_name); } -static void prepare_packed_git_one(struct repository *r, char *objdir, int local) +static void prepare_packed_git_one(struct odb_source *source, int local) { - struct prepare_pack_data data; struct string_list garbage = STRING_LIST_INIT_DUP; + struct prepare_pack_data data = { + .m = source->midx, + .r = source->odb->repo, + .garbage = &garbage, + .local = local, + }; - data.m = r->objects->multi_pack_index; - - /* look for the multi-pack-index for this object directory */ - while (data.m && strcmp(data.m->object_dir, objdir)) - data.m = data.m->next; - - data.r = r; - data.garbage = &garbage; - data.local = local; - - for_each_file_in_pack_dir(objdir, prepare_pack, &data); + for_each_file_in_pack_dir(source->path, prepare_pack, &data); report_pack_garbage(data.garbage); string_list_clear(data.garbage, 0); @@ -965,14 +962,18 @@ static void prepare_packed_git(struct repository *r); unsigned long repo_approximate_object_count(struct repository *r) { if (!r->objects->approximate_object_count_valid) { - unsigned long count; - struct multi_pack_index *m; + struct odb_source *source; + unsigned long count = 0; struct packed_git *p; prepare_packed_git(r); - count = 0; - for (m = get_multi_pack_index(r); m; m = m->next) - count += m->num_objects; + + for (source = r->objects->sources; source; source = source->next) { + struct multi_pack_index *m = get_multi_pack_index(source); + if (m) + count += m->num_objects; + } + for (p = r->objects->packed_git; p; p = p->next) { if (open_pack_index(p)) continue; @@ -1037,8 +1038,8 @@ static void prepare_packed_git(struct repository *r) odb_prepare_alternates(r->objects); for (source = r->objects->sources; source; source = source->next) { int local = (source == r->objects->sources); - prepare_multi_pack_index_one(r, source->path, local); - prepare_packed_git_one(r, source->path, local); + prepare_multi_pack_index_one(source, local); + prepare_packed_git_one(source, local); } rearrange_packed_git(r); @@ -1076,31 +1077,21 @@ struct packed_git *get_packed_git(struct repository *r) return r->objects->packed_git; } -struct multi_pack_index *get_multi_pack_index(struct repository *r) +struct multi_pack_index *get_multi_pack_index(struct odb_source *source) { - prepare_packed_git(r); - return r->objects->multi_pack_index; -} - -struct multi_pack_index *get_local_multi_pack_index(struct repository *r) -{ - struct multi_pack_index *m = get_multi_pack_index(r); - - /* no need to iterate; we always put the local one first (if any) */ - if (m && m->local) - return m; - - return NULL; + prepare_packed_git(source->odb->repo); + return source->midx; } struct packed_git *get_all_packs(struct repository *r) { - struct multi_pack_index *m; - prepare_packed_git(r); - for (m = r->objects->multi_pack_index; m; m = m->next) { - uint32_t i; - for (i = 0; i < m->num_packs + m->num_packs_in_base; i++) + + for (struct odb_source *source = r->objects->sources; source; source = source->next) { + struct multi_pack_index *m = source->midx; + if (!m) + continue; + for (uint32_t i = 0; i < m->num_packs + m->num_packs_in_base; i++) prepare_midx_pack(r, m, i); } @@ -2083,16 +2074,15 @@ static int fill_pack_entry(const struct object_id *oid, int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e) { struct list_head *pos; - struct multi_pack_index *m; prepare_packed_git(r); - if (!r->objects->packed_git && !r->objects->multi_pack_index) - return 0; - for (m = r->objects->multi_pack_index; m; m = m->next) { - if (fill_midx_entry(r, oid, e, m)) + for (struct odb_source *source = r->objects->sources; source; source = source->next) + if (source->midx && fill_midx_entry(r, oid, e, source->midx)) return 1; - } + + if (!r->objects->packed_git) + return 0; list_for_each(pos, &r->objects->packed_git_mru) { struct packed_git *p = list_entry(pos, struct packed_git, mru); diff --git a/packfile.h b/packfile.h index 53c3b7d3b4..f16753f2a9 100644 --- a/packfile.h +++ b/packfile.h @@ -147,8 +147,7 @@ void install_packed_git(struct repository *r, struct packed_git *pack); struct packed_git *get_packed_git(struct repository *r); struct list_head *get_packed_git_mru(struct repository *r); -struct multi_pack_index *get_multi_pack_index(struct repository *r); -struct multi_pack_index *get_local_multi_pack_index(struct repository *r); +struct multi_pack_index *get_multi_pack_index(struct odb_source *source); struct packed_git *get_all_packs(struct repository *r); /* diff --git a/prio-queue.c b/prio-queue.c index ec33ac27db..9748528ce6 100644 --- a/prio-queue.c +++ b/prio-queue.c @@ -58,22 +58,10 @@ void prio_queue_put(struct prio_queue *queue, void *thing) } } -void *prio_queue_get(struct prio_queue *queue) +static void sift_down_root(struct prio_queue *queue) { - void *result; size_t ix, child; - if (!queue->nr) - return NULL; - if (!queue->compare) - return queue->array[--queue->nr].data; /* LIFO */ - - result = queue->array[0].data; - if (!--queue->nr) - return result; - - queue->array[0] = queue->array[queue->nr]; - /* Push down the one at the root */ for (ix = 0; ix * 2 + 1 < queue->nr; ix = child) { child = ix * 2 + 1; /* left */ @@ -86,6 +74,23 @@ void *prio_queue_get(struct prio_queue *queue) swap(queue, child, ix); } +} + +void *prio_queue_get(struct prio_queue *queue) +{ + void *result; + + if (!queue->nr) + return NULL; + if (!queue->compare) + return queue->array[--queue->nr].data; /* LIFO */ + + result = queue->array[0].data; + if (!--queue->nr) + return result; + + queue->array[0] = queue->array[queue->nr]; + sift_down_root(queue); return result; } @@ -97,3 +102,17 @@ void *prio_queue_peek(struct prio_queue *queue) return queue->array[queue->nr - 1].data; return queue->array[0].data; } + +void prio_queue_replace(struct prio_queue *queue, void *thing) +{ + if (!queue->nr) { + prio_queue_put(queue, thing); + } else if (!queue->compare) { + queue->array[queue->nr - 1].ctr = queue->insertion_ctr++; + queue->array[queue->nr - 1].data = thing; + } else { + queue->array[0].ctr = queue->insertion_ctr++; + queue->array[0].data = thing; + sift_down_root(queue); + } +} diff --git a/prio-queue.h b/prio-queue.h index 38d032636d..da7fad2f1f 100644 --- a/prio-queue.h +++ b/prio-queue.h @@ -52,6 +52,14 @@ void *prio_queue_get(struct prio_queue *); */ void *prio_queue_peek(struct prio_queue *); +/* + * Replace the "thing" that compares the smallest with a new "thing", + * like prio_queue_get()+prio_queue_put() would do, but in a more + * efficient way. Does the same as prio_queue_put() if the queue is + * empty. + */ +void prio_queue_replace(struct prio_queue *queue, void *thing); + void clear_prio_queue(struct prio_queue *); /* Reverse the LIFO elements */ diff --git a/ref-filter.c b/ref-filter.c index f9f2c512a8..d5a146de87 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -2684,6 +2684,41 @@ static int filter_exclude_match(struct ref_filter *filter, const char *refname) } /* + * We need to seek to the reference right after a given marker but excluding any + * matching references. So we seek to the lexicographically next reference. + */ +static int start_ref_iterator_after(struct ref_iterator *iter, const char *marker) +{ + struct strbuf sb = STRBUF_INIT; + int ret; + + strbuf_addstr(&sb, marker); + strbuf_addch(&sb, 1); + + ret = ref_iterator_seek(iter, sb.buf, 0); + + strbuf_release(&sb); + return ret; +} + +static int for_each_fullref_with_seek(struct ref_filter *filter, each_ref_fn cb, + void *cb_data, unsigned int flags) +{ + struct ref_iterator *iter; + int ret = 0; + + iter = refs_ref_iterator_begin(get_main_ref_store(the_repository), "", + NULL, 0, flags); + if (filter->start_after) + ret = start_ref_iterator_after(iter, filter->start_after); + + if (ret) + return ret; + + return do_for_each_ref_iterator(iter, cb, cb_data); +} + +/* * This is the same as for_each_fullref_in(), but it tries to iterate * only over the patterns we'll care about. Note that it _doesn't_ do a full * pattern match, so the callback still has to match each ref individually. @@ -2694,8 +2729,8 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter, { if (filter->kind & FILTER_REFS_ROOT_REFS) { /* In this case, we want to print all refs including root refs. */ - return refs_for_each_include_root_refs(get_main_ref_store(the_repository), - cb, cb_data); + return for_each_fullref_with_seek(filter, cb, cb_data, + DO_FOR_EACH_INCLUDE_ROOT_REFS); } if (!filter->match_as_path) { @@ -2704,8 +2739,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter, * prefixes like "refs/heads/" etc. are stripped off, * so we have to look at everything: */ - return refs_for_each_fullref_in(get_main_ref_store(the_repository), - "", NULL, cb, cb_data); + return for_each_fullref_with_seek(filter, cb, cb_data, 0); } if (filter->ignore_case) { @@ -2714,14 +2748,12 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter, * so just return everything and let the caller * sort it out. */ - return refs_for_each_fullref_in(get_main_ref_store(the_repository), - "", NULL, cb, cb_data); + return for_each_fullref_with_seek(filter, cb, cb_data, 0); } if (!filter->name_patterns[0]) { /* no patterns; we have to look at everything */ - return refs_for_each_fullref_in(get_main_ref_store(the_repository), - "", filter->exclude.v, cb, cb_data); + return for_each_fullref_with_seek(filter, cb, cb_data, 0); } return refs_for_each_fullref_in_prefixes(get_main_ref_store(the_repository), @@ -3189,6 +3221,7 @@ void filter_is_base(struct repository *r, static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref_fn fn, void *cb_data) { + const char *prefix = NULL; int ret = 0; filter->kind = type & FILTER_REFS_KIND_MASK; @@ -3199,38 +3232,47 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref /* Simple per-ref filtering */ if (!filter->kind) die("filter_refs: invalid type"); - else { - /* - * For common cases where we need only branches or remotes or tags, - * we only iterate through those refs. If a mix of refs is needed, - * we iterate over all refs and filter out required refs with the help - * of filter_ref_kind(). - */ - if (filter->kind == FILTER_REFS_BRANCHES) - ret = refs_for_each_fullref_in(get_main_ref_store(the_repository), - "refs/heads/", NULL, - fn, cb_data); - else if (filter->kind == FILTER_REFS_REMOTES) - ret = refs_for_each_fullref_in(get_main_ref_store(the_repository), - "refs/remotes/", NULL, - fn, cb_data); - else if (filter->kind == FILTER_REFS_TAGS) - ret = refs_for_each_fullref_in(get_main_ref_store(the_repository), - "refs/tags/", NULL, fn, - cb_data); - else if (filter->kind & FILTER_REFS_REGULAR) - ret = for_each_fullref_in_pattern(filter, fn, cb_data); - /* - * When printing all ref types, HEAD is already included, - * so we don't want to print HEAD again. - */ - if (!ret && !(filter->kind & FILTER_REFS_ROOT_REFS) && - (filter->kind & FILTER_REFS_DETACHED_HEAD)) - refs_head_ref(get_main_ref_store(the_repository), fn, - cb_data); + /* + * For common cases where we need only branches or remotes or tags, + * we only iterate through those refs. If a mix of refs is needed, + * we iterate over all refs and filter out required refs with the help + * of filter_ref_kind(). + */ + if (filter->kind == FILTER_REFS_BRANCHES) + prefix = "refs/heads/"; + else if (filter->kind == FILTER_REFS_REMOTES) + prefix = "refs/remotes/"; + else if (filter->kind == FILTER_REFS_TAGS) + prefix = "refs/tags/"; + + if (prefix) { + struct ref_iterator *iter; + + iter = refs_ref_iterator_begin(get_main_ref_store(the_repository), + "", NULL, 0, 0); + + if (filter->start_after) + ret = start_ref_iterator_after(iter, filter->start_after); + else if (prefix) + ret = ref_iterator_seek(iter, prefix, 1); + + if (!ret) + ret = do_for_each_ref_iterator(iter, fn, cb_data); + } else if (filter->kind & FILTER_REFS_REGULAR) { + ret = for_each_fullref_in_pattern(filter, fn, cb_data); } + /* + * When printing all ref types, HEAD is already included, + * so we don't want to print HEAD again. + */ + if (!ret && !(filter->kind & FILTER_REFS_ROOT_REFS) && + (filter->kind & FILTER_REFS_DETACHED_HEAD)) + refs_head_ref(get_main_ref_store(the_repository), fn, + cb_data); + + clear_contains_cache(&filter->internal.contains_cache); clear_contains_cache(&filter->internal.no_contains_cache); diff --git a/ref-filter.h b/ref-filter.h index c98c4fbd4c..f22ca94b49 100644 --- a/ref-filter.h +++ b/ref-filter.h @@ -64,6 +64,7 @@ struct ref_array { struct ref_filter { const char **name_patterns; + const char *start_after; struct strvec exclude; struct oid_array points_at; struct commit_list *with_commit; @@ -81,6 +81,20 @@ int reflog_expire_config(const char *var, const char *value, return 0; } +void reflog_clear_expire_config(struct reflog_expire_options *opts) +{ + struct reflog_expire_entry_option *ent = opts->entries, *tmp; + + while (ent) { + tmp = ent; + ent = ent->next; + free(tmp); + } + + opts->entries = NULL; + opts->entries_tail = NULL; +} + void reflog_expire_options_set_refname(struct reflog_expire_options *cb, const char *ref) { @@ -34,6 +34,8 @@ struct reflog_expire_options { int reflog_expire_config(const char *var, const char *value, const struct config_context *ctx, void *cb); +void reflog_clear_expire_config(struct reflog_expire_options *opts); + /* * Adapt the options so that they apply to the given refname. This applies any * per-reference reflog expiry configuration that may exist to the options. @@ -2657,12 +2657,12 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs if (!initial_transaction) { int ok; - if (!iter) { + if (!iter) iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0, DO_FOR_EACH_INCLUDE_BROKEN); - } else if (ref_iterator_seek(iter, dirname.buf) < 0) { + else if (ref_iterator_seek(iter, dirname.buf, + REF_ITERATOR_SEEK_SET_PREFIX) < 0) goto cleanup; - } while ((ok = ref_iterator_advance(iter)) == ITER_OK) { if (skip && @@ -1194,4 +1194,159 @@ int repo_migrate_ref_storage_format(struct repository *repo, unsigned int flags, struct strbuf *err); +/* + * Reference iterators + * + * A reference iterator encapsulates the state of an in-progress + * iteration over references. Create an instance of `struct + * ref_iterator` via one of the functions in this module. + * + * A freshly-created ref_iterator doesn't yet point at a reference. To + * advance the iterator, call ref_iterator_advance(). If successful, + * this sets the iterator's refname, oid, and flags fields to describe + * the next reference and returns ITER_OK. The data pointed at by + * refname and oid belong to the iterator; if you want to retain them + * after calling ref_iterator_advance() again or calling + * ref_iterator_free(), you must make a copy. When the iteration has + * been exhausted, ref_iterator_advance() releases any resources + * associated with the iteration, frees the ref_iterator object, and + * returns ITER_DONE. If you want to abort the iteration early, call + * ref_iterator_free(), which also frees the ref_iterator object and + * any associated resources. If there was an internal error advancing + * to the next entry, ref_iterator_advance() aborts the iteration, + * frees the ref_iterator, and returns ITER_ERROR. + * + * The reference currently being looked at can be peeled by calling + * ref_iterator_peel(). This function is often faster than peel_ref(), + * so it should be preferred when iterating over references. + * + * Putting it all together, a typical iteration looks like this: + * + * int ok; + * struct ref_iterator *iter = ...; + * + * while ((ok = ref_iterator_advance(iter)) == ITER_OK) { + * if (want_to_stop_iteration()) { + * ok = ITER_DONE; + * break; + * } + * + * // Access information about the current reference: + * if (!(iter->flags & REF_ISSYMREF)) + * printf("%s is %s\n", iter->refname, oid_to_hex(iter->oid)); + * + * // If you need to peel the reference: + * ref_iterator_peel(iter, &oid); + * } + * + * if (ok != ITER_DONE) + * handle_error(); + * ref_iterator_free(iter); + */ +struct ref_iterator; + +/* + * These flags are passed to refs_ref_iterator_begin() (and do_for_each_ref(), + * which feeds it). + */ +enum do_for_each_ref_flags { + /* + * Include broken references in a do_for_each_ref*() iteration, which + * would normally be omitted. This includes both refs that point to + * missing objects (a true repository corruption), ones with illegal + * names (which we prefer not to expose to callers), as well as + * dangling symbolic refs (i.e., those that point to a non-existent + * ref; this is not a corruption, but as they have no valid oid, we + * omit them from normal iteration results). + */ + DO_FOR_EACH_INCLUDE_BROKEN = (1 << 0), + + /* + * Only include per-worktree refs in a do_for_each_ref*() iteration. + * Normally this will be used with a files ref_store, since that's + * where all reference backends will presumably store their + * per-worktree refs. + */ + DO_FOR_EACH_PER_WORKTREE_ONLY = (1 << 1), + + /* + * Omit dangling symrefs from output; this only has an effect with + * INCLUDE_BROKEN, since they are otherwise not included at all. + */ + DO_FOR_EACH_OMIT_DANGLING_SYMREFS = (1 << 2), + + /* + * Include root refs i.e. HEAD and pseudorefs along with the regular + * refs. + */ + DO_FOR_EACH_INCLUDE_ROOT_REFS = (1 << 3), +}; + +/* + * Return an iterator that goes over each reference in `refs` for + * which the refname begins with prefix. If trim is non-zero, then + * trim that many characters off the beginning of each refname. + * The output is ordered by refname. + */ +struct ref_iterator *refs_ref_iterator_begin( + struct ref_store *refs, + const char *prefix, const char **exclude_patterns, + int trim, enum do_for_each_ref_flags flags); + +/* + * Advance the iterator to the first or next item and return ITER_OK. + * If the iteration is exhausted, free the resources associated with + * the ref_iterator and return ITER_DONE. On errors, free the iterator + * resources and return ITER_ERROR. It is a bug to use ref_iterator or + * call this function again after it has returned ITER_DONE or + * ITER_ERROR. + */ +int ref_iterator_advance(struct ref_iterator *ref_iterator); + +enum ref_iterator_seek_flag { + /* + * When the REF_ITERATOR_SEEK_SET_PREFIX flag is set, the iterator's prefix is + * updated to match the provided string, affecting all subsequent iterations. If + * not, the iterator seeks to the specified reference and clears any previously + * set prefix. + */ + REF_ITERATOR_SEEK_SET_PREFIX = (1 << 0), +}; + +/* + * Seek the iterator to the first reference matching the given seek string. + * The seek string is matched as a literal string, without regard for path + * separators. If seek is NULL or the empty string, seek the iterator to the + * first reference again. + * + * This function is expected to behave as if a new ref iterator has been + * created, but allows reuse of existing iterators for optimization. + * + * Returns 0 on success, a negative error code otherwise. + */ +int ref_iterator_seek(struct ref_iterator *ref_iterator, const char *refname, + unsigned int flags); + +/* + * If possible, peel the reference currently being viewed by the + * iterator. Return 0 on success. + */ +int ref_iterator_peel(struct ref_iterator *ref_iterator, + struct object_id *peeled); + +/* Free the reference iterator and any associated resources. */ +void ref_iterator_free(struct ref_iterator *ref_iterator); + +/* + * The common backend for the for_each_*ref* functions. Call fn for + * each reference in iter. If the iterator itself ever returns + * ITER_ERROR, return -1. If fn ever returns a non-zero value, stop + * the iteration and return that value. Otherwise, return 0. In any + * case, free the iterator when done. This function is basically an + * adapter between the callback style of reference iteration and the + * iterator style. + */ +int do_for_each_ref_iterator(struct ref_iterator *iter, + each_ref_fn fn, void *cb_data); + #endif /* REFS_H */ diff --git a/refs/debug.c b/refs/debug.c index 485e3079d7..da300efaf3 100644 --- a/refs/debug.c +++ b/refs/debug.c @@ -170,12 +170,13 @@ static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator) } static int debug_ref_iterator_seek(struct ref_iterator *ref_iterator, - const char *prefix) + const char *refname, unsigned int flags) { struct debug_ref_iterator *diter = (struct debug_ref_iterator *)ref_iterator; - int res = diter->iter->vtable->seek(diter->iter, prefix); - trace_printf_key(&trace_refs, "iterator_seek: %s: %d\n", prefix ? prefix : "", res); + int res = diter->iter->vtable->seek(diter->iter, refname, flags); + trace_printf_key(&trace_refs, "iterator_seek: %s flags: %d: %d\n", + refname ? refname : "", flags, res); return res; } diff --git a/refs/files-backend.c b/refs/files-backend.c index 89ae4517a9..088b52c740 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -929,11 +929,11 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator) } static int files_ref_iterator_seek(struct ref_iterator *ref_iterator, - const char *prefix) + const char *refname, unsigned int flags) { struct files_ref_iterator *iter = (struct files_ref_iterator *)ref_iterator; - return ref_iterator_seek(iter->iter0, prefix); + return ref_iterator_seek(iter->iter0, refname, flags); } static int files_ref_iterator_peel(struct ref_iterator *ref_iterator, @@ -2316,7 +2316,8 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator) } static int files_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED, - const char *prefix UNUSED) + const char *refname UNUSED, + unsigned int flags UNUSED) { BUG("ref_iterator_seek() called for reflog_iterator"); } diff --git a/refs/iterator.c b/refs/iterator.c index 766d96e795..17ef841d8a 100644 --- a/refs/iterator.c +++ b/refs/iterator.c @@ -15,10 +15,10 @@ int ref_iterator_advance(struct ref_iterator *ref_iterator) return ref_iterator->vtable->advance(ref_iterator); } -int ref_iterator_seek(struct ref_iterator *ref_iterator, - const char *prefix) +int ref_iterator_seek(struct ref_iterator *ref_iterator, const char *refname, + unsigned int flags) { - return ref_iterator->vtable->seek(ref_iterator, prefix); + return ref_iterator->vtable->seek(ref_iterator, refname, flags); } int ref_iterator_peel(struct ref_iterator *ref_iterator, @@ -57,7 +57,8 @@ static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator UNUSED) } static int empty_ref_iterator_seek(struct ref_iterator *ref_iterator UNUSED, - const char *prefix UNUSED) + const char *refname UNUSED, + unsigned int flags UNUSED) { return 0; } @@ -224,7 +225,7 @@ error: } static int merge_ref_iterator_seek(struct ref_iterator *ref_iterator, - const char *prefix) + const char *refname, unsigned int flags) { struct merge_ref_iterator *iter = (struct merge_ref_iterator *)ref_iterator; @@ -234,11 +235,11 @@ static int merge_ref_iterator_seek(struct ref_iterator *ref_iterator, iter->iter0 = iter->iter0_owned; iter->iter1 = iter->iter1_owned; - ret = ref_iterator_seek(iter->iter0, prefix); + ret = ref_iterator_seek(iter->iter0, refname, flags); if (ret < 0) return ret; - ret = ref_iterator_seek(iter->iter1, prefix); + ret = ref_iterator_seek(iter->iter1, refname, flags); if (ret < 0) return ret; @@ -407,13 +408,16 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator) } static int prefix_ref_iterator_seek(struct ref_iterator *ref_iterator, - const char *prefix) + const char *refname, unsigned int flags) { struct prefix_ref_iterator *iter = (struct prefix_ref_iterator *)ref_iterator; - free(iter->prefix); - iter->prefix = xstrdup_or_null(prefix); - return ref_iterator_seek(iter->iter0, prefix); + + if (flags & REF_ITERATOR_SEEK_SET_PREFIX) { + free(iter->prefix); + iter->prefix = xstrdup_or_null(refname); + } + return ref_iterator_seek(iter->iter0, refname, flags); } static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator, diff --git a/refs/packed-backend.c b/refs/packed-backend.c index 7fd73a0e6d..5fa4ae6655 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -1004,19 +1004,23 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator) } static int packed_ref_iterator_seek(struct ref_iterator *ref_iterator, - const char *prefix) + const char *refname, unsigned int flags) { struct packed_ref_iterator *iter = (struct packed_ref_iterator *)ref_iterator; const char *start; - if (prefix && *prefix) - start = find_reference_location(iter->snapshot, prefix, 0); + if (refname && *refname) + start = find_reference_location(iter->snapshot, refname, 0); else start = iter->snapshot->start; - free(iter->prefix); - iter->prefix = xstrdup_or_null(prefix); + /* Unset any previously set prefix */ + FREE_AND_NULL(iter->prefix); + + if (flags & REF_ITERATOR_SEEK_SET_PREFIX) + iter->prefix = xstrdup_or_null(refname); + iter->pos = start; iter->eof = iter->snapshot->eof; @@ -1194,7 +1198,8 @@ static struct ref_iterator *packed_ref_iterator_begin( iter->repo = ref_store->repo; iter->flags = flags; - if (packed_ref_iterator_seek(&iter->base, prefix) < 0) { + if (packed_ref_iterator_seek(&iter->base, prefix, + REF_ITERATOR_SEEK_SET_PREFIX) < 0) { ref_iterator_free(&iter->base); return NULL; } diff --git a/refs/ref-cache.c b/refs/ref-cache.c index c1f1bab1d5..ceef3a2008 100644 --- a/refs/ref-cache.c +++ b/refs/ref-cache.c @@ -194,20 +194,6 @@ static struct ref_dir *find_containing_dir(struct ref_dir *dir, return dir; } -struct ref_entry *find_ref_entry(struct ref_dir *dir, const char *refname) -{ - int entry_index; - struct ref_entry *entry; - dir = find_containing_dir(dir, refname); - if (!dir) - return NULL; - entry_index = search_ref_dir(dir, refname, strlen(refname)); - if (entry_index == -1) - return NULL; - entry = dir->entries[entry_index]; - return (entry->flag & REF_DIR) ? NULL : entry; -} - /* * Emit a warning and return true iff ref1 and ref2 have the same name * and the same oid. Die if they have the same name but different @@ -448,11 +434,9 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) } } -static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator, - const char *prefix) +static int cache_ref_iterator_set_prefix(struct cache_ref_iterator *iter, + const char *prefix) { - struct cache_ref_iterator *iter = - (struct cache_ref_iterator *)ref_iterator; struct cache_ref_iterator_level *level; struct ref_dir *dir; @@ -483,6 +467,83 @@ static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator, return 0; } +static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *refname, unsigned int flags) +{ + struct cache_ref_iterator *iter = + (struct cache_ref_iterator *)ref_iterator; + + if (flags & REF_ITERATOR_SEEK_SET_PREFIX) { + return cache_ref_iterator_set_prefix(iter, refname); + } else if (refname && *refname) { + struct cache_ref_iterator_level *level; + const char *slash = refname; + struct ref_dir *dir; + + dir = get_ref_dir(iter->cache->root); + + if (iter->prime_dir) + prime_ref_dir(dir, refname); + + iter->levels_nr = 1; + level = &iter->levels[0]; + level->index = -1; + level->dir = dir; + + /* Unset any previously set prefix */ + FREE_AND_NULL(iter->prefix); + + /* + * Breakdown the provided seek path and assign the correct + * indexing to each level as needed. + */ + do { + int len, idx; + int cmp = 0; + + sort_ref_dir(dir); + + slash = strchr(slash, '/'); + len = slash ? slash - refname : (int)strlen(refname); + + for (idx = 0; idx < dir->nr; idx++) { + cmp = strncmp(refname, dir->entries[idx]->name, len); + if (cmp <= 0) + break; + } + /* don't overflow the index */ + idx = idx >= dir->nr ? dir->nr - 1 : idx; + + if (slash) + slash = slash + 1; + + level->index = idx; + if (dir->entries[idx]->flag & REF_DIR) { + /* push down a level */ + dir = get_ref_dir(dir->entries[idx]); + + ALLOC_GROW(iter->levels, iter->levels_nr + 1, + iter->levels_alloc); + level = &iter->levels[iter->levels_nr++]; + level->dir = dir; + level->index = -1; + level->prefix_state = PREFIX_CONTAINS_DIR; + } else { + /* reduce the index so the leaf node is iterated over */ + if (cmp <= 0 && !slash) + level->index = idx - 1; + /* + * while the seek path may not be exhausted, our + * match is exhausted at a leaf node. + */ + break; + } + } while (slash); + } + + return 0; +} + static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -523,7 +584,8 @@ struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache, iter->cache = cache; iter->prime_dir = prime_dir; - if (cache_ref_iterator_seek(&iter->base, prefix) < 0) { + if (cache_ref_iterator_seek(&iter->base, prefix, + REF_ITERATOR_SEEK_SET_PREFIX) < 0) { ref_iterator_free(&iter->base); return NULL; } diff --git a/refs/ref-cache.h b/refs/ref-cache.h index 5f04e518c3..f635d2d824 100644 --- a/refs/ref-cache.h +++ b/refs/ref-cache.h @@ -202,13 +202,6 @@ void free_ref_cache(struct ref_cache *cache); void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry); /* - * Find the value entry with the given name in dir, sorting ref_dirs - * and recursing into subdirectories as necessary. If the name is not - * found or it corresponds to a directory entry, return NULL. - */ -struct ref_entry *find_ref_entry(struct ref_dir *dir, const char *refname); - -/* * Start iterating over references in `cache`. If `prefix` is * specified, only include references whose names start with that * prefix. If `prime_dir` is true, then fill any incomplete diff --git a/refs/refs-internal.h b/refs/refs-internal.h index f868870851..40c1c0f93d 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -244,90 +244,8 @@ const char *find_descendant_ref(const char *dirname, #define SYMREF_MAXDEPTH 5 /* - * These flags are passed to refs_ref_iterator_begin() (and do_for_each_ref(), - * which feeds it). - */ -enum do_for_each_ref_flags { - /* - * Include broken references in a do_for_each_ref*() iteration, which - * would normally be omitted. This includes both refs that point to - * missing objects (a true repository corruption), ones with illegal - * names (which we prefer not to expose to callers), as well as - * dangling symbolic refs (i.e., those that point to a non-existent - * ref; this is not a corruption, but as they have no valid oid, we - * omit them from normal iteration results). - */ - DO_FOR_EACH_INCLUDE_BROKEN = (1 << 0), - - /* - * Only include per-worktree refs in a do_for_each_ref*() iteration. - * Normally this will be used with a files ref_store, since that's - * where all reference backends will presumably store their - * per-worktree refs. - */ - DO_FOR_EACH_PER_WORKTREE_ONLY = (1 << 1), - - /* - * Omit dangling symrefs from output; this only has an effect with - * INCLUDE_BROKEN, since they are otherwise not included at all. - */ - DO_FOR_EACH_OMIT_DANGLING_SYMREFS = (1 << 2), - - /* - * Include root refs i.e. HEAD and pseudorefs along with the regular - * refs. - */ - DO_FOR_EACH_INCLUDE_ROOT_REFS = (1 << 3), -}; - -/* - * Reference iterators - * - * A reference iterator encapsulates the state of an in-progress - * iteration over references. Create an instance of `struct - * ref_iterator` via one of the functions in this module. - * - * A freshly-created ref_iterator doesn't yet point at a reference. To - * advance the iterator, call ref_iterator_advance(). If successful, - * this sets the iterator's refname, oid, and flags fields to describe - * the next reference and returns ITER_OK. The data pointed at by - * refname and oid belong to the iterator; if you want to retain them - * after calling ref_iterator_advance() again or calling - * ref_iterator_free(), you must make a copy. When the iteration has - * been exhausted, ref_iterator_advance() releases any resources - * associated with the iteration, frees the ref_iterator object, and - * returns ITER_DONE. If you want to abort the iteration early, call - * ref_iterator_free(), which also frees the ref_iterator object and - * any associated resources. If there was an internal error advancing - * to the next entry, ref_iterator_advance() aborts the iteration, - * frees the ref_iterator, and returns ITER_ERROR. - * - * The reference currently being looked at can be peeled by calling - * ref_iterator_peel(). This function is often faster than peel_ref(), - * so it should be preferred when iterating over references. - * - * Putting it all together, a typical iteration looks like this: - * - * int ok; - * struct ref_iterator *iter = ...; - * - * while ((ok = ref_iterator_advance(iter)) == ITER_OK) { - * if (want_to_stop_iteration()) { - * ok = ITER_DONE; - * break; - * } - * - * // Access information about the current reference: - * if (!(iter->flags & REF_ISSYMREF)) - * printf("%s is %s\n", iter->refname, oid_to_hex(iter->oid)); - * - * // If you need to peel the reference: - * ref_iterator_peel(iter, &oid); - * } - * - * if (ok != ITER_DONE) - * handle_error(); - * ref_iterator_free(iter); + * Data structure for holding a reference iterator. See refs.h for + * more details and usage instructions. */ struct ref_iterator { struct ref_iterator_vtable *vtable; @@ -338,42 +256,6 @@ struct ref_iterator { }; /* - * Advance the iterator to the first or next item and return ITER_OK. - * If the iteration is exhausted, free the resources associated with - * the ref_iterator and return ITER_DONE. On errors, free the iterator - * resources and return ITER_ERROR. It is a bug to use ref_iterator or - * call this function again after it has returned ITER_DONE or - * ITER_ERROR. - */ -int ref_iterator_advance(struct ref_iterator *ref_iterator); - -/* - * Seek the iterator to the first reference with the given prefix. - * The prefix is matched as a literal string, without regard for path - * separators. If prefix is NULL or the empty string, seek the iterator to the - * first reference again. - * - * This function is expected to behave as if a new ref iterator with the same - * prefix had been created, but allows reuse of iterators and thus may allow - * the backend to optimize. Parameters other than the prefix that have been - * passed when creating the iterator will remain unchanged. - * - * Returns 0 on success, a negative error code otherwise. - */ -int ref_iterator_seek(struct ref_iterator *ref_iterator, - const char *prefix); - -/* - * If possible, peel the reference currently being viewed by the - * iterator. Return 0 on success. - */ -int ref_iterator_peel(struct ref_iterator *ref_iterator, - struct object_id *peeled); - -/* Free the reference iterator and any associated resources. */ -void ref_iterator_free(struct ref_iterator *ref_iterator); - -/* * An iterator over nothing (its first ref_iterator_advance() call * returns ITER_DONE). */ @@ -385,17 +267,6 @@ struct ref_iterator *empty_ref_iterator_begin(void); int is_empty_ref_iterator(struct ref_iterator *ref_iterator); /* - * Return an iterator that goes over each reference in `refs` for - * which the refname begins with prefix. If trim is non-zero, then - * trim that many characters off the beginning of each refname. - * The output is ordered by refname. - */ -struct ref_iterator *refs_ref_iterator_begin( - struct ref_store *refs, - const char *prefix, const char **exclude_patterns, - int trim, enum do_for_each_ref_flags flags); - -/* * A callback function used to instruct merge_ref_iterator how to * interleave the entries from iter0 and iter1. The function should * return one of the constants defined in enum iterator_selection. It @@ -482,11 +353,12 @@ void base_ref_iterator_init(struct ref_iterator *iter, typedef int ref_iterator_advance_fn(struct ref_iterator *ref_iterator); /* - * Seek the iterator to the first reference matching the given prefix. Should - * behave the same as if a new iterator was created with the same prefix. + * Seek the iterator to the first matching reference. If the + * REF_ITERATOR_SEEK_SET_PREFIX flag is set, it would behave the same as if a + * new iterator was created with the provided refname as prefix. */ typedef int ref_iterator_seek_fn(struct ref_iterator *ref_iterator, - const char *prefix); + const char *refname, unsigned int flags); /* * Peels the current ref, returning 0 for success or -1 for failure. @@ -520,18 +392,6 @@ struct ref_iterator_vtable { */ extern struct ref_iterator *current_ref_iter; -/* - * The common backend for the for_each_*ref* functions. Call fn for - * each reference in iter. If the iterator itself ever returns - * ITER_ERROR, return -1. If fn ever returns a non-zero value, stop - * the iteration and return that value. Otherwise, return 0. In any - * case, free the iterator when done. This function is basically an - * adapter between the callback style of reference iteration and the - * iterator style. - */ -int do_for_each_ref_iterator(struct ref_iterator *iter, - each_ref_fn fn, void *cb_data); - struct ref_store; /* refs backends */ diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index 4c3817f4ec..c3d48cc412 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -719,15 +719,20 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator) } static int reftable_ref_iterator_seek(struct ref_iterator *ref_iterator, - const char *prefix) + const char *refname, unsigned int flags) { struct reftable_ref_iterator *iter = (struct reftable_ref_iterator *)ref_iterator; - free(iter->prefix); - iter->prefix = xstrdup_or_null(prefix); - iter->prefix_len = prefix ? strlen(prefix) : 0; - iter->err = reftable_iterator_seek_ref(&iter->iter, prefix); + /* Unset any previously set prefix */ + FREE_AND_NULL(iter->prefix); + iter->prefix_len = 0; + + if (flags & REF_ITERATOR_SEEK_SET_PREFIX) { + iter->prefix = xstrdup_or_null(refname); + iter->prefix_len = refname ? strlen(refname) : 0; + } + iter->err = reftable_iterator_seek_ref(&iter->iter, refname); return iter->err; } @@ -839,7 +844,8 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_ if (ret) goto done; - ret = reftable_ref_iterator_seek(&iter->base, prefix); + ret = reftable_ref_iterator_seek(&iter->base, prefix, + REF_ITERATOR_SEEK_SET_PREFIX); if (ret) goto done; @@ -2042,7 +2048,8 @@ static int reftable_reflog_iterator_advance(struct ref_iterator *ref_iterator) } static int reftable_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED, - const char *prefix UNUSED) + const char *refname UNUSED, + unsigned int flags UNUSED) { BUG("reftable reflog iterator cannot be seeked"); return -1; diff --git a/revision.c b/revision.c index 212ca0de27..c2e17205a8 100644 --- a/revision.c +++ b/revision.c @@ -50,8 +50,6 @@ #include "parse-options.h" #include "wildmatch.h" -volatile show_early_output_fn_t show_early_output; - static char *term_bad; static char *term_good; @@ -1473,7 +1471,6 @@ static int limit_list(struct rev_info *revs) while (original_list) { struct commit *commit = pop_commit(&original_list); struct object *obj = &commit->object; - show_early_output_fn_t show; if (commit == interesting_cache) interesting_cache = NULL; @@ -1497,13 +1494,6 @@ static int limit_list(struct rev_info *revs) continue; date = commit->date; p = &commit_list_insert(commit, p)->next; - - show = show_early_output; - if (!show) - continue; - - show(revs, newlist); - show_early_output = NULL; } if (revs->cherry_pick || revs->cherry_mark) cherry_pick_list(newlist, revs); @@ -2437,13 +2427,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg } else if (!strcmp(arg, "--author-date-order")) { revs->sort_order = REV_SORT_BY_AUTHOR_DATE; revs->topo_order = 1; - } else if (!strcmp(arg, "--early-output")) { - revs->early_output = 100; - revs->topo_order = 1; - } else if (skip_prefix(arg, "--early-output=", &optarg)) { - if (strtoul_ui(optarg, 10, &revs->early_output) < 0) - die("'%s': not a non-negative integer", optarg); - revs->topo_order = 1; } else if (!strcmp(arg, "--parents")) { revs->rewrite_parents = 1; revs->print_parents = 1; diff --git a/revision.h b/revision.h index ac843f58d0..21e288c5ba 100644 --- a/revision.h +++ b/revision.h @@ -160,8 +160,6 @@ struct rev_info { /* topo-sort */ enum rev_sort_order sort_order; - unsigned int early_output; - unsigned int ignore_missing:1, ignore_missing_links:1; @@ -553,10 +551,4 @@ int rewrite_parents(struct rev_info *revs, */ struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit); -/** - * Global for the (undocumented) "--early-output" flag for "git log". - */ -typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *); -extern volatile show_early_output_fn_t show_early_output; - #endif diff --git a/t/Makefile b/t/Makefile index 791e0a0978..757674e727 100644 --- a/t/Makefile +++ b/t/Makefile @@ -125,7 +125,6 @@ check-meson: @mkdir -p mesontmp && \ printf "%s\n" \ "integration_tests t[0-9][0-9][0-9][0-9]-*.sh" \ - "unit_test_programs unit-tests/t-*.c" \ "clar_test_suites unit-tests/u-*.c" | \ while read -r variable pattern; do \ awk "/^$$variable = \[\$$/ {flag=1 ; next } /^]$$/ { flag=0 } flag { gsub(/^ \047/, \"\"); gsub(/\047,\$$/, \"\"); print }" meson.build >mesontmp/meson.txt && \ diff --git a/t/helper/test-delta.c b/t/helper/test-delta.c index 6bc787a474..52ea00c937 100644 --- a/t/helper/test-delta.c +++ b/t/helper/test-delta.c @@ -11,6 +11,7 @@ #include "test-tool.h" #include "git-compat-util.h" #include "delta.h" +#include "strbuf.h" static const char usage_str[] = "test-tool delta (-d|-p) <from_file> <data_file> <out_file>"; @@ -18,68 +19,38 @@ static const char usage_str[] = int cmd__delta(int argc, const char **argv) { int fd; - struct stat st; - void *from_buf = NULL, *data_buf = NULL, *out_buf = NULL; - unsigned long from_size, data_size, out_size; - int ret = 1; + struct strbuf from = STRBUF_INIT, data = STRBUF_INIT; + char *out_buf; + unsigned long out_size; - if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) { - fprintf(stderr, "usage: %s\n", usage_str); - return 1; - } + if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) + usage(usage_str); - fd = open(argv[2], O_RDONLY); - if (fd < 0 || fstat(fd, &st)) { - perror(argv[2]); - return 1; - } - from_size = st.st_size; - from_buf = xmalloc(from_size); - if (read_in_full(fd, from_buf, from_size) < 0) { - perror(argv[2]); - close(fd); - goto cleanup; - } - close(fd); - - fd = open(argv[3], O_RDONLY); - if (fd < 0 || fstat(fd, &st)) { - perror(argv[3]); - goto cleanup; - } - data_size = st.st_size; - data_buf = xmalloc(data_size); - if (read_in_full(fd, data_buf, data_size) < 0) { - perror(argv[3]); - close(fd); - goto cleanup; - } - close(fd); + if (strbuf_read_file(&from, argv[2], 0) < 0) + die_errno("unable to read '%s'", argv[2]); + if (strbuf_read_file(&data, argv[3], 0) < 0) + die_errno("unable to read '%s'", argv[3]); if (argv[1][1] == 'd') - out_buf = diff_delta(from_buf, from_size, - data_buf, data_size, + out_buf = diff_delta(from.buf, from.len, + data.buf, data.len, &out_size, 0); else - out_buf = patch_delta(from_buf, from_size, - data_buf, data_size, + out_buf = patch_delta(from.buf, from.len, + data.buf, data.len, &out_size); - if (!out_buf) { - fprintf(stderr, "delta operation failed (returned NULL)\n"); - goto cleanup; - } + if (!out_buf) + die("delta operation failed (returned NULL)"); - fd = open (argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666); - if (fd < 0 || write_in_full(fd, out_buf, out_size) < 0) { - perror(argv[4]); - goto cleanup; - } + fd = xopen(argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (write_in_full(fd, out_buf, out_size) < 0) + die_errno("write(%s)", argv[4]); + if (close(fd) < 0) + die_errno("close(%s)", argv[4]); - ret = 0; -cleanup: - free(from_buf); - free(data_buf); + strbuf_release(&from); + strbuf_release(&data); free(out_buf); - return ret; + return 0; } diff --git a/t/helper/test-truncate.c b/t/helper/test-truncate.c index 3931deaec7..2820cc7ed7 100644 --- a/t/helper/test-truncate.c +++ b/t/helper/test-truncate.c @@ -21,5 +21,8 @@ int cmd__truncate(int argc, const char **argv) if (ftruncate(fd, (off_t) sz) < 0) die_errno("failed to truncate file"); + + close(fd); + return 0; } diff --git a/t/meson.build b/t/meson.build index 1af289425d..09f3068f98 100644 --- a/t/meson.build +++ b/t/meson.build @@ -8,6 +8,14 @@ clar_test_suites = [ 'unit-tests/u-oidmap.c', 'unit-tests/u-oidtree.c', 'unit-tests/u-prio-queue.c', + 'unit-tests/u-reftable-basics.c', + 'unit-tests/u-reftable-block.c', + 'unit-tests/u-reftable-merged.c', + 'unit-tests/u-reftable-pq.c', + 'unit-tests/u-reftable-readwrite.c', + 'unit-tests/u-reftable-record.c', + 'unit-tests/u-reftable-stack.c', + 'unit-tests/u-reftable-table.c', 'unit-tests/u-reftable-tree.c', 'unit-tests/u-strbuf.c', 'unit-tests/u-strcmp-offset.c', @@ -20,7 +28,8 @@ clar_test_suites = [ clar_sources = [ 'unit-tests/clar/clar.c', 'unit-tests/unit-test.c', - 'unit-tests/lib-oid.c' + 'unit-tests/lib-oid.c', + 'unit-tests/lib-reftable.c' ] clar_decls_h = custom_target( @@ -54,33 +63,6 @@ clar_unit_tests = executable('unit-tests', ) test('unit-tests', clar_unit_tests, kwargs: test_kwargs) -unit_test_programs = [ - 'unit-tests/t-reftable-basics.c', - 'unit-tests/t-reftable-block.c', - 'unit-tests/t-reftable-merged.c', - 'unit-tests/t-reftable-pq.c', - 'unit-tests/t-reftable-readwrite.c', - 'unit-tests/t-reftable-record.c', - 'unit-tests/t-reftable-stack.c', - 'unit-tests/t-reftable-table.c', -] - -foreach unit_test_program : unit_test_programs - unit_test_name = fs.stem(unit_test_program) - unit_test = executable(unit_test_name, - sources: [ - 'unit-tests/test-lib.c', - 'unit-tests/lib-reftable.c', - unit_test_program, - ], - dependencies: [libgit_commonmain], - ) - test(unit_test_name, unit_test, - workdir: meson.current_source_dir(), - kwargs: test_kwargs, - ) -endforeach - subdir('helper') integration_tests = [ @@ -1116,6 +1098,7 @@ benchmarks = [ 'perf/p1450-fsck.sh', 'perf/p1451-fsck-skip-list.sh', 'perf/p1500-graph-walks.sh', + 'perf/p1501-rev-parse-oneline.sh', 'perf/p2000-sparse-operations.sh', 'perf/p3400-rebase.sh', 'perf/p3404-rebase-interactive.sh', @@ -1162,8 +1145,6 @@ benchmarks = [ # sufficient to catch missing test suites in our CI though. foreach glob, tests : { 't[0-9][0-9][0-9][0-9]-*.sh': integration_tests, - 'perf/p[0-9][0-9][0-9][0-9]-*.sh': benchmarks, - 'unit-tests/t-*.c': unit_test_programs, 'unit-tests/u-*.c': clar_test_suites, } actual_tests = run_command(shell, '-c', 'ls ' + glob, @@ -1230,4 +1211,4 @@ if perl.found() and time.found() timeout: 0, ) endforeach -endif +endif
\ No newline at end of file diff --git a/t/perf/p1501-rev-parse-oneline.sh b/t/perf/p1501-rev-parse-oneline.sh new file mode 100755 index 0000000000..538fa9c404 --- /dev/null +++ b/t/perf/p1501-rev-parse-oneline.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +test_description='Test :/ object name notation' + +. ./perf-lib.sh + +test_perf_fresh_repo + +# +# Creates lots of merges to make history traversal costly. In +# particular it creates 2^($max_level-1)-1 2-way merges on top of +# 2^($max_level-1) root commits. E.g., the commit history looks like +# this for a $max_level of 3: +# +# _1_ +# / \ +# 2 3 +# / \ / \ +# 4 5 6 7 +# +# The numbers are the fast-import marks, which also are the commit +# messages. 1 is the HEAD commit and a merge, 2 and 3 are also merges, +# 4-7 are the root commits. +# +build_history () { + local max_level="$1" && + local level="${2:-1}" && + local mark="${3:-1}" && + if test $level -eq $max_level + then + echo "reset refs/heads/master" && + echo "from $ZERO_OID" && + echo "commit refs/heads/master" && + echo "mark :$mark" && + echo "committer C <c@example.com> 1234567890 +0000" && + echo "data <<EOF" && + echo "$mark" && + echo "EOF" + else + local level1=$((level+1)) && + local mark1=$((2*mark)) && + local mark2=$((2*mark+1)) && + build_history $max_level $level1 $mark1 && + build_history $max_level $level1 $mark2 && + echo "commit refs/heads/master" && + echo "mark :$mark" && + echo "committer C <c@example.com> 1234567890 +0000" && + echo "data <<EOF" && + echo "$mark" && + echo "EOF" && + echo "from :$mark1" && + echo "merge :$mark2" + fi +} + +test_expect_success 'setup' ' + build_history 16 | git fast-import && + git log --format="%H %s" --reverse >commits && + sed -n -e "s/ .*$//p" -e "q" <commits >expect && + sed -n -e "s/^.* //p" -e "q" <commits >needle +' + +test_perf "rev-parse :/$(cat needle)" ' + git rev-parse :/$(cat needle) >actual +' + +test_expect_success 'verify result' ' + test_cmp expect actual +' + +test_done diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index 42b501f163..e30f87a358 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -673,4 +673,32 @@ test_expect_success 'reflog drop --all with reference' ' ) ' +test_expect_success 'expire with pattern config' ' + # Split refs/heads/ into two roots so we can apply config to each. Make + # two branches per root to verify that config is applied correctly + # multiple times. + git branch root1/branch1 && + git branch root1/branch2 && + git branch root2/branch1 && + git branch root2/branch2 && + + test_config "gc.reflogexpire" "never" && + test_config "gc.refs/heads/root2/*.reflogExpire" "now" && + git reflog expire \ + root1/branch1 root1/branch2 \ + root2/branch1 root2/branch2 && + + cat >expect <<-\EOF && + root1/branch1@{0} + root1/branch2@{0} + EOF + git log -g --branches="root*" --format=%gD >actual.raw && + # The sole reflog entry of each branch points to the same commit, so + # the order in which they are shown is nondeterministic. We just care + # about the what was expired (and what was not), so sort to get a known + # order. + sort <actual.raw >actual.sorted && + test_cmp expect actual.sorted +' + test_done diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index 26b42a526a..5d093e3a7a 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -394,6 +394,16 @@ test_expect_success 'autosquash with empty custom instructionFormat' ' ) ' +test_expect_success 'autosquash with invalid custom instructionFormat' ' + git reset --hard base && + test_commit invalid-instructionFormat-test && + ( + test_must_fail git -c rebase.instructionFormat=blah \ + rebase --autosquash --force-rebase -i HEAD^ && + test_path_is_missing .git/rebase-merge + ) +' + set_backup_editor () { write_script backup-editor.sh <<-\EOF cp "$1" .git/backup-"$(basename "$1")" diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index 127216f722..b8a8dd77e7 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -328,6 +328,19 @@ test_expect_success 'there is no --no-reschedule-failed-exec in an ongoing rebas test_expect_code 129 git rebase --edit-todo --no-reschedule-failed-exec ' +test_expect_success 'no change in comment character due to conflicts markers with core.commentChar=auto' ' + git checkout -b branch-a && + test_commit A F1 && + git checkout -b branch-b HEAD^ && + test_commit B F1 && + test_must_fail git rebase branch-a && + printf "B\nA\n" >F1 && + git add F1 && + GIT_EDITOR="cat >actual" git -c core.commentChar=auto rebase --continue && + # Check that "#" is still the comment character. + test_grep "^# Changes to be committed" actual +' + test_orig_head_helper () { test_when_finished 'git rebase --abort && git checkout topic && diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 63c9a8f04b..0e0019347e 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -472,6 +472,66 @@ test_expect_success 'pull --no-autostash & merge.autostash unset' ' test_pull_autostash_fail --no-autostash --no-rebase ' +test_expect_success 'pull succeeds with dirty working directory and pull.autostash=true' ' + test_config pull.autostash true && + test_pull_autostash 1 --rebase && + test_pull_autostash 2 --no-rebase && + test_pull_autostash 1 --autostash --rebase && + test_pull_autostash 2 --autostash --no-rebase +' + +test_expect_success 'pull fails with dirty working directory and pull.autostash=false' ' + test_config pull.autostash false && + test_pull_autostash_fail --rebase && + test_pull_autostash_fail --no-rebase && + test_pull_autostash_fail --no-autostash --rebase && + test_pull_autostash_fail --no-autostash --no-rebase +' + +test_expect_success 'pull --autostash overrides pull.autostash=false' ' + test_config pull.autostash false && + test_pull_autostash 1 --autostash --rebase && + test_pull_autostash 2 --autostash --no-rebase +' + +test_expect_success 'pull --no-autostash overrides pull.autostash=true' ' + test_config pull.autostash true && + test_pull_autostash_fail --no-autostash --rebase && + test_pull_autostash_fail --no-autostash --no-rebase +' + +test_expect_success 'pull.autostash=true overrides rebase.autostash' ' + test_config pull.autostash true && + test_config rebase.autostash true && + test_pull_autostash 1 --rebase && + test_config rebase.autostash false && + test_pull_autostash 1 --rebase +' + +test_expect_success 'pull.autostash=false overrides rebase.autostash' ' + test_config pull.autostash false && + test_config rebase.autostash true && + test_pull_autostash_fail --rebase && + test_config rebase.autostash false && + test_pull_autostash_fail --rebase +' + +test_expect_success 'pull.autostash=true overrides merge.autostash' ' + test_config pull.autostash true && + test_config merge.autostash true && + test_pull_autostash 2 --no-rebase && + test_config merge.autostash false && + test_pull_autostash 2 --no-rebase +' + +test_expect_success 'pull.autostash=false overrides merge.autostash' ' + test_config pull.autostash false && + test_config merge.autostash true && + test_pull_autostash_fail --no-rebase && + test_config merge.autostash false && + test_pull_autostash_fail --no-rebase +' + test_expect_success 'pull.rebase' ' git reset --hard before-rebase && test_config pull.rebase true && diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh index bb02b86c16..e097db6b02 100755 --- a/t/t6302-for-each-ref-filter.sh +++ b/t/t6302-for-each-ref-filter.sh @@ -541,4 +541,198 @@ test_expect_success 'validate worktree atom' ' test_cmp expect actual ' +test_expect_success 'start after with empty value' ' + cat >expect <<-\EOF && + refs/heads/main + refs/heads/main_worktree + refs/heads/side + refs/odd/spot + refs/tags/annotated-tag + refs/tags/doubly-annotated-tag + refs/tags/doubly-signed-tag + refs/tags/foo1.10 + refs/tags/foo1.3 + refs/tags/foo1.6 + refs/tags/four + refs/tags/one + refs/tags/signed-tag + refs/tags/three + refs/tags/two + EOF + git for-each-ref --format="%(refname)" --start-after="" >actual && + test_cmp expect actual +' + +test_expect_success 'start after a specific reference' ' + cat >expect <<-\EOF && + refs/tags/annotated-tag + refs/tags/doubly-annotated-tag + refs/tags/doubly-signed-tag + refs/tags/foo1.10 + refs/tags/foo1.3 + refs/tags/foo1.6 + refs/tags/four + refs/tags/one + refs/tags/signed-tag + refs/tags/three + refs/tags/two + EOF + git for-each-ref --format="%(refname)" --start-after=refs/odd/spot >actual && + test_cmp expect actual +' + +test_expect_success 'start after a specific reference with partial match' ' + cat >expect <<-\EOF && + refs/odd/spot + refs/tags/annotated-tag + refs/tags/doubly-annotated-tag + refs/tags/doubly-signed-tag + refs/tags/foo1.10 + refs/tags/foo1.3 + refs/tags/foo1.6 + refs/tags/four + refs/tags/one + refs/tags/signed-tag + refs/tags/three + refs/tags/two + EOF + git for-each-ref --format="%(refname)" --start-after=refs/odd/sp >actual && + test_cmp expect actual +' + +test_expect_success 'start after, just behind a specific reference' ' + cat >expect <<-\EOF && + refs/odd/spot + refs/tags/annotated-tag + refs/tags/doubly-annotated-tag + refs/tags/doubly-signed-tag + refs/tags/foo1.10 + refs/tags/foo1.3 + refs/tags/foo1.6 + refs/tags/four + refs/tags/one + refs/tags/signed-tag + refs/tags/three + refs/tags/two + EOF + git for-each-ref --format="%(refname)" --start-after=refs/odd/parrot >actual && + test_cmp expect actual +' + +test_expect_success 'start after with specific directory match' ' + cat >expect <<-\EOF && + refs/odd/spot + refs/tags/annotated-tag + refs/tags/doubly-annotated-tag + refs/tags/doubly-signed-tag + refs/tags/foo1.10 + refs/tags/foo1.3 + refs/tags/foo1.6 + refs/tags/four + refs/tags/one + refs/tags/signed-tag + refs/tags/three + refs/tags/two + EOF + git for-each-ref --format="%(refname)" --start-after=refs/odd >actual && + test_cmp expect actual +' + +test_expect_success 'start after with specific directory and trailing slash' ' + cat >expect <<-\EOF && + refs/odd/spot + refs/tags/annotated-tag + refs/tags/doubly-annotated-tag + refs/tags/doubly-signed-tag + refs/tags/foo1.10 + refs/tags/foo1.3 + refs/tags/foo1.6 + refs/tags/four + refs/tags/one + refs/tags/signed-tag + refs/tags/three + refs/tags/two + EOF + git for-each-ref --format="%(refname)" --start-after=refs/odd/ >actual && + test_cmp expect actual +' + +test_expect_success 'start after, just behind a specific directory' ' + cat >expect <<-\EOF && + refs/odd/spot + refs/tags/annotated-tag + refs/tags/doubly-annotated-tag + refs/tags/doubly-signed-tag + refs/tags/foo1.10 + refs/tags/foo1.3 + refs/tags/foo1.6 + refs/tags/four + refs/tags/one + refs/tags/signed-tag + refs/tags/three + refs/tags/two + EOF + git for-each-ref --format="%(refname)" --start-after=refs/lost >actual && + test_cmp expect actual +' + +test_expect_success 'start after, overflow specific reference length' ' + cat >expect <<-\EOF && + refs/tags/annotated-tag + refs/tags/doubly-annotated-tag + refs/tags/doubly-signed-tag + refs/tags/foo1.10 + refs/tags/foo1.3 + refs/tags/foo1.6 + refs/tags/four + refs/tags/one + refs/tags/signed-tag + refs/tags/three + refs/tags/two + EOF + git for-each-ref --format="%(refname)" --start-after=refs/odd/spotnew >actual && + test_cmp expect actual +' + +test_expect_success 'start after, overflow specific reference path' ' + cat >expect <<-\EOF && + refs/tags/annotated-tag + refs/tags/doubly-annotated-tag + refs/tags/doubly-signed-tag + refs/tags/foo1.10 + refs/tags/foo1.3 + refs/tags/foo1.6 + refs/tags/four + refs/tags/one + refs/tags/signed-tag + refs/tags/three + refs/tags/two + EOF + git for-each-ref --format="%(refname)" --start-after=refs/odd/spot/new >actual && + test_cmp expect actual +' + +test_expect_success 'start after, last reference' ' + cat >expect <<-\EOF && + EOF + git for-each-ref --format="%(refname)" --start-after=refs/tags/two >actual && + test_cmp expect actual +' + +test_expect_success 'start after used with a pattern' ' + cat >expect <<-\EOF && + fatal: cannot use --start-after with patterns + EOF + test_must_fail git for-each-ref --format="%(refname)" --start-after=refs/odd/spot refs/tags 2>actual && + test_cmp expect actual +' + +test_expect_success 'start after used with custom sort order' ' + cat >expect <<-\EOF && + fatal: cannot use --start-after with custom sort options + EOF + test_must_fail git for-each-ref --format="%(refname)" --start-after=refs/odd/spot --sort=author 2>actual && + test_cmp expect actual +' + test_done diff --git a/t/unit-tests/lib-reftable.c b/t/unit-tests/lib-reftable.c index 8a69612266..fdb5b11a20 100644 --- a/t/unit-tests/lib-reftable.c +++ b/t/unit-tests/lib-reftable.c @@ -1,12 +1,14 @@ -#define DISABLE_SIGN_COMPARE_WARNINGS - +#include "unit-test.h" #include "lib-reftable.h" -#include "test-lib.h" +#include "hex.h" +#include "parse-options.h" #include "reftable/constants.h" #include "reftable/writer.h" #include "strbuf.h" +#include "string-list.h" +#include "strvec.h" -void t_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id) +void cl_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id) { memset(p, (uint8_t)i, hash_size(id)); } @@ -22,17 +24,17 @@ static int strbuf_writer_flush(void *arg UNUSED) return 0; } -struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf, +struct reftable_writer *cl_reftable_strbuf_writer(struct reftable_buf *buf, struct reftable_write_options *opts) { struct reftable_writer *writer; int ret = reftable_writer_new(&writer, &strbuf_writer_write, &strbuf_writer_flush, buf, opts); - check(!ret); + cl_assert(!ret); return writer; } -void t_reftable_write_to_buf(struct reftable_buf *buf, +void cl_reftable_write_to_buf(struct reftable_buf *buf, struct reftable_ref_record *refs, size_t nrefs, struct reftable_log_record *logs, @@ -64,35 +66,36 @@ void t_reftable_write_to_buf(struct reftable_buf *buf, min = ui; } - writer = t_reftable_strbuf_writer(buf, &opts); - reftable_writer_set_limits(writer, min, max); + writer = cl_reftable_strbuf_writer(buf, &opts); + ret = reftable_writer_set_limits(writer, min, max); + cl_assert(!ret); if (nrefs) { ret = reftable_writer_add_refs(writer, refs, nrefs); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); } if (nlogs) { ret = reftable_writer_add_logs(writer, logs, nlogs); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); } ret = reftable_writer_close(writer); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); stats = reftable_writer_stats(writer); - for (size_t i = 0; i < stats->ref_stats.blocks; i++) { + for (size_t i = 0; i < (size_t)stats->ref_stats.blocks; i++) { size_t off = i * (opts.block_size ? opts.block_size : DEFAULT_BLOCK_SIZE); if (!off) off = header_size(opts.hash_id == REFTABLE_HASH_SHA256 ? 2 : 1); - check_char(buf->buf[off], ==, 'r'); + cl_assert(buf->buf[off] == 'r'); } if (nrefs) - check_int(stats->ref_stats.blocks, >, 0); + cl_assert(stats->ref_stats.blocks > 0); if (nlogs) - check_int(stats->log_stats.blocks, >, 0); + cl_assert(stats->log_stats.blocks > 0); reftable_writer_free(writer); } diff --git a/t/unit-tests/lib-reftable.h b/t/unit-tests/lib-reftable.h index e4c360fa7e..d7e6d3136f 100644 --- a/t/unit-tests/lib-reftable.h +++ b/t/unit-tests/lib-reftable.h @@ -1,21 +1,20 @@ -#ifndef LIB_REFTABLE_H -#define LIB_REFTABLE_H - +#include "git-compat-util.h" +#include "clar/clar.h" +#include "clar-decls.h" #include "git-compat-util.h" #include "reftable/reftable-writer.h" +#include "strbuf.h" struct reftable_buf; -void t_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id); +void cl_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id); -struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf, +struct reftable_writer *cl_reftable_strbuf_writer(struct reftable_buf *buf, struct reftable_write_options *opts); -void t_reftable_write_to_buf(struct reftable_buf *buf, +void cl_reftable_write_to_buf(struct reftable_buf *buf, struct reftable_ref_record *refs, size_t nrecords, struct reftable_log_record *logs, size_t nlogs, struct reftable_write_options *opts); - -#endif diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c deleted file mode 100644 index c9e751e49e..0000000000 --- a/t/unit-tests/t-reftable-basics.c +++ /dev/null @@ -1,219 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "test-lib.h" -#include "reftable/basics.h" - -struct integer_needle_lesseq_args { - int needle; - int *haystack; -}; - -static int integer_needle_lesseq(size_t i, void *_args) -{ - struct integer_needle_lesseq_args *args = _args; - return args->needle <= args->haystack[i]; -} - -static void *realloc_stub(void *p UNUSED, size_t size UNUSED) -{ - return NULL; -} - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - if_test ("binary search with binsearch works") { - int haystack[] = { 2, 4, 6, 8, 10 }; - struct { - int needle; - size_t expected_idx; - } testcases[] = { - {-9000, 0}, - {-1, 0}, - {0, 0}, - {2, 0}, - {3, 1}, - {4, 1}, - {7, 3}, - {9, 4}, - {10, 4}, - {11, 5}, - {9000, 5}, - }; - - for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) { - struct integer_needle_lesseq_args args = { - .haystack = haystack, - .needle = testcases[i].needle, - }; - size_t idx; - - idx = binsearch(ARRAY_SIZE(haystack), - &integer_needle_lesseq, &args); - check_int(idx, ==, testcases[i].expected_idx); - } - } - - if_test ("names_length returns size of a NULL-terminated string array") { - const char *a[] = { "a", "b", NULL }; - check_int(names_length(a), ==, 2); - } - - if_test ("names_equal compares NULL-terminated string arrays") { - const char *a[] = { "a", "b", "c", NULL }; - const char *b[] = { "a", "b", "d", NULL }; - const char *c[] = { "a", "b", NULL }; - - check(names_equal(a, a)); - check(!names_equal(a, b)); - check(!names_equal(a, c)); - } - - if_test ("parse_names works for basic input") { - char in1[] = "line\n"; - char in2[] = "a\nb\nc"; - char **out = parse_names(in1, strlen(in1)); - check(out != NULL); - check_str(out[0], "line"); - check(!out[1]); - free_names(out); - - out = parse_names(in2, strlen(in2)); - check(out != NULL); - check_str(out[0], "a"); - check_str(out[1], "b"); - check_str(out[2], "c"); - check(!out[3]); - free_names(out); - } - - if_test ("parse_names drops empty string") { - char in[] = "a\n\nb\n"; - char **out = parse_names(in, strlen(in)); - check(out != NULL); - check_str(out[0], "a"); - /* simply '\n' should be dropped as empty string */ - check_str(out[1], "b"); - check(!out[2]); - free_names(out); - } - - if_test ("common_prefix_size works") { - struct reftable_buf a = REFTABLE_BUF_INIT; - struct reftable_buf b = REFTABLE_BUF_INIT; - struct { - const char *a, *b; - int want; - } cases[] = { - {"abcdef", "abc", 3}, - { "abc", "ab", 2 }, - { "", "abc", 0 }, - { "abc", "abd", 2 }, - { "abc", "pqr", 0 }, - }; - - for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { - check(!reftable_buf_addstr(&a, cases[i].a)); - check(!reftable_buf_addstr(&b, cases[i].b)); - check_uint(common_prefix_size(&a, &b), ==, cases[i].want); - reftable_buf_reset(&a); - reftable_buf_reset(&b); - } - reftable_buf_release(&a); - reftable_buf_release(&b); - } - - if_test ("reftable_put_be64 and reftable_get_be64 work") { - uint64_t in = 0x1122334455667788; - uint8_t dest[8]; - uint64_t out; - reftable_put_be64(dest, in); - out = reftable_get_be64(dest); - check_int(in, ==, out); - } - - if_test ("reftable_put_be32 and reftable_get_be32 work") { - uint32_t in = 0x11223344; - uint8_t dest[4]; - uint32_t out; - reftable_put_be32(dest, in); - out = reftable_get_be32(dest); - check_int(in, ==, out); - } - - if_test ("reftable_put_be24 and reftable_get_be24 work") { - uint32_t in = 0x112233; - uint8_t dest[3]; - uint32_t out; - reftable_put_be24(dest, in); - out = reftable_get_be24(dest); - check_int(in, ==, out); - } - - if_test ("put_be16 and get_be16 work") { - uint32_t in = 0xfef1; - uint8_t dest[3]; - uint32_t out; - reftable_put_be16(dest, in); - out = reftable_get_be16(dest); - check_int(in, ==, out); - } - - if_test ("REFTABLE_ALLOC_GROW works") { - int *arr = NULL, *old_arr; - size_t alloc = 0, old_alloc; - - check(!REFTABLE_ALLOC_GROW(arr, 1, alloc)); - check(arr != NULL); - check_uint(alloc, >=, 1); - arr[0] = 42; - - old_alloc = alloc; - old_arr = arr; - reftable_set_alloc(NULL, realloc_stub, NULL); - check(REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc)); - check(arr == old_arr); - check_uint(alloc, ==, old_alloc); - - old_alloc = alloc; - reftable_set_alloc(NULL, NULL, NULL); - check(!REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc)); - check(arr != NULL); - check_uint(alloc, >, old_alloc); - arr[alloc - 1] = 42; - - reftable_free(arr); - } - - if_test ("REFTABLE_ALLOC_GROW_OR_NULL works") { - int *arr = NULL; - size_t alloc = 0, old_alloc; - - REFTABLE_ALLOC_GROW_OR_NULL(arr, 1, alloc); - check(arr != NULL); - check_uint(alloc, >=, 1); - arr[0] = 42; - - old_alloc = alloc; - REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc); - check(arr != NULL); - check_uint(alloc, >, old_alloc); - arr[alloc - 1] = 42; - - old_alloc = alloc; - reftable_set_alloc(NULL, realloc_stub, NULL); - REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc); - check(arr == NULL); - check_uint(alloc, ==, 0); - reftable_set_alloc(NULL, NULL, NULL); - - reftable_free(arr); - } - - return test_done(); -} diff --git a/t/unit-tests/u-prio-queue.c b/t/unit-tests/u-prio-queue.c index 145e689c9c..63e58114ae 100644 --- a/t/unit-tests/u-prio-queue.c +++ b/t/unit-tests/u-prio-queue.c @@ -13,6 +13,7 @@ static int intcmp(const void *va, const void *vb, void *data UNUSED) #define STACK -3 #define GET -4 #define REVERSE -5 +#define REPLACE -6 static int show(int *v) { @@ -51,6 +52,15 @@ static void test_prio_queue(int *input, size_t input_size, case REVERSE: prio_queue_reverse(&pq); break; + case REPLACE: + peek = prio_queue_peek(&pq); + cl_assert(i + 1 < input_size); + cl_assert(input[i + 1] >= 0); + cl_assert(j < result_size); + cl_assert_equal_i(result[j], show(peek)); + j++; + prio_queue_replace(&pq, &input[++i]); + break; default: prio_queue_put(&pq, &input[i]); break; @@ -81,6 +91,13 @@ void test_prio_queue__empty(void) ((int []){ 1, 2, MISSING, 1, 2, MISSING })); } +void test_prio_queue__replace(void) +{ + TEST_INPUT(((int []){ REPLACE, 6, 2, 4, REPLACE, 5, 7, GET, + REPLACE, 1, DUMP }), + ((int []){ MISSING, 2, 4, 5, 1, 6, 7 })); +} + void test_prio_queue__stack(void) { TEST_INPUT(((int []){ STACK, 8, 1, 5, 4, 6, 2, 3, DUMP }), @@ -92,3 +109,9 @@ void test_prio_queue__reverse_stack(void) TEST_INPUT(((int []){ STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP }), ((int []){ 1, 2, 3, 4, 5, 6 })); } + +void test_prio_queue__replace_stack(void) +{ + TEST_INPUT(((int []){ STACK, 8, 1, 5, REPLACE, 4, 6, 2, 3, DUMP }), + ((int []){ 5, 3, 2, 6, 4, 1, 8 })); +} diff --git a/t/unit-tests/u-reftable-basics.c b/t/unit-tests/u-reftable-basics.c new file mode 100644 index 0000000000..a0471083e7 --- /dev/null +++ b/t/unit-tests/u-reftable-basics.c @@ -0,0 +1,227 @@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "unit-test.h" +#include "lib-reftable.h" +#include "reftable/basics.h" + +struct integer_needle_lesseq_args { + int needle; + int *haystack; +}; + +static int integer_needle_lesseq(size_t i, void *_args) +{ + struct integer_needle_lesseq_args *args = _args; + return args->needle <= args->haystack[i]; +} + +static void *realloc_stub(void *p UNUSED, size_t size UNUSED) +{ + return NULL; +} + +void test_reftable_basics__binsearch(void) +{ + int haystack[] = { 2, 4, 6, 8, 10 }; + struct { + int needle; + size_t expected_idx; + } testcases[] = { + {-9000, 0}, + {-1, 0}, + {0, 0}, + {2, 0}, + {3, 1}, + {4, 1}, + {7, 3}, + {9, 4}, + {10, 4}, + {11, 5}, + {9000, 5}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) { + struct integer_needle_lesseq_args args = { + .haystack = haystack, + .needle = testcases[i].needle, + }; + size_t idx; + + idx = binsearch(ARRAY_SIZE(haystack), + &integer_needle_lesseq, &args); + cl_assert_equal_i(idx, testcases[i].expected_idx); + } +} + +void test_reftable_basics__names_length(void) +{ + const char *a[] = { "a", "b", NULL }; + cl_assert_equal_i(names_length(a), 2); +} + +void test_reftable_basics__names_equal(void) +{ + const char *a[] = { "a", "b", "c", NULL }; + const char *b[] = { "a", "b", "d", NULL }; + const char *c[] = { "a", "b", NULL }; + + cl_assert(names_equal(a, a)); + cl_assert(!names_equal(a, b)); + cl_assert(!names_equal(a, c)); +} + +void test_reftable_basics__parse_names(void) +{ + char in1[] = "line\n"; + char in2[] = "a\nb\nc"; + char **out = parse_names(in1, strlen(in1)); + cl_assert(out != NULL); + cl_assert_equal_s(out[0], "line"); + cl_assert(!out[1]); + free_names(out); + + out = parse_names(in2, strlen(in2)); + cl_assert(out != NULL); + cl_assert_equal_s(out[0], "a"); + cl_assert_equal_s(out[1], "b"); + cl_assert_equal_s(out[2], "c"); + cl_assert(!out[3]); + free_names(out); +} + +void test_reftable_basics__parse_names_drop_empty_string(void) +{ + char in[] = "a\n\nb\n"; + char **out = parse_names(in, strlen(in)); + cl_assert(out != NULL); + cl_assert_equal_s(out[0], "a"); + /* simply '\n' should be dropped as empty string */ + cl_assert_equal_s(out[1], "b"); + cl_assert(out[2] == NULL); + free_names(out); +} + +void test_reftable_basics__common_prefix_size(void) +{ + struct reftable_buf a = REFTABLE_BUF_INIT; + struct reftable_buf b = REFTABLE_BUF_INIT; + struct { + const char *a, *b; + int want; + } cases[] = { + {"abcdef", "abc", 3}, + { "abc", "ab", 2 }, + { "", "abc", 0 }, + { "abc", "abd", 2 }, + { "abc", "pqr", 0 }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { + cl_assert_equal_i(reftable_buf_addstr(&a, cases[i].a), 0); + cl_assert_equal_i(reftable_buf_addstr(&b, cases[i].b), 0); + cl_assert_equal_i(common_prefix_size(&a, &b), cases[i].want); + reftable_buf_reset(&a); + reftable_buf_reset(&b); + } + reftable_buf_release(&a); + reftable_buf_release(&b); +} + +void test_reftable_basics__put_get_be64(void) +{ + uint64_t in = 0x1122334455667788; + uint8_t dest[8]; + uint64_t out; + reftable_put_be64(dest, in); + out = reftable_get_be64(dest); + cl_assert(in == out); +} + +void test_reftable_basics__put_get_be32(void) +{ + uint32_t in = 0x11223344; + uint8_t dest[4]; + uint32_t out; + reftable_put_be32(dest, in); + out = reftable_get_be32(dest); + cl_assert_equal_i(in, out); +} + +void test_reftable_basics__put_get_be24(void) +{ + uint32_t in = 0x112233; + uint8_t dest[3]; + uint32_t out; + reftable_put_be24(dest, in); + out = reftable_get_be24(dest); + cl_assert_equal_i(in, out); +} + +void test_reftable_basics__put_get_be16(void) +{ + uint32_t in = 0xfef1; + uint8_t dest[3]; + uint32_t out; + reftable_put_be16(dest, in); + out = reftable_get_be16(dest); + cl_assert_equal_i(in, out); +} + +void test_reftable_basics__alloc_grow(void) +{ + int *arr = NULL, *old_arr; + size_t alloc = 0, old_alloc; + + cl_assert_equal_i(REFTABLE_ALLOC_GROW(arr, 1, alloc), 0); + cl_assert(arr != NULL); + cl_assert(alloc >= 1); + arr[0] = 42; + + old_alloc = alloc; + old_arr = arr; + reftable_set_alloc(NULL, realloc_stub, NULL); + cl_assert(REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc)); + cl_assert(arr == old_arr); + cl_assert_equal_i(alloc, old_alloc); + + old_alloc = alloc; + reftable_set_alloc(NULL, NULL, NULL); + cl_assert_equal_i(REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc), 0); + cl_assert(arr != NULL); + cl_assert(alloc > old_alloc); + arr[alloc - 1] = 42; + + reftable_free(arr); +} + +void test_reftable_basics__alloc_grow_or_null(void) +{ + int *arr = NULL; + size_t alloc = 0, old_alloc; + + REFTABLE_ALLOC_GROW_OR_NULL(arr, 1, alloc); + cl_assert(arr != NULL); + cl_assert(alloc >= 1); + arr[0] = 42; + + old_alloc = alloc; + REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc); + cl_assert(arr != NULL); + cl_assert(alloc > old_alloc); + arr[alloc - 1] = 42; + + old_alloc = alloc; + reftable_set_alloc(NULL, realloc_stub, NULL); + REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc); + cl_assert(arr == NULL); + cl_assert_equal_i(alloc, 0); + reftable_set_alloc(NULL, NULL, NULL); + + reftable_free(arr); +} diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/u-reftable-block.c index 52f1dae1c9..f4bded7d26 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/u-reftable-block.c @@ -6,14 +6,15 @@ license that can be found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd */ -#include "test-lib.h" +#include "unit-test.h" +#include "lib-reftable.h" #include "reftable/block.h" #include "reftable/blocksource.h" #include "reftable/constants.h" #include "reftable/reftable-error.h" #include "strbuf.h" -static void t_ref_block_read_write(void) +void test_reftable_block__read_write(void) { const int header_off = 21; /* random */ struct reftable_record recs[30]; @@ -34,17 +35,18 @@ static void t_ref_block_read_write(void) struct reftable_buf block_data = REFTABLE_BUF_INIT; REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); - check(block_data.buf != NULL); + cl_assert(block_data.buf != NULL); block_data.len = block_size; - ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_REF, (uint8_t *) block_data.buf, block_size, + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_REF, + (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); - check(!ret); + cl_assert(!ret); rec.u.ref.refname = (char *) ""; rec.u.ref.value_type = REFTABLE_REF_DELETION; ret = block_writer_add(&bw, &rec); - check_int(ret, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(ret, REFTABLE_API_ERROR); for (i = 0; i < N; i++) { rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); @@ -55,11 +57,11 @@ static void t_ref_block_read_write(void) ret = block_writer_add(&bw, &rec); rec.u.ref.refname = NULL; rec.u.ref.value_type = REFTABLE_REF_DELETION; - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); } ret = block_writer_finish(&bw); - check_int(ret, >, 0); + cl_assert(ret > 0); block_writer_release(&bw); @@ -71,32 +73,32 @@ static void t_ref_block_read_write(void) for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); - check_int(ret, >=, 0); + cl_assert(ret >= 0); if (ret > 0) { - check_int(i, ==, N); + cl_assert_equal_i(i, N); break; } - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); } for (i = 0; i < N; i++) { reftable_record_key(&recs[i], &want); ret = block_iter_seek_key(&it, &want); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); want.len--; ret = block_iter_seek_key(&it, &want); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); - check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(ret, 0); + cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1); } reftable_block_release(&block); @@ -108,7 +110,7 @@ static void t_ref_block_read_write(void) reftable_record_release(&recs[i]); } -static void t_log_block_read_write(void) +void test_reftable_block__log_read_write(void) { const int header_off = 21; struct reftable_record recs[30]; @@ -129,12 +131,12 @@ static void t_log_block_read_write(void) struct reftable_buf block_data = REFTABLE_BUF_INIT; REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); - check(block_data.buf != NULL); + cl_assert(block_data.buf != NULL); block_data.len = block_size; ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_LOG, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); - check(!ret); + cl_assert(!ret); for (i = 0; i < N; i++) { rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i); @@ -145,11 +147,11 @@ static void t_log_block_read_write(void) ret = block_writer_add(&bw, &rec); rec.u.log.refname = NULL; rec.u.log.value_type = REFTABLE_LOG_DELETION; - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); } ret = block_writer_finish(&bw); - check_int(ret, >, 0); + cl_assert(ret > 0); block_writer_release(&bw); @@ -161,33 +163,33 @@ static void t_log_block_read_write(void) for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); - check_int(ret, >=, 0); + cl_assert(ret >= 0); if (ret > 0) { - check_int(i, ==, N); + cl_assert_equal_i(i, N); break; } - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); } for (i = 0; i < N; i++) { reftable_buf_reset(&want); - check(!reftable_buf_addstr(&want, recs[i].u.log.refname)); + cl_assert(reftable_buf_addstr(&want, recs[i].u.log.refname) == 0); ret = block_iter_seek_key(&it, &want); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); want.len--; ret = block_iter_seek_key(&it, &want); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); - check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(ret, 0); + cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1); } reftable_block_release(&block); @@ -199,7 +201,7 @@ static void t_log_block_read_write(void) reftable_record_release(&recs[i]); } -static void t_obj_block_read_write(void) +void test_reftable_block__obj_read_write(void) { const int header_off = 21; struct reftable_record recs[30]; @@ -220,12 +222,12 @@ static void t_obj_block_read_write(void) struct reftable_buf block_data = REFTABLE_BUF_INIT; REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); - check(block_data.buf != NULL); + cl_assert(block_data.buf != NULL); block_data.len = block_size; ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_OBJ, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); - check(!ret); + cl_assert(!ret); for (i = 0; i < N; i++) { uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated; @@ -238,11 +240,11 @@ static void t_obj_block_read_write(void) ret = block_writer_add(&bw, &rec); rec.u.obj.hash_prefix = NULL; rec.u.obj.hash_prefix_len = 0; - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); } ret = block_writer_finish(&bw); - check_int(ret, >, 0); + cl_assert(ret > 0); block_writer_release(&bw); @@ -254,24 +256,24 @@ static void t_obj_block_read_write(void) for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); - check_int(ret, >=, 0); + cl_assert(ret >= 0); if (ret > 0) { - check_int(i, ==, N); + cl_assert_equal_i(i, N); break; } - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); } for (i = 0; i < N; i++) { reftable_record_key(&recs[i], &want); ret = block_iter_seek_key(&it, &want); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); } reftable_block_release(&block); @@ -283,7 +285,7 @@ static void t_obj_block_read_write(void) reftable_record_release(&recs[i]); } -static void t_index_block_read_write(void) +void test_reftable_block__ref_read_write(void) { const int header_off = 21; struct reftable_record recs[30]; @@ -305,12 +307,12 @@ static void t_index_block_read_write(void) struct reftable_buf block_data = REFTABLE_BUF_INIT; REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); - check(block_data.buf != NULL); + cl_assert(block_data.buf != NULL); block_data.len = block_size; ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_INDEX, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); - check(!ret); + cl_assert(!ret); for (i = 0; i < N; i++) { char buf[128]; @@ -319,15 +321,15 @@ static void t_index_block_read_write(void) reftable_buf_init(&recs[i].u.idx.last_key); recs[i].type = REFTABLE_BLOCK_TYPE_INDEX; - check(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf)); + cl_assert(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf)); recs[i].u.idx.offset = i; ret = block_writer_add(&bw, &recs[i]); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); } ret = block_writer_finish(&bw); - check_int(ret, >, 0); + cl_assert(ret > 0); block_writer_release(&bw); @@ -339,32 +341,32 @@ static void t_index_block_read_write(void) for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); - check_int(ret, >=, 0); + cl_assert(ret >= 0); if (ret > 0) { - check_int(i, ==, N); + cl_assert_equal_i(i, N); break; } - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); } for (i = 0; i < N; i++) { reftable_record_key(&recs[i], &want); ret = block_iter_seek_key(&it, &want); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); want.len--; ret = block_iter_seek_key(&it, &want); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); - check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(ret, 0); + cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1); } reftable_block_release(&block); @@ -376,7 +378,7 @@ static void t_index_block_read_write(void) reftable_record_release(&recs[i]); } -static void t_block_iterator(void) +void test_reftable_block__iterator(void) { struct reftable_block_source source = { 0 }; struct block_writer writer = { @@ -391,11 +393,12 @@ static void t_block_iterator(void) data.len = 1024; REFTABLE_CALLOC_ARRAY(data.buf, data.len); - check(data.buf != NULL); + cl_assert(data.buf != NULL); - err = block_writer_init(&writer, REFTABLE_BLOCK_TYPE_REF, (uint8_t *) data.buf, data.len, + err = block_writer_init(&writer, REFTABLE_BLOCK_TYPE_REF, + (uint8_t *) data.buf, data.len, 0, hash_size(REFTABLE_HASH_SHA1)); - check(!err); + cl_assert(!err); for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) { expected_refs[i] = (struct reftable_record) { @@ -408,42 +411,42 @@ static void t_block_iterator(void) memset(expected_refs[i].u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1); err = block_writer_add(&writer, &expected_refs[i]); - check_int(err, ==, 0); + cl_assert_equal_i(err, 0); } err = block_writer_finish(&writer); - check_int(err, >, 0); + cl_assert(err > 0); block_source_from_buf(&source, &data); reftable_block_init(&block, &source, 0, 0, data.len, REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF); err = reftable_block_init_iterator(&block, &it); - check_int(err, ==, 0); + cl_assert_equal_i(err, 0); for (size_t i = 0; ; i++) { err = reftable_iterator_next_ref(&it, &ref); if (err > 0) { - check_int(i, ==, ARRAY_SIZE(expected_refs)); + cl_assert_equal_i(i, ARRAY_SIZE(expected_refs)); break; } - check_int(err, ==, 0); + cl_assert_equal_i(err, 0); - check(reftable_ref_record_equal(&ref, &expected_refs[i].u.ref, - REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_ref_record_equal(&ref, + &expected_refs[i].u.ref, REFTABLE_HASH_SIZE_SHA1)); } err = reftable_iterator_seek_ref(&it, "refs/heads/does-not-exist"); - check_int(err, ==, 0); + cl_assert_equal_i(err, 0); err = reftable_iterator_next_ref(&it, &ref); - check_int(err, ==, 1); + cl_assert_equal_i(err, 1); err = reftable_iterator_seek_ref(&it, "refs/heads/branch-13"); - check_int(err, ==, 0); + cl_assert_equal_i(err, 0); err = reftable_iterator_next_ref(&it, &ref); - check_int(err, ==, 0); - check(reftable_ref_record_equal(&ref, &expected_refs[13].u.ref, - REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(err, 0); + cl_assert(reftable_ref_record_equal(&ref, + &expected_refs[13].u.ref,REFTABLE_HASH_SIZE_SHA1)); for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) reftable_free(expected_refs[i].u.ref.refname); @@ -453,14 +456,3 @@ static void t_block_iterator(void) block_writer_release(&writer); reftable_buf_release(&data); } - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_index_block_read_write(), "read-write operations on index blocks work"); - TEST(t_log_block_read_write(), "read-write operations on log blocks work"); - TEST(t_obj_block_read_write(), "read-write operations on obj blocks work"); - TEST(t_ref_block_read_write(), "read-write operations on ref blocks work"); - TEST(t_block_iterator(), "block iterator works"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/u-reftable-merged.c index 18c3251a56..54cb7fc2a7 100644 --- a/t/unit-tests/t-reftable-merged.c +++ b/t/unit-tests/u-reftable-merged.c @@ -6,7 +6,7 @@ license that can be found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd */ -#include "test-lib.h" +#include "unit-test.h" #include "lib-reftable.h" #include "reftable/blocksource.h" #include "reftable/constants.h" @@ -29,21 +29,21 @@ merged_table_from_records(struct reftable_ref_record **refs, int err; REFTABLE_CALLOC_ARRAY(*tables, n); - check(*tables != NULL); + cl_assert(*tables != NULL); REFTABLE_CALLOC_ARRAY(*source, n); - check(*source != NULL); + cl_assert(*source != NULL); for (size_t i = 0; i < n; i++) { - t_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts); + cl_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts); block_source_from_buf(&(*source)[i], &buf[i]); err = reftable_table_new(&(*tables)[i], &(*source)[i], "name"); - check(!err); + cl_assert(!err); } err = reftable_merged_table_new(&mt, *tables, n, REFTABLE_HASH_SHA1); - check(!err); + cl_assert(!err); return mt; } @@ -54,7 +54,7 @@ static void tables_destroy(struct reftable_table **tables, const size_t n) reftable_free(tables); } -static void t_merged_single_record(void) +void test_reftable_merged__single_record(void) { struct reftable_ref_record r1[] = { { .refname = (char *) "b", @@ -85,13 +85,14 @@ static void t_merged_single_record(void) int err; err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, "a"); - check(!err); + cl_assert(!err); err = reftable_iterator_next_ref(&it, &ref); - check(!err); - check(reftable_ref_record_equal(&r2[0], &ref, REFTABLE_HASH_SIZE_SHA1)); + cl_assert(!err); + cl_assert(reftable_ref_record_equal(&r2[0], &ref, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_ref_record_release(&ref); reftable_iterator_destroy(&it); tables_destroy(tables, 3); @@ -101,7 +102,7 @@ static void t_merged_single_record(void) reftable_free(bs); } -static void t_merged_refs(void) +void test_reftable_merged__refs(void) { struct reftable_ref_record r1[] = { { @@ -165,12 +166,12 @@ static void t_merged_refs(void) size_t i; err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, "a"); - check(!err); - check_int(reftable_merged_table_hash_id(mt), ==, REFTABLE_HASH_SHA1); - check_int(reftable_merged_table_min_update_index(mt), ==, 1); - check_int(reftable_merged_table_max_update_index(mt), ==, 3); + cl_assert(err == 0); + cl_assert_equal_i(reftable_merged_table_hash_id(mt), REFTABLE_HASH_SHA1); + cl_assert_equal_i(reftable_merged_table_min_update_index(mt), 1); + cl_assert_equal_i(reftable_merged_table_max_update_index(mt), 3); while (len < 100) { /* cap loops/recursion. */ struct reftable_ref_record ref = { 0 }; @@ -178,15 +179,15 @@ static void t_merged_refs(void) if (err > 0) break; - check(!REFTABLE_ALLOC_GROW(out, len + 1, cap)); + cl_assert(REFTABLE_ALLOC_GROW(out, len + 1, cap) == 0); out[len++] = ref; } reftable_iterator_destroy(&it); - check_int(ARRAY_SIZE(want), ==, len); + cl_assert_equal_i(ARRAY_SIZE(want), len); for (i = 0; i < len; i++) - check(reftable_ref_record_equal(want[i], &out[i], - REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_ref_record_equal(want[i], &out[i], + REFTABLE_HASH_SIZE_SHA1) != 0); for (i = 0; i < len; i++) reftable_ref_record_release(&out[i]); reftable_free(out); @@ -198,7 +199,7 @@ static void t_merged_refs(void) reftable_free(bs); } -static void t_merged_seek_multiple_times(void) +void test_reftable_merged__seek_multiple_times(void) { struct reftable_ref_record r1[] = { { @@ -248,20 +249,17 @@ static void t_merged_seek_multiple_times(void) for (size_t i = 0; i < 5; i++) { int err = reftable_iterator_seek_ref(&it, "c"); - check(!err); + cl_assert(!err); - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - err = reftable_ref_record_equal(&rec, &r1[1], REFTABLE_HASH_SIZE_SHA1); - check(err == 1); + cl_assert(reftable_iterator_next_ref(&it, &rec) == 0); + cl_assert_equal_i(reftable_ref_record_equal(&rec, &r1[1], + REFTABLE_HASH_SIZE_SHA1), 1); - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - err = reftable_ref_record_equal(&rec, &r2[1], REFTABLE_HASH_SIZE_SHA1); - check(err == 1); + cl_assert(reftable_iterator_next_ref(&it, &rec) == 0); + cl_assert_equal_i(reftable_ref_record_equal(&rec, &r2[1], + REFTABLE_HASH_SIZE_SHA1), 1); - err = reftable_iterator_next_ref(&it, &rec); - check(err > 0); + cl_assert(reftable_iterator_next_ref(&it, &rec) > 0); } for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) @@ -273,7 +271,7 @@ static void t_merged_seek_multiple_times(void) reftable_free(sources); } -static void t_merged_seek_multiple_times_without_draining(void) +void test_reftable_merged__seek_multiple_times_no_drain(void) { struct reftable_ref_record r1[] = { { @@ -317,24 +315,19 @@ static void t_merged_seek_multiple_times_without_draining(void) struct reftable_ref_record rec = { 0 }; struct reftable_iterator it = { 0 }; struct reftable_merged_table *mt; - int err; mt = merged_table_from_records(refs, &sources, &tables, sizes, bufs, 2); merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); - err = reftable_iterator_seek_ref(&it, "b"); - check(!err); - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - err = reftable_ref_record_equal(&rec, &r2[0], REFTABLE_HASH_SIZE_SHA1); - check(err == 1); + cl_assert(reftable_iterator_seek_ref(&it, "b") == 0); + cl_assert(reftable_iterator_next_ref(&it, &rec) == 0); + cl_assert_equal_i(reftable_ref_record_equal(&rec, &r2[0], + REFTABLE_HASH_SIZE_SHA1), 1); - err = reftable_iterator_seek_ref(&it, "a"); - check(!err); - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - err = reftable_ref_record_equal(&rec, &r1[0], REFTABLE_HASH_SIZE_SHA1); - check(err == 1); + cl_assert(reftable_iterator_seek_ref(&it, "a") == 0); + cl_assert(reftable_iterator_next_ref(&it, &rec) == 0); + cl_assert_equal_i(reftable_ref_record_equal(&rec, &r1[0], + REFTABLE_HASH_SIZE_SHA1), 1); for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) reftable_buf_release(&bufs[i]); @@ -359,25 +352,25 @@ merged_table_from_log_records(struct reftable_log_record **logs, int err; REFTABLE_CALLOC_ARRAY(*tables, n); - check(*tables != NULL); + cl_assert(*tables != NULL); REFTABLE_CALLOC_ARRAY(*source, n); - check(*source != NULL); + cl_assert(*source != NULL); for (size_t i = 0; i < n; i++) { - t_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts); + cl_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts); block_source_from_buf(&(*source)[i], &buf[i]); err = reftable_table_new(&(*tables)[i], &(*source)[i], "name"); - check(!err); + cl_assert(!err); } err = reftable_merged_table_new(&mt, *tables, n, REFTABLE_HASH_SHA1); - check(!err); + cl_assert(!err); return mt; } -static void t_merged_logs(void) +void test_reftable_merged__logs(void) { struct reftable_log_record r1[] = { { @@ -439,19 +432,19 @@ static void t_merged_logs(void) struct reftable_merged_table *mt = merged_table_from_log_records( logs, &bs, &tables, sizes, bufs, 3); struct reftable_iterator it = { 0 }; - int err; struct reftable_log_record *out = NULL; size_t len = 0; size_t cap = 0; size_t i; + int err; err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_log(&it, "a"); - check(!err); - check_int(reftable_merged_table_hash_id(mt), ==, REFTABLE_HASH_SHA1); - check_int(reftable_merged_table_min_update_index(mt), ==, 1); - check_int(reftable_merged_table_max_update_index(mt), ==, 3); + cl_assert(!err); + cl_assert_equal_i(reftable_merged_table_hash_id(mt), REFTABLE_HASH_SHA1); + cl_assert_equal_i(reftable_merged_table_min_update_index(mt), 1); + cl_assert_equal_i(reftable_merged_table_max_update_index(mt), 3); while (len < 100) { /* cap loops/recursion. */ struct reftable_log_record log = { 0 }; @@ -459,24 +452,24 @@ static void t_merged_logs(void) if (err > 0) break; - check(!REFTABLE_ALLOC_GROW(out, len + 1, cap)); + cl_assert(REFTABLE_ALLOC_GROW(out, len + 1, cap) == 0); out[len++] = log; } reftable_iterator_destroy(&it); - check_int(ARRAY_SIZE(want), ==, len); + cl_assert_equal_i(ARRAY_SIZE(want), len); for (i = 0; i < len; i++) - check(reftable_log_record_equal(want[i], &out[i], - REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_log_record_equal(want[i], &out[i], + REFTABLE_HASH_SIZE_SHA1) != 0); err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_log_at(&it, "a", 2); - check(!err); + cl_assert(!err); reftable_log_record_release(&out[0]); - err = reftable_iterator_next_log(&it, &out[0]); - check(!err); - check(reftable_log_record_equal(&out[0], &r3[0], REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_iterator_next_log(&it, &out[0]) == 0); + cl_assert(reftable_log_record_equal(&out[0], &r3[0], + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_iterator_destroy(&it); for (i = 0; i < len; i++) @@ -490,11 +483,11 @@ static void t_merged_logs(void) reftable_free(bs); } -static void t_default_write_opts(void) +void test_reftable_merged__default_write_opts(void) { struct reftable_write_options opts = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_ref_record rec = { .refname = (char *) "master", .update_index = 1, @@ -507,40 +500,25 @@ static void t_default_write_opts(void) reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_add_ref(w, &rec); - check(!err); + cl_assert_equal_i(reftable_writer_add_ref(w, &rec), 0); - err = reftable_writer_close(w); - check(!err); + cl_assert_equal_i(reftable_writer_close(w), 0); reftable_writer_free(w); block_source_from_buf(&source, &buf); err = reftable_table_new(&table, &source, "filename"); - check(!err); + cl_assert(!err); hash_id = reftable_table_hash_id(table); - check_int(hash_id, ==, REFTABLE_HASH_SHA1); + cl_assert_equal_i(hash_id, REFTABLE_HASH_SHA1); err = reftable_merged_table_new(&merged, &table, 1, REFTABLE_HASH_SHA256); - check_int(err, ==, REFTABLE_FORMAT_ERROR); + cl_assert_equal_i(err, REFTABLE_FORMAT_ERROR); err = reftable_merged_table_new(&merged, &table, 1, REFTABLE_HASH_SHA1); - check(!err); + cl_assert(!err); reftable_table_decref(table); reftable_merged_table_free(merged); reftable_buf_release(&buf); } - - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_default_write_opts(), "merged table with default write opts"); - TEST(t_merged_logs(), "merged table with multiple log updates for same ref"); - TEST(t_merged_refs(), "merged table with multiple updates to same ref"); - TEST(t_merged_seek_multiple_times(), "merged table can seek multiple times"); - TEST(t_merged_seek_multiple_times_without_draining(), "merged table can seek multiple times without draining"); - TEST(t_merged_single_record(), "ref occurring in only one record can be fetched"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/u-reftable-pq.c index fb5a4eb187..f8a28f6e07 100644 --- a/t/unit-tests/t-reftable-pq.c +++ b/t/unit-tests/u-reftable-pq.c @@ -6,7 +6,8 @@ license that can be found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd */ -#include "test-lib.h" +#include "unit-test.h" +#include "lib-reftable.h" #include "reftable/constants.h" #include "reftable/pq.h" #include "strbuf.h" @@ -15,18 +16,18 @@ static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq) { for (size_t i = 1; i < pq->len; i++) { size_t parent = (i - 1) / 2; - check(pq_less(&pq->heap[parent], &pq->heap[i])); + cl_assert(pq_less(&pq->heap[parent], &pq->heap[i]) != 0); } } static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b) { int cmp; - check(!reftable_record_cmp(a->rec, b->rec, &cmp)); + cl_assert_equal_i(reftable_record_cmp(a->rec, b->rec, &cmp), 0); return !cmp && (a->index == b->index); } -static void t_pq_record(void) +void test_reftable_pq__record(void) { struct merged_iter_pqueue pq = { 0 }; struct reftable_record recs[54]; @@ -34,7 +35,8 @@ static void t_pq_record(void) char *last = NULL; for (i = 0; i < N; i++) { - check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF)); + cl_assert(!reftable_record_init(&recs[i], + REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i); } @@ -53,13 +55,13 @@ static void t_pq_record(void) struct pq_entry top = merged_iter_pqueue_top(pq); struct pq_entry e; - check(!merged_iter_pqueue_remove(&pq, &e)); + cl_assert_equal_i(merged_iter_pqueue_remove(&pq, &e), 0); merged_iter_pqueue_check(&pq); - check(pq_entry_equal(&top, &e)); - check(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF); + cl_assert(pq_entry_equal(&top, &e)); + cl_assert(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF); if (last) - check_int(strcmp(last, e.rec->u.ref.refname), <, 0); + cl_assert(strcmp(last, e.rec->u.ref.refname) < 0); last = e.rec->u.ref.refname; } @@ -68,7 +70,7 @@ static void t_pq_record(void) merged_iter_pqueue_release(&pq); } -static void t_pq_index(void) +void test_reftable_pq__index(void) { struct merged_iter_pqueue pq = { 0 }; struct reftable_record recs[13]; @@ -76,7 +78,8 @@ static void t_pq_index(void) size_t N = ARRAY_SIZE(recs), i; for (i = 0; i < N; i++) { - check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF)); + cl_assert(!reftable_record_init(&recs[i], + REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = (char *) "refs/heads/master"; } @@ -96,28 +99,29 @@ static void t_pq_index(void) struct pq_entry top = merged_iter_pqueue_top(pq); struct pq_entry e; - check(!merged_iter_pqueue_remove(&pq, &e)); + cl_assert_equal_i(merged_iter_pqueue_remove(&pq, &e), 0); merged_iter_pqueue_check(&pq); - check(pq_entry_equal(&top, &e)); - check(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF); - check_int(e.index, ==, i); + cl_assert(pq_entry_equal(&top, &e)); + cl_assert(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF); + cl_assert_equal_i(e.index, i); if (last) - check_str(last, e.rec->u.ref.refname); + cl_assert_equal_s(last, e.rec->u.ref.refname); last = e.rec->u.ref.refname; } merged_iter_pqueue_release(&pq); } -static void t_merged_iter_pqueue_top(void) +void test_reftable_pq__merged_iter_pqueue_top(void) { struct merged_iter_pqueue pq = { 0 }; struct reftable_record recs[13]; size_t N = ARRAY_SIZE(recs), i; for (i = 0; i < N; i++) { - check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF)); + cl_assert(!reftable_record_init(&recs[i], + REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = (char *) "refs/heads/master"; } @@ -137,25 +141,16 @@ static void t_merged_iter_pqueue_top(void) struct pq_entry top = merged_iter_pqueue_top(pq); struct pq_entry e; - check(!merged_iter_pqueue_remove(&pq, &e)); + cl_assert_equal_i(merged_iter_pqueue_remove(&pq, &e), 0); merged_iter_pqueue_check(&pq); - check(pq_entry_equal(&top, &e)); - check(reftable_record_equal(top.rec, &recs[i], REFTABLE_HASH_SIZE_SHA1)); + cl_assert(pq_entry_equal(&top, &e) != 0); + cl_assert(reftable_record_equal(top.rec, &recs[i], REFTABLE_HASH_SIZE_SHA1) != 0); for (size_t j = 0; i < pq.len; j++) { - check(pq_less(&top, &pq.heap[j])); - check_int(top.index, >, j); + cl_assert(pq_less(&top, &pq.heap[j]) != 0); + cl_assert(top.index > j); } } merged_iter_pqueue_release(&pq); } - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_pq_record(), "pq works with record-based comparison"); - TEST(t_pq_index(), "pq works with index-based comparison"); - TEST(t_merged_iter_pqueue_top(), "merged_iter_pqueue_top works"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/u-reftable-readwrite.c index 4c49129439..4d8c4be5f1 100644 --- a/t/unit-tests/t-reftable-readwrite.c +++ b/t/unit-tests/u-reftable-readwrite.c @@ -8,7 +8,7 @@ https://developers.google.com/open-source/licenses/bsd #define DISABLE_SIGN_COMPARE_WARNINGS -#include "test-lib.h" +#include "unit-test.h" #include "lib-reftable.h" #include "reftable/basics.h" #include "reftable/blocksource.h" @@ -19,24 +19,24 @@ https://developers.google.com/open-source/licenses/bsd static const int update_index = 5; -static void t_buffer(void) +void test_reftable_readwrite__buffer(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; struct reftable_block_data out = { 0 }; int n; uint8_t in[] = "hello"; - check(!reftable_buf_add(&buf, in, sizeof(in))); + cl_assert_equal_i(reftable_buf_add(&buf, in, sizeof(in)), 0); block_source_from_buf(&source, &buf); - check_int(block_source_size(&source), ==, 6); + cl_assert_equal_i(block_source_size(&source), 6); n = block_source_read_data(&source, &out, 0, sizeof(in)); - check_int(n, ==, sizeof(in)); - check(!memcmp(in, out.data, n)); + cl_assert_equal_i(n, sizeof(in)); + cl_assert(!memcmp(in, out.data, n)); block_source_release_data(&out); n = block_source_read_data(&source, &out, 1, 2); - check_int(n, ==, 2); - check(!memcmp(out.data, "el", 2)); + cl_assert_equal_i(n, 2); + cl_assert(!memcmp(out.data, "el", 2)); block_source_release_data(&out); block_source_close(&source); @@ -55,41 +55,41 @@ static void write_table(char ***names, struct reftable_buf *buf, int N, int i; REFTABLE_CALLOC_ARRAY(*names, N + 1); - check(*names != NULL); + cl_assert(*names != NULL); REFTABLE_CALLOC_ARRAY(refs, N); - check(refs != NULL); + cl_assert(refs != NULL); REFTABLE_CALLOC_ARRAY(logs, N); - check(logs != NULL); + cl_assert(logs != NULL); for (i = 0; i < N; i++) { refs[i].refname = (*names)[i] = xstrfmt("refs/heads/branch%02d", i); refs[i].update_index = update_index; refs[i].value_type = REFTABLE_REF_VAL1; - t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(refs[i].value.val1, i, + REFTABLE_HASH_SHA1); } for (i = 0; i < N; i++) { logs[i].refname = (*names)[i]; logs[i].update_index = update_index; logs[i].value_type = REFTABLE_LOG_UPDATE; - t_reftable_set_hash(logs[i].value.update.new_hash, i, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); logs[i].value.update.message = (char *) "message"; } - t_reftable_write_to_buf(buf, refs, N, logs, N, &opts); + cl_reftable_write_to_buf(buf, refs, N, logs, N, &opts); reftable_free(refs); reftable_free(logs); } -static void t_log_buffer_size(void) +void test_reftable_readwrite__log_buffer_size(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_write_options opts = { .block_size = 4096, }; - int err; int i; struct reftable_log_record log = { .refname = (char *) "refs/heads/master", @@ -102,7 +102,8 @@ static void t_log_buffer_size(void) .time = 0x5e430672, .message = (char *) "commit: 9\n", } } }; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, + &opts); /* This tests buffer extension for log compression. Must use a random hash, to ensure that the compressed part is larger than the original. @@ -112,22 +113,19 @@ static void t_log_buffer_size(void) log.value.update.new_hash[i] = (uint8_t)(git_rand(0) % 256); } reftable_writer_set_limits(w, update_index, update_index); - err = reftable_writer_add_log(w, &log); - check(!err); - err = reftable_writer_close(w); - check(!err); + cl_assert_equal_i(reftable_writer_add_log(w, &log), 0); + cl_assert_equal_i(reftable_writer_close(w), 0); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_log_overflow(void) +void test_reftable_readwrite__log_overflow(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; char msg[256] = { 0 }; struct reftable_write_options opts = { .block_size = ARRAY_SIZE(msg), }; - int err; struct reftable_log_record log = { .refname = (char *) "refs/heads/master", .update_index = update_index, @@ -144,21 +142,22 @@ static void t_log_overflow(void) }, }, }; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, + &opts); memset(msg, 'x', sizeof(msg) - 1); reftable_writer_set_limits(w, update_index, update_index); - err = reftable_writer_add_log(w, &log); - check_int(err, ==, REFTABLE_ENTRY_TOO_BIG_ERROR); + cl_assert_equal_i(reftable_writer_add_log(w, &log), REFTABLE_ENTRY_TOO_BIG_ERROR); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_log_write_limits(void) +void test_reftable_readwrite__log_write_limits(void) { struct reftable_write_options opts = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, + &opts); struct reftable_log_record log = { .refname = (char *)"refs/head/master", .update_index = 0, @@ -174,29 +173,25 @@ static void t_log_write_limits(void) }, }, }; - int err; reftable_writer_set_limits(w, 1, 1); /* write with update_index (0) below set limits (1, 1) */ - err = reftable_writer_add_log(w, &log); - check_int(err, ==, 0); + cl_assert_equal_i(reftable_writer_add_log(w, &log), 0); /* write with update_index (1) in the set limits (1, 1) */ log.update_index = 1; - err = reftable_writer_add_log(w, &log); - check_int(err, ==, 0); + cl_assert_equal_i(reftable_writer_add_log(w, &log), 0); /* write with update_index (3) above set limits (1, 1) */ log.update_index = 3; - err = reftable_writer_add_log(w, &log); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_writer_add_log(w, &log), REFTABLE_API_ERROR); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_log_write_read(void) +void test_reftable_readwrite__log_write_read(void) { struct reftable_write_options opts = { .block_size = 256, @@ -207,13 +202,14 @@ static void t_log_write_read(void) struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); const struct reftable_stats *stats = NULL; - int N = 2, err, i, n; + int N = 2, i; char **names; + int err; names = reftable_calloc(N + 1, sizeof(*names)); - check(names != NULL); + cl_assert(names != NULL); reftable_writer_set_limits(w, 0, N); @@ -225,8 +221,7 @@ static void t_log_write_read(void) ref.refname = name; ref.update_index = i; - err = reftable_writer_add_ref(w, &ref); - check(!err); + cl_assert_equal_i(reftable_writer_add_ref(w, &ref), 0); } for (i = 0; i < N; i++) { @@ -235,60 +230,57 @@ static void t_log_write_read(void) log.refname = names[i]; log.update_index = i; log.value_type = REFTABLE_LOG_UPDATE; - t_reftable_set_hash(log.value.update.old_hash, i, - REFTABLE_HASH_SHA1); - t_reftable_set_hash(log.value.update.new_hash, i + 1, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(log.value.update.old_hash, i, + REFTABLE_HASH_SHA1); + cl_reftable_set_hash(log.value.update.new_hash, i + 1, + REFTABLE_HASH_SHA1); - err = reftable_writer_add_log(w, &log); - check(!err); + cl_assert_equal_i(reftable_writer_add_log(w, &log), 0); } - n = reftable_writer_close(w); - check_int(n, ==, 0); + cl_assert_equal_i(reftable_writer_close(w), 0); stats = reftable_writer_stats(w); - check_int(stats->log_stats.blocks, >, 0); + cl_assert(stats->log_stats.blocks > 0); reftable_writer_free(w); w = NULL; block_source_from_buf(&source, &buf); err = reftable_table_new(&table, &source, "file.log"); - check(!err); + cl_assert(!err); err = reftable_table_init_ref_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, names[N - 1]); - check(!err); + cl_assert(!err); err = reftable_iterator_next_ref(&it, &ref); - check(!err); + cl_assert(!err); /* end of iteration. */ - err = reftable_iterator_next_ref(&it, &ref); - check_int(err, >, 0); + cl_assert(reftable_iterator_next_ref(&it, &ref) > 0); reftable_iterator_destroy(&it); reftable_ref_record_release(&ref); err = reftable_table_init_log_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_log(&it, ""); - check(!err); + cl_assert(!err); for (i = 0; ; i++) { int err = reftable_iterator_next_log(&it, &log); if (err > 0) break; - check(!err); - check_str(names[i], log.refname); - check_int(i, ==, log.update_index); + cl_assert(!err); + cl_assert_equal_s(names[i], log.refname); + cl_assert_equal_i(i, log.update_index); reftable_log_record_release(&log); } - check_int(i, ==, N); + cl_assert_equal_i(i, N); reftable_iterator_destroy(&it); /* cleanup. */ @@ -297,7 +289,7 @@ static void t_log_write_read(void) reftable_table_decref(table); } -static void t_log_zlib_corruption(void) +void test_reftable_readwrite__log_zlib_corruption(void) { struct reftable_write_options opts = { .block_size = 256, @@ -306,10 +298,12 @@ static void t_log_zlib_corruption(void) struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, + &opts); const struct reftable_stats *stats = NULL; char message[100] = { 0 }; - int err, i, n; + int i; + int err; struct reftable_log_record log = { .refname = (char *) "refname", .value_type = REFTABLE_LOG_UPDATE, @@ -329,14 +323,11 @@ static void t_log_zlib_corruption(void) reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_add_log(w, &log); - check(!err); - - n = reftable_writer_close(w); - check_int(n, ==, 0); + cl_assert_equal_i(reftable_writer_add_log(w, &log), 0); + cl_assert_equal_i(reftable_writer_close(w), 0); stats = reftable_writer_stats(w); - check_int(stats->log_stats.blocks, >, 0); + cl_assert(stats->log_stats.blocks > 0); reftable_writer_free(w); w = NULL; @@ -346,12 +337,12 @@ static void t_log_zlib_corruption(void) block_source_from_buf(&source, &buf); err = reftable_table_new(&table, &source, "file.log"); - check(!err); + cl_assert(!err); err = reftable_table_init_log_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_log(&it, "refname"); - check_int(err, ==, REFTABLE_ZLIB_ERROR); + cl_assert_equal_i(err, REFTABLE_ZLIB_ERROR); reftable_iterator_destroy(&it); @@ -360,7 +351,7 @@ static void t_log_zlib_corruption(void) reftable_buf_release(&buf); } -static void t_table_read_write_sequential(void) +void test_reftable_readwrite__table_read_write_sequential(void) { char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; @@ -376,24 +367,24 @@ static void t_table_read_write_sequential(void) block_source_from_buf(&source, &buf); err = reftable_table_new(&table, &source, "file.ref"); - check(!err); + cl_assert(!err); err = reftable_table_init_ref_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, ""); - check(!err); + cl_assert(!err); for (j = 0; ; j++) { struct reftable_ref_record ref = { 0 }; int r = reftable_iterator_next_ref(&it, &ref); - check_int(r, >=, 0); + cl_assert(r >= 0); if (r > 0) break; - check_str(names[j], ref.refname); - check_int(update_index, ==, ref.update_index); + cl_assert_equal_s(names[j], ref.refname); + cl_assert_equal_i(update_index, ref.update_index); reftable_ref_record_release(&ref); } - check_int(j, ==, N); + cl_assert_equal_i(j, N); reftable_iterator_destroy(&it); reftable_table_decref(table); @@ -401,42 +392,42 @@ static void t_table_read_write_sequential(void) free_names(names); } -static void t_table_write_small_table(void) +void test_reftable_readwrite__table_write_small_table(void) { char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; int N = 1; write_table(&names, &buf, N, 4096, REFTABLE_HASH_SHA1); - check_int(buf.len, <, 200); + cl_assert(buf.len < 200); reftable_buf_release(&buf); free_names(names); } -static void t_table_read_api(void) +void test_reftable_readwrite__table_read_api(void) { char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; int N = 50; struct reftable_table *table; struct reftable_block_source source = { 0 }; - int err; struct reftable_log_record log = { 0 }; struct reftable_iterator it = { 0 }; + int err; write_table(&names, &buf, N, 256, REFTABLE_HASH_SHA1); block_source_from_buf(&source, &buf); err = reftable_table_new(&table, &source, "file.ref"); - check(!err); + cl_assert(!err); err = reftable_table_init_ref_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, names[0]); - check(!err); + cl_assert(!err); err = reftable_iterator_next_log(&it, &log); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(err, REFTABLE_API_ERROR); reftable_buf_release(&buf); free_names(names); @@ -464,42 +455,43 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) block_source_from_buf(&source, &buf); err = reftable_table_new(&table, &source, "file.ref"); - check(!err); - check_int(hash_id, ==, reftable_table_hash_id(table)); + cl_assert(!err); + cl_assert_equal_i(hash_id, reftable_table_hash_id(table)); if (!index) { table->ref_offsets.index_offset = 0; } else { - check_int(table->ref_offsets.index_offset, >, 0); + cl_assert(table->ref_offsets.index_offset > 0); } for (i = 1; i < N; i++) { err = reftable_table_init_ref_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, names[i]); - check(!err); + cl_assert(!err); err = reftable_iterator_next_ref(&it, &ref); - check(!err); - check_str(names[i], ref.refname); - check_int(REFTABLE_REF_VAL1, ==, ref.value_type); - check_int(i, ==, ref.value.val1[0]); + cl_assert(!err); + cl_assert_equal_s(names[i], ref.refname); + cl_assert_equal_i(REFTABLE_REF_VAL1, ref.value_type); + cl_assert_equal_i(i, ref.value.val1[0]); reftable_ref_record_release(&ref); reftable_iterator_destroy(&it); } - check(!reftable_buf_addstr(&pastLast, names[N - 1])); - check(!reftable_buf_addstr(&pastLast, "/")); + cl_assert_equal_i(reftable_buf_addstr(&pastLast, names[N - 1]), + 0); + cl_assert_equal_i(reftable_buf_addstr(&pastLast, "/"), 0); err = reftable_table_init_ref_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, pastLast.buf); if (err == 0) { struct reftable_ref_record ref = { 0 }; int err = reftable_iterator_next_ref(&it, &ref); - check_int(err, >, 0); + cl_assert(err > 0); } else { - check_int(err, >, 0); + cl_assert(err > 0); } reftable_buf_release(&pastLast); @@ -510,17 +502,17 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) reftable_table_decref(table); } -static void t_table_read_write_seek_linear(void) +void test_reftable_readwrite__table_read_write_seek_linear(void) { t_table_read_write_seek(0, REFTABLE_HASH_SHA1); } -static void t_table_read_write_seek_linear_sha256(void) +void test_reftable_readwrite__table_read_write_seek_linear_sha256(void) { t_table_read_write_seek(0, REFTABLE_HASH_SHA256); } -static void t_table_read_write_seek_index(void) +void test_reftable_readwrite__table_read_write_seek_index(void) { t_table_read_write_seek(1, REFTABLE_HASH_SHA1); } @@ -538,14 +530,16 @@ static void t_table_refs_for(int indexed) struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, + &opts); struct reftable_iterator it = { 0 }; - int N = 50, n, j, err, i; + int N = 50, j, i; + int err; want_names = reftable_calloc(N + 1, sizeof(*want_names)); - check(want_names != NULL); + cl_assert(want_names != NULL); - t_reftable_set_hash(want_hash, 4, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(want_hash, 4, REFTABLE_HASH_SHA1); for (i = 0; i < N; i++) { uint8_t hash[REFTABLE_HASH_SIZE_SHA1]; @@ -561,24 +555,22 @@ static void t_table_refs_for(int indexed) ref.refname = name; ref.value_type = REFTABLE_REF_VAL2; - t_reftable_set_hash(ref.value.val2.value, i / 4, - REFTABLE_HASH_SHA1); - t_reftable_set_hash(ref.value.val2.target_value, 3 + i / 4, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(ref.value.val2.value, i / 4, + REFTABLE_HASH_SHA1); + cl_reftable_set_hash(ref.value.val2.target_value, + 3 + i / 4, REFTABLE_HASH_SHA1); /* 80 bytes / entry, so 3 entries per block. Yields 17 */ /* blocks. */ - n = reftable_writer_add_ref(w, &ref); - check_int(n, ==, 0); + cl_assert_equal_i(reftable_writer_add_ref(w, &ref), 0); if (!memcmp(ref.value.val2.value, want_hash, REFTABLE_HASH_SIZE_SHA1) || !memcmp(ref.value.val2.target_value, want_hash, REFTABLE_HASH_SIZE_SHA1)) want_names[want_names_len++] = xstrdup(name); } - n = reftable_writer_close(w); - check_int(n, ==, 0); + cl_assert_equal_i(reftable_writer_close(w), 0); reftable_writer_free(w); w = NULL; @@ -586,29 +578,29 @@ static void t_table_refs_for(int indexed) block_source_from_buf(&source, &buf); err = reftable_table_new(&table, &source, "file.ref"); - check(!err); + cl_assert(!err); if (!indexed) table->obj_offsets.is_present = 0; err = reftable_table_init_ref_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, ""); - check(!err); + cl_assert(!err); reftable_iterator_destroy(&it); err = reftable_table_refs_for(table, &it, want_hash); - check(!err); + cl_assert(!err); for (j = 0; ; j++) { int err = reftable_iterator_next_ref(&it, &ref); - check_int(err, >=, 0); + cl_assert(err >= 0); if (err > 0) break; - check_int(j, <, want_names_len); - check_str(ref.refname, want_names[j]); + cl_assert(j < want_names_len); + cl_assert_equal_s(ref.refname, want_names[j]); reftable_ref_record_release(&ref); } - check_int(j, ==, want_names_len); + cl_assert_equal_i(j, want_names_len); reftable_buf_release(&buf); free_names(want_names); @@ -616,21 +608,21 @@ static void t_table_refs_for(int indexed) reftable_table_decref(table); } -static void t_table_refs_for_no_index(void) +void test_reftable_readwrite__table_refs_for_no_index(void) { t_table_refs_for(0); } -static void t_table_refs_for_obj_index(void) +void test_reftable_readwrite__table_refs_for_obj_index(void) { t_table_refs_for(1); } -static void t_write_empty_table(void) +void test_reftable_readwrite__write_empty_table(void) { struct reftable_write_options opts = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_block_source source = { 0 }; struct reftable_table *table = NULL; struct reftable_ref_record rec = { 0 }; @@ -639,43 +631,41 @@ static void t_write_empty_table(void) reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_close(w); - check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR); + cl_assert_equal_i(reftable_writer_close(w), REFTABLE_EMPTY_TABLE_ERROR); reftable_writer_free(w); - check_uint(buf.len, ==, header_size(1) + footer_size(1)); + cl_assert_equal_i(buf.len, header_size(1) + footer_size(1)); block_source_from_buf(&source, &buf); err = reftable_table_new(&table, &source, "filename"); - check(!err); + cl_assert(!err); err = reftable_table_init_ref_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, ""); - check(!err); + cl_assert(!err); err = reftable_iterator_next_ref(&it, &rec); - check_int(err, >, 0); + cl_assert(err > 0); reftable_iterator_destroy(&it); reftable_table_decref(table); reftable_buf_release(&buf); } -static void t_write_object_id_min_length(void) +void test_reftable_readwrite__write_object_id_min_length(void) { struct reftable_write_options opts = { .block_size = 75, }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_ref_record ref = { .update_index = 1, .value_type = REFTABLE_REF_VAL1, .value.val1 = {42}, }; - int err; int i; reftable_writer_set_limits(w, 1, 1); @@ -686,30 +676,27 @@ static void t_write_object_id_min_length(void) char name[256]; snprintf(name, sizeof(name), "ref%05d", i); ref.refname = name; - err = reftable_writer_add_ref(w, &ref); - check(!err); + cl_assert_equal_i(reftable_writer_add_ref(w, &ref), 0); } - err = reftable_writer_close(w); - check(!err); - check_int(reftable_writer_stats(w)->object_id_len, ==, 2); + cl_assert_equal_i(reftable_writer_close(w), 0); + cl_assert_equal_i(reftable_writer_stats(w)->object_id_len, 2); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_write_object_id_length(void) +void test_reftable_readwrite__write_object_id_length(void) { struct reftable_write_options opts = { .block_size = 75, }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_ref_record ref = { .update_index = 1, .value_type = REFTABLE_REF_VAL1, .value.val1 = {42}, }; - int err; int i; reftable_writer_set_limits(w, 1, 1); @@ -721,44 +708,39 @@ static void t_write_object_id_length(void) snprintf(name, sizeof(name), "ref%05d", i); ref.refname = name; ref.value.val1[15] = i; - err = reftable_writer_add_ref(w, &ref); - check(!err); + cl_assert(reftable_writer_add_ref(w, &ref) == 0); } - err = reftable_writer_close(w); - check(!err); - check_int(reftable_writer_stats(w)->object_id_len, ==, 16); + cl_assert_equal_i(reftable_writer_close(w), 0); + cl_assert_equal_i(reftable_writer_stats(w)->object_id_len, 16); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_write_empty_key(void) +void test_reftable_readwrite__write_empty_key(void) { struct reftable_write_options opts = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_ref_record ref = { .refname = (char *) "", .update_index = 1, .value_type = REFTABLE_REF_DELETION, }; - int err; reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_add_ref(w, &ref); - check_int(err, ==, REFTABLE_API_ERROR); - - err = reftable_writer_close(w); - check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR); + cl_assert_equal_i(reftable_writer_add_ref(w, &ref), REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_writer_close(w), + REFTABLE_EMPTY_TABLE_ERROR); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_write_key_order(void) +void test_reftable_readwrite__write_key_order(void) { struct reftable_write_options opts = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_ref_record refs[2] = { { .refname = (char *) "b", @@ -776,24 +758,21 @@ static void t_write_key_order(void) }, } }; - int err; reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_add_ref(w, &refs[0]); - check(!err); - err = reftable_writer_add_ref(w, &refs[1]); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_writer_add_ref(w, &refs[0]), 0); + cl_assert_equal_i(reftable_writer_add_ref(w, &refs[1]), + REFTABLE_API_ERROR); refs[0].update_index = 2; - err = reftable_writer_add_ref(w, &refs[0]); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_writer_add_ref(w, &refs[0]), REFTABLE_API_ERROR); reftable_writer_close(w); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_write_multiple_indices(void) +void test_reftable_readwrite__write_multiple_indices(void) { struct reftable_write_options opts = { .block_size = 100, @@ -805,9 +784,10 @@ static void t_write_multiple_indices(void) struct reftable_writer *writer; struct reftable_table *table; char buf[128]; - int err, i; + int i; + int err; - writer = t_reftable_strbuf_writer(&writer_buf, &opts); + writer = cl_reftable_strbuf_writer(&writer_buf, &opts); reftable_writer_set_limits(writer, 1, 1); for (i = 0; i < 100; i++) { struct reftable_ref_record ref = { @@ -819,8 +799,7 @@ static void t_write_multiple_indices(void) snprintf(buf, sizeof(buf), "refs/heads/%04d", i); ref.refname = buf; - err = reftable_writer_add_ref(writer, &ref); - check(!err); + cl_assert_equal_i(reftable_writer_add_ref(writer, &ref), 0); } for (i = 0; i < 100; i++) { @@ -836,8 +815,7 @@ static void t_write_multiple_indices(void) snprintf(buf, sizeof(buf), "refs/heads/%04d", i); log.refname = buf; - err = reftable_writer_add_log(writer, &log); - check(!err); + cl_assert_equal_i(reftable_writer_add_log(writer, &log), 0); } reftable_writer_close(writer); @@ -847,22 +825,22 @@ static void t_write_multiple_indices(void) * for each of the block types. */ stats = reftable_writer_stats(writer); - check_int(stats->ref_stats.index_offset, >, 0); - check_int(stats->obj_stats.index_offset, >, 0); - check_int(stats->log_stats.index_offset, >, 0); + cl_assert(stats->ref_stats.index_offset > 0); + cl_assert(stats->obj_stats.index_offset > 0); + cl_assert(stats->log_stats.index_offset > 0); block_source_from_buf(&source, &writer_buf); err = reftable_table_new(&table, &source, "filename"); - check(!err); + cl_assert(!err); /* * Seeking the log uses the log index now. In case there is any * confusion regarding indices we would notice here. */ err = reftable_table_init_log_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_log(&it, ""); - check(!err); + cl_assert(!err); reftable_iterator_destroy(&it); reftable_writer_free(writer); @@ -870,7 +848,7 @@ static void t_write_multiple_indices(void) reftable_buf_release(&writer_buf); } -static void t_write_multi_level_index(void) +void test_reftable_readwrite__write_multi_level_index(void) { struct reftable_write_options opts = { .block_size = 100, @@ -883,7 +861,7 @@ static void t_write_multi_level_index(void) struct reftable_table *table; int err; - writer = t_reftable_strbuf_writer(&writer_buf, &opts); + writer = cl_reftable_strbuf_writer(&writer_buf, &opts); reftable_writer_set_limits(writer, 1, 1); for (size_t i = 0; i < 200; i++) { struct reftable_ref_record ref = { @@ -896,8 +874,7 @@ static void t_write_multi_level_index(void) snprintf(buf, sizeof(buf), "refs/heads/%03" PRIuMAX, (uintmax_t)i); ref.refname = buf; - err = reftable_writer_add_ref(writer, &ref); - check(!err); + cl_assert_equal_i(reftable_writer_add_ref(writer, &ref), 0); } reftable_writer_close(writer); @@ -906,19 +883,19 @@ static void t_write_multi_level_index(void) * multi-level index. */ stats = reftable_writer_stats(writer); - check_int(stats->ref_stats.max_index_level, ==, 2); + cl_assert_equal_i(stats->ref_stats.max_index_level, 2); block_source_from_buf(&source, &writer_buf); err = reftable_table_new(&table, &source, "filename"); - check(!err); + cl_assert(!err); /* * Seeking the last ref should work as expected. */ err = reftable_table_init_ref_iterator(table, &it); - check(!err); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, "refs/heads/199"); - check(!err); + cl_assert(!err); reftable_iterator_destroy(&it); reftable_writer_free(writer); @@ -927,7 +904,7 @@ static void t_write_multi_level_index(void) reftable_buf_release(&buf); } -static void t_corrupt_table_empty(void) +void test_reftable_readwrite__corrupt_table_empty(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; @@ -936,50 +913,22 @@ static void t_corrupt_table_empty(void) block_source_from_buf(&source, &buf); err = reftable_table_new(&table, &source, "file.log"); - check_int(err, ==, REFTABLE_FORMAT_ERROR); + cl_assert_equal_i(err, REFTABLE_FORMAT_ERROR); } -static void t_corrupt_table(void) +void test_reftable_readwrite__corrupt_table(void) { uint8_t zeros[1024] = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; struct reftable_table *table; int err; - check(!reftable_buf_add(&buf, zeros, sizeof(zeros))); + + cl_assert(!reftable_buf_add(&buf, zeros, sizeof(zeros))); block_source_from_buf(&source, &buf); err = reftable_table_new(&table, &source, "file.log"); - check_int(err, ==, REFTABLE_FORMAT_ERROR); + cl_assert_equal_i(err, REFTABLE_FORMAT_ERROR); reftable_buf_release(&buf); } - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_buffer(), "strbuf works as blocksource"); - TEST(t_corrupt_table(), "read-write on corrupted table"); - TEST(t_corrupt_table_empty(), "read-write on an empty table"); - TEST(t_log_buffer_size(), "buffer extension for log compression"); - TEST(t_log_overflow(), "log overflow returns expected error"); - TEST(t_log_write_limits(), "writer limits for writing log records"); - TEST(t_log_write_read(), "read-write on log records"); - TEST(t_log_zlib_corruption(), "reading corrupted log record returns expected error"); - TEST(t_table_read_api(), "read on a table"); - TEST(t_table_read_write_seek_index(), "read-write on a table with index"); - TEST(t_table_read_write_seek_linear(), "read-write on a table without index (SHA1)"); - TEST(t_table_read_write_seek_linear_sha256(), "read-write on a table without index (SHA256)"); - TEST(t_table_read_write_sequential(), "sequential read-write on a table"); - TEST(t_table_refs_for_no_index(), "refs-only table with no index"); - TEST(t_table_refs_for_obj_index(), "refs-only table with index"); - TEST(t_table_write_small_table(), "write_table works"); - TEST(t_write_empty_key(), "write on refs with empty keys"); - TEST(t_write_empty_table(), "read-write on empty tables"); - TEST(t_write_key_order(), "refs must be written in increasing order"); - TEST(t_write_multi_level_index(), "table with multi-level index"); - TEST(t_write_multiple_indices(), "table with indices for multiple block types"); - TEST(t_write_object_id_length(), "prefix compression on writing refs"); - TEST(t_write_object_id_min_length(), "prefix compression on writing refs"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/u-reftable-record.c index 553a007664..6c8c0d5374 100644 --- a/t/unit-tests/t-reftable-record.c +++ b/t/unit-tests/u-reftable-record.c @@ -6,7 +6,8 @@ https://developers.google.com/open-source/licenses/bsd */ -#include "test-lib.h" +#include "unit-test.h" +#include "lib-reftable.h" #include "reftable/basics.h" #include "reftable/constants.h" #include "reftable/record.h" @@ -17,16 +18,17 @@ static void t_copy(struct reftable_record *rec) uint8_t typ; typ = reftable_record_type(rec); - check(!reftable_record_init(©, typ)); + cl_assert_equal_i(reftable_record_init(©, typ), 0); reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1); /* do it twice to catch memory leaks */ reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1); - check(reftable_record_equal(rec, ©, REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_record_equal(rec, ©, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_record_release(©); } -static void t_varint_roundtrip(void) +void test_reftable_record__varint_roundtrip(void) { uint64_t inputs[] = { 0, 1, @@ -49,16 +51,16 @@ static void t_varint_roundtrip(void) int n = put_var_int(&out, in); uint64_t got = 0; - check_int(n, >, 0); + cl_assert(n > 0); out.len = n; n = get_var_int(&got, &out); - check_int(n, >, 0); + cl_assert(n > 0); - check_int(got, ==, in); + cl_assert_equal_i(got, in); } } -static void t_varint_overflow(void) +void test_reftable_record__varint_overflow(void) { unsigned char buf[] = { 0xFF, 0xFF, 0xFF, 0xFF, @@ -70,8 +72,7 @@ static void t_varint_overflow(void) .len = sizeof(buf), }; uint64_t value; - int err = get_var_int(&value, &view); - check_int(err, ==, -1); + cl_assert_equal_i(get_var_int(&value, &view), -1); } static void set_hash(uint8_t *h, int j) @@ -80,7 +81,7 @@ static void set_hash(uint8_t *h, int j) h[i] = (j >> i) & 0xff; } -static void t_reftable_ref_record_comparison(void) +void test_reftable_record__ref_record_comparison(void) { struct reftable_record in[3] = { { @@ -102,21 +103,23 @@ static void t_reftable_ref_record_comparison(void) }; int cmp; - check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1], &cmp)); - check(!cmp); + cl_assert(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1) == 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); - check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[1], &in[2], &cmp)); - check_int(cmp, >, 0); + cl_assert(reftable_record_equal(&in[1], &in[2], + REFTABLE_HASH_SIZE_SHA1) == 0); + cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0); + cl_assert(cmp > 0); in[1].u.ref.value_type = in[0].u.ref.value_type; - check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1], &cmp)); - check(!cmp); + cl_assert(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1) != 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); } -static void t_reftable_ref_record_compare_name(void) +void test_reftable_record__ref_record_compare_name(void) { struct reftable_ref_record recs[3] = { { @@ -130,12 +133,15 @@ static void t_reftable_ref_record_compare_name(void) }, }; - check_int(reftable_ref_record_compare_name(&recs[0], &recs[1]), <, 0); - check_int(reftable_ref_record_compare_name(&recs[1], &recs[0]), >, 0); - check_int(reftable_ref_record_compare_name(&recs[0], &recs[2]), ==, 0); + cl_assert(reftable_ref_record_compare_name(&recs[0], + &recs[1]) < 0); + cl_assert(reftable_ref_record_compare_name(&recs[1], + &recs[0]) > 0); + cl_assert_equal_i(reftable_ref_record_compare_name(&recs[0], + &recs[2]), 0); } -static void t_reftable_ref_record_roundtrip(void) +void test_reftable_record__ref_record_roundtrip(void) { struct reftable_buf scratch = REFTABLE_BUF_INIT; @@ -172,19 +178,21 @@ static void t_reftable_ref_record_roundtrip(void) t_copy(&in); - check_int(reftable_record_val_type(&in), ==, i); - check_int(reftable_record_is_deletion(&in), ==, i == REFTABLE_REF_DELETION); + cl_assert_equal_i(reftable_record_val_type(&in), i); + cl_assert_equal_i(reftable_record_is_deletion(&in), + i == REFTABLE_REF_DELETION); reftable_record_key(&in, &key); n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); - check_int(n, >, 0); + cl_assert(n > 0); /* decode into a non-zero reftable_record to test for leaks. */ m = reftable_record_decode(&out, key, i, dest, REFTABLE_HASH_SIZE_SHA1, &scratch); - check_int(n, ==, m); + cl_assert_equal_i(n, m); - check(reftable_ref_record_equal(&in.u.ref, &out.u.ref, - REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_ref_record_equal(&in.u.ref, + &out.u.ref, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_record_release(&in); reftable_buf_release(&key); @@ -194,7 +202,7 @@ static void t_reftable_ref_record_roundtrip(void) reftable_buf_release(&scratch); } -static void t_reftable_log_record_comparison(void) +void test_reftable_record__log_record_comparison(void) { struct reftable_record in[3] = { { @@ -215,21 +223,24 @@ static void t_reftable_log_record_comparison(void) }; int cmp; - check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[1], &in[2], &cmp)); - check_int(cmp, >, 0); + cl_assert_equal_i(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_equal(&in[1], &in[2], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0); + cl_assert(cmp > 0); /* comparison should be reversed for equal keys, because * comparison is now performed on the basis of update indices */ - check(!reftable_record_cmp(&in[0], &in[1], &cmp)); - check_int(cmp, <, 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(cmp < 0); in[1].u.log.update_index = in[0].u.log.update_index; - check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1], &cmp)); + cl_assert(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1) != 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); } -static void t_reftable_log_record_compare_key(void) +void test_reftable_record__log_record_compare_key(void) { struct reftable_log_record logs[3] = { { @@ -246,19 +257,24 @@ static void t_reftable_log_record_compare_key(void) }, }; - check_int(reftable_log_record_compare_key(&logs[0], &logs[1]), <, 0); - check_int(reftable_log_record_compare_key(&logs[1], &logs[0]), >, 0); + cl_assert(reftable_log_record_compare_key(&logs[0], + &logs[1]) < 0); + cl_assert(reftable_log_record_compare_key(&logs[1], + &logs[0]) > 0); logs[1].update_index = logs[0].update_index; - check_int(reftable_log_record_compare_key(&logs[0], &logs[1]), <, 0); + cl_assert(reftable_log_record_compare_key(&logs[0], + &logs[1]) < 0); - check_int(reftable_log_record_compare_key(&logs[0], &logs[2]), >, 0); - check_int(reftable_log_record_compare_key(&logs[2], &logs[0]), <, 0); + cl_assert(reftable_log_record_compare_key(&logs[0], + &logs[2]) > 0); + cl_assert(reftable_log_record_compare_key(&logs[2], + &logs[0]) < 0); logs[2].update_index = logs[0].update_index; - check_int(reftable_log_record_compare_key(&logs[0], &logs[2]), ==, 0); + cl_assert_equal_i(reftable_log_record_compare_key(&logs[0], &logs[2]), 0); } -static void t_reftable_log_record_roundtrip(void) +void test_reftable_record__log_record_roundtrip(void) { struct reftable_log_record in[] = { { @@ -292,9 +308,9 @@ static void t_reftable_log_record_roundtrip(void) set_hash(in[2].value.update.new_hash, 3); set_hash(in[2].value.update.old_hash, 4); - check(!reftable_log_record_is_deletion(&in[0])); - check(reftable_log_record_is_deletion(&in[1])); - check(!reftable_log_record_is_deletion(&in[2])); + cl_assert_equal_i(reftable_log_record_is_deletion(&in[0]), 0); + cl_assert(reftable_log_record_is_deletion(&in[1]) != 0); + cl_assert_equal_i(reftable_log_record_is_deletion(&in[2]), 0); for (size_t i = 0; i < ARRAY_SIZE(in); i++) { struct reftable_record rec = { .type = REFTABLE_BLOCK_TYPE_LOG }; @@ -328,14 +344,14 @@ static void t_reftable_log_record_roundtrip(void) reftable_record_key(&rec, &key); n = reftable_record_encode(&rec, dest, REFTABLE_HASH_SIZE_SHA1); - check_int(n, >=, 0); + cl_assert(n >= 0); valtype = reftable_record_val_type(&rec); m = reftable_record_decode(&out, key, valtype, dest, REFTABLE_HASH_SIZE_SHA1, &scratch); - check_int(n, ==, m); + cl_assert_equal_i(n, m); - check(reftable_log_record_equal(&in[i], &out.u.log, - REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_log_record_equal(&in[i], &out.u.log, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_log_record_release(&in[i]); reftable_buf_release(&key); reftable_record_release(&out); @@ -344,7 +360,7 @@ static void t_reftable_log_record_roundtrip(void) reftable_buf_release(&scratch); } -static void t_key_roundtrip(void) +void test_reftable_record__key_roundtrip(void) { uint8_t buffer[1024] = { 0 }; struct string_view dest = { @@ -359,25 +375,28 @@ static void t_key_roundtrip(void) int n, m; uint8_t rt_extra; - check(!reftable_buf_addstr(&last_key, "refs/heads/master")); - check(!reftable_buf_addstr(&key, "refs/tags/bla")); + cl_assert_equal_i(reftable_buf_addstr(&last_key, + "refs/heads/master"), 0); + cl_assert_equal_i(reftable_buf_addstr(&key, + "refs/tags/bla"), 0); extra = 6; n = reftable_encode_key(&restart, dest, last_key, key, extra); - check(!restart); - check_int(n, >, 0); + cl_assert(!restart); + cl_assert(n > 0); - check(!reftable_buf_addstr(&roundtrip, "refs/heads/master")); + cl_assert_equal_i(reftable_buf_addstr(&roundtrip, + "refs/heads/master"), 0); m = reftable_decode_key(&roundtrip, &rt_extra, dest); - check_int(n, ==, m); - check(!reftable_buf_cmp(&key, &roundtrip)); - check_int(rt_extra, ==, extra); + cl_assert_equal_i(n, m); + cl_assert_equal_i(reftable_buf_cmp(&key, &roundtrip), 0); + cl_assert_equal_i(rt_extra, extra); reftable_buf_release(&last_key); reftable_buf_release(&key); reftable_buf_release(&roundtrip); } -static void t_reftable_obj_record_comparison(void) +void test_reftable_record__obj_record_comparison(void) { uint8_t id_bytes[] = { 0, 1, 2, 3, 4, 5, 6 }; @@ -405,21 +424,23 @@ static void t_reftable_obj_record_comparison(void) }; int cmp; - check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1], &cmp)); - check(!cmp); + cl_assert_equal_i(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); - check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[1], &in[2], &cmp)); - check_int(cmp, >, 0); + cl_assert_equal_i(reftable_record_equal(&in[1], &in[2], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0); + cl_assert(cmp > 0); in[1].u.obj.offset_len = in[0].u.obj.offset_len; - check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1], &cmp)); - check(!cmp); + cl_assert(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1) != 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); } -static void t_reftable_obj_record_roundtrip(void) +void test_reftable_record__obj_record_roundtrip(void) { uint8_t testHash1[REFTABLE_HASH_SIZE_SHA1] = { 1, 2, 3, 4, 0 }; uint64_t till9[] = { 1, 2, 3, 4, 500, 600, 700, 800, 9000 }; @@ -460,17 +481,18 @@ static void t_reftable_obj_record_roundtrip(void) int n, m; uint8_t extra; - check(!reftable_record_is_deletion(&in)); + cl_assert_equal_i(reftable_record_is_deletion(&in), 0); t_copy(&in); reftable_record_key(&in, &key); n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); - check_int(n, >, 0); + cl_assert(n > 0); extra = reftable_record_val_type(&in); m = reftable_record_decode(&out, key, extra, dest, REFTABLE_HASH_SIZE_SHA1, &scratch); - check_int(n, ==, m); + cl_assert_equal_i(n, m); - check(reftable_record_equal(&in, &out, REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_record_equal(&in, &out, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_buf_release(&key); reftable_record_release(&out); } @@ -478,7 +500,7 @@ static void t_reftable_obj_record_roundtrip(void) reftable_buf_release(&scratch); } -static void t_reftable_index_record_comparison(void) +void test_reftable_record__index_record_comparison(void) { struct reftable_record in[3] = { { @@ -499,28 +521,33 @@ static void t_reftable_index_record_comparison(void) }; int cmp; - check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master")); - check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master")); - check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch")); + cl_assert_equal_i(reftable_buf_addstr(&in[0].u.idx.last_key, + "refs/heads/master"), 0); + cl_assert_equal_i(reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master"), 0); + cl_assert(reftable_buf_addstr(&in[2].u.idx.last_key, + "refs/heads/branch") == 0); - check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1], &cmp)); - check(!cmp); + cl_assert_equal_i(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); - check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[1], &in[2], &cmp)); - check_int(cmp, >, 0); + cl_assert_equal_i(reftable_record_equal(&in[1], &in[2], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0); + cl_assert(cmp > 0); in[1].u.idx.offset = in[0].u.idx.offset; - check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1], &cmp)); - check(!cmp); + cl_assert(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1) != 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); for (size_t i = 0; i < ARRAY_SIZE(in); i++) reftable_record_release(&in[i]); } -static void t_reftable_index_record_roundtrip(void) +void test_reftable_record__index_record_roundtrip(void) { struct reftable_record in = { .type = REFTABLE_BLOCK_TYPE_INDEX, @@ -543,43 +570,26 @@ static void t_reftable_index_record_roundtrip(void) int n, m; uint8_t extra; - check(!reftable_buf_addstr(&in.u.idx.last_key, "refs/heads/master")); + cl_assert_equal_i(reftable_buf_addstr(&in.u.idx.last_key, + "refs/heads/master"), 0); reftable_record_key(&in, &key); t_copy(&in); - check(!reftable_record_is_deletion(&in)); - check(!reftable_buf_cmp(&key, &in.u.idx.last_key)); + cl_assert_equal_i(reftable_record_is_deletion(&in), 0); + cl_assert_equal_i(reftable_buf_cmp(&key, &in.u.idx.last_key), 0); n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); - check_int(n, >, 0); + cl_assert(n > 0); extra = reftable_record_val_type(&in); - m = reftable_record_decode(&out, key, extra, dest, REFTABLE_HASH_SIZE_SHA1, - &scratch); - check_int(m, ==, n); + m = reftable_record_decode(&out, key, extra, dest, + REFTABLE_HASH_SIZE_SHA1, &scratch); + cl_assert_equal_i(m, n); - check(reftable_record_equal(&in, &out, REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_record_equal(&in, &out, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_record_release(&out); reftable_buf_release(&key); reftable_buf_release(&scratch); reftable_buf_release(&in.u.idx.last_key); } - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_reftable_ref_record_comparison(), "comparison operations work on ref record"); - TEST(t_reftable_log_record_comparison(), "comparison operations work on log record"); - TEST(t_reftable_index_record_comparison(), "comparison operations work on index record"); - TEST(t_reftable_obj_record_comparison(), "comparison operations work on obj record"); - TEST(t_reftable_ref_record_compare_name(), "reftable_ref_record_compare_name works"); - TEST(t_reftable_log_record_compare_key(), "reftable_log_record_compare_key works"); - TEST(t_reftable_log_record_roundtrip(), "record operations work on log record"); - TEST(t_reftable_ref_record_roundtrip(), "record operations work on ref record"); - TEST(t_varint_roundtrip(), "put_var_int and get_var_int work"); - TEST(t_varint_overflow(), "get_var_int notices an integer overflow"); - TEST(t_key_roundtrip(), "reftable_encode_key and reftable_decode_key work"); - TEST(t_reftable_obj_record_roundtrip(), "record operations work on obj record"); - TEST(t_reftable_index_record_roundtrip(), "record operations work on index record"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/u-reftable-stack.c index 2f49c97519..e4ea57138e 100644 --- a/t/unit-tests/t-reftable-stack.c +++ b/t/unit-tests/u-reftable-stack.c @@ -8,9 +8,9 @@ https://developers.google.com/open-source/licenses/bsd #define DISABLE_SIGN_COMPARE_WARNINGS -#include "test-lib.h" -#include "lib-reftable.h" +#include "unit-test.h" #include "dir.h" +#include "lib-reftable.h" #include "reftable/merged.h" #include "reftable/reftable-error.h" #include "reftable/stack.h" @@ -70,11 +70,11 @@ static char *get_tmp_template(int linenumber) static char *get_tmp_dir(int linenumber) { char *dir = get_tmp_template(linenumber); - check(mkdtemp(dir) != NULL); + cl_assert(mkdtemp(dir) != NULL); return dir; } -static void t_read_file(void) +void test_reftable_stack__read_file(void) { char *fn = get_tmp_template(__LINE__); struct tempfile *tmp = mks_tempfile(fn); @@ -84,17 +84,17 @@ static void t_read_file(void) char **names = NULL; const char *want[] = { "line1", "line2", "line3" }; - check_int(fd, >, 0); + cl_assert(fd > 0); n = write_in_full(fd, out, strlen(out)); - check_int(n, ==, strlen(out)); + cl_assert_equal_i(n, strlen(out)); err = close(fd); - check_int(err, >=, 0); + cl_assert(err >= 0); err = read_lines(fn, &names); - check(!err); + cl_assert(!err); for (size_t i = 0; names[i]; i++) - check_str(want[i], names[i]); + cl_assert_equal_s(want[i], names[i]); free_names(names); (void) remove(fn); delete_tempfile(&tmp); @@ -103,8 +103,8 @@ static void t_read_file(void) static int write_test_ref(struct reftable_writer *wr, void *arg) { struct reftable_ref_record *ref = arg; - check(!reftable_writer_set_limits(wr, ref->update_index, - ref->update_index)); + cl_assert_equal_i(reftable_writer_set_limits(wr, + ref->update_index, ref->update_index), 0); return reftable_writer_add_ref(wr, ref); } @@ -112,7 +112,6 @@ static void write_n_ref_tables(struct reftable_stack *st, size_t n) { int disable_auto_compact; - int err; disable_auto_compact = st->opts.disable_auto_compact; st->opts.disable_auto_compact = 1; @@ -126,10 +125,10 @@ static void write_n_ref_tables(struct reftable_stack *st, snprintf(buf, sizeof(buf), "refs/heads/branch-%04"PRIuMAX, (uintmax_t)i); ref.refname = buf; - t_reftable_set_hash(ref.value.val1, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(ref.value.val1, i, REFTABLE_HASH_SHA1); - err = reftable_stack_add(st, &write_test_ref, &ref); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, + &write_test_ref, &ref), 0); } st->opts.disable_auto_compact = disable_auto_compact; @@ -144,12 +143,13 @@ static int write_test_log(struct reftable_writer *wr, void *arg) { struct write_log_arg *wla = arg; - check(!reftable_writer_set_limits(wr, wla->update_index, - wla->update_index)); + cl_assert_equal_i(reftable_writer_set_limits(wr, + wla->update_index, + wla->update_index), 0); return reftable_writer_add_log(wr, wla->log); } -static void t_reftable_stack_add_one(void) +void test_reftable_stack__add_one(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_buf scratch = REFTABLE_BUF_INIT; @@ -158,7 +158,6 @@ static void t_reftable_stack_add_one(void) .default_permissions = 0660, }; struct reftable_stack *st = NULL; - int err; struct reftable_ref_record ref = { .refname = (char *) "HEAD", .update_index = 1, @@ -167,32 +166,37 @@ static void t_reftable_stack_add_one(void) }; struct reftable_ref_record dest = { 0 }; struct stat stat_result = { 0 }; + int err; + err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert(!err); err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); + cl_assert(!err); err = reftable_stack_read_ref(st, ref.refname, &dest); - check(!err); - check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); - check_int(st->tables_len, >, 0); + cl_assert(!err); + cl_assert(reftable_ref_record_equal(&ref, &dest, + REFTABLE_HASH_SIZE_SHA1)); + cl_assert(st->tables_len > 0); #ifndef GIT_WINDOWS_NATIVE - check(!reftable_buf_addstr(&scratch, dir)); - check(!reftable_buf_addstr(&scratch, "/tables.list")); - err = stat(scratch.buf, &stat_result); - check(!err); - check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); + cl_assert_equal_i(reftable_buf_addstr(&scratch, dir), 0); + cl_assert_equal_i(reftable_buf_addstr(&scratch, + "/tables.list"), 0); + cl_assert_equal_i(stat(scratch.buf, &stat_result), 0); + cl_assert_equal_i((stat_result.st_mode & 0777), + opts.default_permissions); reftable_buf_reset(&scratch); - check(!reftable_buf_addstr(&scratch, dir)); - check(!reftable_buf_addstr(&scratch, "/")); + cl_assert_equal_i(reftable_buf_addstr(&scratch, dir), 0); + cl_assert_equal_i(reftable_buf_addstr(&scratch, "/"), 0); /* do not try at home; not an external API for reftable. */ - check(!reftable_buf_addstr(&scratch, st->tables[0]->name)); + cl_assert(!reftable_buf_addstr(&scratch, st->tables[0]->name)); err = stat(scratch.buf, &stat_result); - check(!err); - check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); + cl_assert(!err); + cl_assert_equal_i((stat_result.st_mode & 0777), + opts.default_permissions); #else (void) stat_result; #endif @@ -204,14 +208,13 @@ static void t_reftable_stack_add_one(void) umask(mask); } -static void t_reftable_stack_uptodate(void) +void test_reftable_stack__uptodate(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st1 = NULL; struct reftable_stack *st2 = NULL; char *dir = get_tmp_dir(__LINE__); - int err; struct reftable_ref_record ref1 = { .refname = (char *) "HEAD", .update_index = 1, @@ -229,34 +232,25 @@ static void t_reftable_stack_uptodate(void) /* simulate multi-process access to the same stack by creating two stacks for the same directory. */ - err = reftable_new_stack(&st1, dir, &opts); - check(!err); - - err = reftable_new_stack(&st2, dir, &opts); - check(!err); - - err = reftable_stack_add(st1, write_test_ref, &ref1); - check(!err); - - err = reftable_stack_add(st2, write_test_ref, &ref2); - check_int(err, ==, REFTABLE_OUTDATED_ERROR); - - err = reftable_stack_reload(st2); - check(!err); - - err = reftable_stack_add(st2, write_test_ref, &ref2); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0); + cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_add(st1, write_test_ref, + &ref1), 0); + cl_assert_equal_i(reftable_stack_add(st2, write_test_ref, + &ref2), REFTABLE_OUTDATED_ERROR); + cl_assert_equal_i(reftable_stack_reload(st2), 0); + cl_assert_equal_i(reftable_stack_add(st2, write_test_ref, + &ref2), 0); reftable_stack_destroy(st1); reftable_stack_destroy(st2); clear_dir(dir); } -static void t_reftable_stack_transaction_api(void) +void test_reftable_stack__transaction_api(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err; struct reftable_addition *add = NULL; struct reftable_ref_record ref = { @@ -267,37 +261,32 @@ static void t_reftable_stack_transaction_api(void) }; struct reftable_ref_record dest = { 0 }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); reftable_addition_destroy(add); - err = reftable_stack_new_addition(&add, st, 0); - check(!err); - - err = reftable_addition_add(add, write_test_ref, &ref); - check(!err); - - err = reftable_addition_commit(add); - check(!err); + cl_assert_equal_i(reftable_stack_new_addition(&add, st, 0), 0); + cl_assert_equal_i(reftable_addition_add(add, write_test_ref, + &ref), 0); + cl_assert_equal_i(reftable_addition_commit(add), 0); reftable_addition_destroy(add); - err = reftable_stack_read_ref(st, ref.refname, &dest); - check(!err); - check_int(REFTABLE_REF_SYMREF, ==, dest.value_type); - check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_stack_read_ref(st, ref.refname, + &dest), 0); + cl_assert_equal_i(REFTABLE_REF_SYMREF, dest.value_type); + cl_assert(reftable_ref_record_equal(&ref, &dest, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_ref_record_release(&dest); reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_transaction_with_reload(void) +void test_reftable_stack__transaction_with_reload(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_stack *st1 = NULL, *st2 = NULL; - int err; struct reftable_addition *add = NULL; struct reftable_ref_record refs[2] = { { @@ -315,17 +304,12 @@ static void t_reftable_stack_transaction_with_reload(void) }; struct reftable_ref_record ref = { 0 }; - err = reftable_new_stack(&st1, dir, NULL); - check(!err); - err = reftable_new_stack(&st2, dir, NULL); - check(!err); - - err = reftable_stack_new_addition(&add, st1, 0); - check(!err); - err = reftable_addition_add(add, write_test_ref, &refs[0]); - check(!err); - err = reftable_addition_commit(add); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st1, dir, NULL), 0); + cl_assert_equal_i(reftable_new_stack(&st2, dir, NULL), 0); + cl_assert_equal_i(reftable_stack_new_addition(&add, st1, 0), 0); + cl_assert_equal_i(reftable_addition_add(add, write_test_ref, + &refs[0]), 0); + cl_assert_equal_i(reftable_addition_commit(add), 0); reftable_addition_destroy(add); /* @@ -333,20 +317,20 @@ static void t_reftable_stack_transaction_with_reload(void) * create the addition and lock the stack by default, but allow the * reload to happen when REFTABLE_STACK_NEW_ADDITION_RELOAD is set. */ - err = reftable_stack_new_addition(&add, st2, 0); - check_int(err, ==, REFTABLE_OUTDATED_ERROR); - err = reftable_stack_new_addition(&add, st2, REFTABLE_STACK_NEW_ADDITION_RELOAD); - check(!err); - err = reftable_addition_add(add, write_test_ref, &refs[1]); - check(!err); - err = reftable_addition_commit(add); - check(!err); + cl_assert_equal_i(reftable_stack_new_addition(&add, st2, 0), + REFTABLE_OUTDATED_ERROR); + cl_assert_equal_i(reftable_stack_new_addition(&add, st2, + REFTABLE_STACK_NEW_ADDITION_RELOAD), 0); + cl_assert_equal_i(reftable_addition_add(add, write_test_ref, + &refs[1]), 0); + cl_assert_equal_i(reftable_addition_commit(add), 0); reftable_addition_destroy(add); for (size_t i = 0; i < ARRAY_SIZE(refs); i++) { - err = reftable_stack_read_ref(st2, refs[i].refname, &ref); - check(!err); - check(reftable_ref_record_equal(&refs[i], &ref, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_stack_read_ref(st2, + refs[i].refname, &ref) , 0); + cl_assert(reftable_ref_record_equal(&refs[i], &ref, + REFTABLE_HASH_SIZE_SHA1) != 0); } reftable_ref_record_release(&ref); @@ -355,17 +339,15 @@ static void t_reftable_stack_transaction_with_reload(void) clear_dir(dir); } -static void t_reftable_stack_transaction_api_performs_auto_compaction(void) +void test_reftable_stack__transaction_api_performs_auto_compaction(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = {0}; struct reftable_addition *add = NULL; struct reftable_stack *st = NULL; size_t n = 20; - int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (size_t i = 0; i <= n; i++) { struct reftable_ref_record ref = { @@ -385,14 +367,11 @@ static void t_reftable_stack_transaction_api_performs_auto_compaction(void) */ st->opts.disable_auto_compact = i != n; - err = reftable_stack_new_addition(&add, st, 0); - check(!err); - - err = reftable_addition_add(add, write_test_ref, &ref); - check(!err); - - err = reftable_addition_commit(add); - check(!err); + cl_assert_equal_i(reftable_stack_new_addition(&add, + st, 0), 0); + cl_assert_equal_i(reftable_addition_add(add, + write_test_ref, &ref), 0); + cl_assert_equal_i(reftable_addition_commit(add), 0); reftable_addition_destroy(add); @@ -402,16 +381,16 @@ static void t_reftable_stack_transaction_api_performs_auto_compaction(void) * all tables in the stack. */ if (i != n) - check_int(st->merged->tables_len, ==, i + 1); + cl_assert_equal_i(st->merged->tables_len, i + 1); else - check_int(st->merged->tables_len, ==, 1); + cl_assert_equal_i(st->merged->tables_len, 1); } reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_auto_compaction_fails_gracefully(void) +void test_reftable_stack__auto_compaction_fails_gracefully(void) { struct reftable_ref_record ref = { .refname = (char *) "refs/heads/master", @@ -425,32 +404,31 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void) char *dir = get_tmp_dir(__LINE__); int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); - - err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); - check_int(st->merged->tables_len, ==, 1); - check_int(st->stats.attempts, ==, 0); - check_int(st->stats.failures, ==, 0); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &ref), 0); + cl_assert_equal_i(st->merged->tables_len, 1); + cl_assert_equal_i(st->stats.attempts, 0); + cl_assert_equal_i(st->stats.failures, 0); /* * Lock the newly written table such that it cannot be compacted. * Adding a new table to the stack should not be impacted by this, even * though auto-compaction will now fail. */ - check(!reftable_buf_addstr(&table_path, dir)); - check(!reftable_buf_addstr(&table_path, "/")); - check(!reftable_buf_addstr(&table_path, st->tables[0]->name)); - check(!reftable_buf_addstr(&table_path, ".lock")); + cl_assert(!reftable_buf_addstr(&table_path, dir)); + cl_assert(!reftable_buf_addstr(&table_path, "/")); + cl_assert(!reftable_buf_addstr(&table_path, + st->tables[0]->name)); + cl_assert(!reftable_buf_addstr(&table_path, ".lock")); write_file_buf(table_path.buf, "", 0); ref.update_index = 2; err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); - check_int(st->merged->tables_len, ==, 2); - check_int(st->stats.attempts, ==, 1); - check_int(st->stats.failures, ==, 1); + cl_assert(!err); + cl_assert_equal_i(st->merged->tables_len, 2); + cl_assert_equal_i(st->stats.attempts, 1); + cl_assert_equal_i(st->stats.failures, 1); reftable_stack_destroy(st); reftable_buf_release(&table_path); @@ -462,12 +440,11 @@ static int write_error(struct reftable_writer *wr UNUSED, void *arg) return *((int *)arg); } -static void t_reftable_stack_update_index_check(void) +void test_reftable_stack__update_index_check(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err; struct reftable_ref_record ref1 = { .refname = (char *) "name1", .update_index = 1, @@ -481,39 +458,33 @@ static void t_reftable_stack_update_index_check(void) .value.symref = (char *) "master", }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); - - err = reftable_stack_add(st, write_test_ref, &ref1); - check(!err); - - err = reftable_stack_add(st, write_test_ref, &ref2); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &ref1), 0); + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &ref2), REFTABLE_API_ERROR); reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_lock_failure(void) +void test_reftable_stack__lock_failure(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err, i; + int i; - err = reftable_new_stack(&st, dir, &opts); - check(!err); - for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--) { - err = reftable_stack_add(st, write_error, &i); - check_int(err, ==, i); - } + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--) + cl_assert_equal_i(reftable_stack_add(st, write_error, + &i), i); reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_add(void) +void test_reftable_stack__add(void) { - int err = 0; struct reftable_write_options opts = { .exact_log_message = 1, .default_permissions = 0660, @@ -526,9 +497,10 @@ static void t_reftable_stack_add(void) struct reftable_buf path = REFTABLE_BUF_INIT; struct stat stat_result; size_t i, N = ARRAY_SIZE(refs); + int err = 0; err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert(!err); for (i = 0; i < N; i++) { char buf[256]; @@ -536,66 +508,66 @@ static void t_reftable_stack_add(void) refs[i].refname = xstrdup(buf); refs[i].update_index = i + 1; refs[i].value_type = REFTABLE_REF_VAL1; - t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(refs[i].value.val1, i, + REFTABLE_HASH_SHA1); logs[i].refname = xstrdup(buf); logs[i].update_index = N + i + 1; logs[i].value_type = REFTABLE_LOG_UPDATE; logs[i].value.update.email = xstrdup("identity@invalid"); - t_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); } - for (i = 0; i < N; i++) { - int err = reftable_stack_add(st, write_test_ref, &refs[i]); - check(!err); - } + for (i = 0; i < N; i++) + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &refs[i]), 0); for (i = 0; i < N; i++) { struct write_log_arg arg = { .log = &logs[i], .update_index = reftable_stack_next_update_index(st), }; - int err = reftable_stack_add(st, write_test_log, &arg); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg), 0); } - err = reftable_stack_compact_all(st, NULL); - check(!err); + cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0); for (i = 0; i < N; i++) { struct reftable_ref_record dest = { 0 }; - int err = reftable_stack_read_ref(st, refs[i].refname, &dest); - check(!err); - check(reftable_ref_record_equal(&dest, refs + i, - REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_stack_read_ref(st, + refs[i].refname, &dest), 0); + cl_assert(reftable_ref_record_equal(&dest, refs + i, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_ref_record_release(&dest); } for (i = 0; i < N; i++) { struct reftable_log_record dest = { 0 }; - int err = reftable_stack_read_log(st, refs[i].refname, &dest); - check(!err); - check(reftable_log_record_equal(&dest, logs + i, - REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_stack_read_log(st, + refs[i].refname, &dest), 0); + cl_assert(reftable_log_record_equal(&dest, logs + i, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_log_record_release(&dest); } #ifndef GIT_WINDOWS_NATIVE - check(!reftable_buf_addstr(&path, dir)); - check(!reftable_buf_addstr(&path, "/tables.list")); - err = stat(path.buf, &stat_result); - check(!err); - check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); + cl_assert_equal_i(reftable_buf_addstr(&path, dir), 0); + cl_assert_equal_i(reftable_buf_addstr(&path, "/tables.list"), 0); + cl_assert_equal_i(stat(path.buf, &stat_result), 0); + cl_assert_equal_i((stat_result.st_mode & 0777), opts.default_permissions); reftable_buf_reset(&path); - check(!reftable_buf_addstr(&path, dir)); - check(!reftable_buf_addstr(&path, "/")); + cl_assert_equal_i(reftable_buf_addstr(&path, dir), 0); + cl_assert_equal_i(reftable_buf_addstr(&path, "/"), 0); /* do not try at home; not an external API for reftable. */ - check(!reftable_buf_addstr(&path, st->tables[0]->name)); + cl_assert(!reftable_buf_addstr(&path, st->tables[0]->name)); err = stat(path.buf, &stat_result); - check(!err); - check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); + cl_assert(!err); + cl_assert_equal_i((stat_result.st_mode & 0777), + opts.default_permissions); #else (void) stat_result; #endif @@ -610,7 +582,7 @@ static void t_reftable_stack_add(void) clear_dir(dir); } -static void t_reftable_stack_iterator(void) +void test_reftable_stack__iterator(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; @@ -621,27 +593,27 @@ static void t_reftable_stack_iterator(void) size_t N = ARRAY_SIZE(refs), i; int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (i = 0; i < N; i++) { refs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); refs[i].update_index = i + 1; refs[i].value_type = REFTABLE_REF_VAL1; - t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(refs[i].value.val1, i, + REFTABLE_HASH_SHA1); logs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); logs[i].update_index = i + 1; logs[i].value_type = REFTABLE_LOG_UPDATE; logs[i].value.update.email = xstrdup("johndoe@invalid"); logs[i].value.update.message = xstrdup("commit\n"); - t_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); } - for (i = 0; i < N; i++) { - err = reftable_stack_add(st, write_test_ref, &refs[i]); - check(!err); - } + for (i = 0; i < N; i++) + cl_assert_equal_i(reftable_stack_add(st, + write_test_ref, &refs[i]), 0); for (i = 0; i < N; i++) { struct write_log_arg arg = { @@ -649,8 +621,8 @@ static void t_reftable_stack_iterator(void) .update_index = reftable_stack_next_update_index(st), }; - err = reftable_stack_add(st, write_test_log, &arg); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, + write_test_log, &arg), 0); } reftable_stack_init_ref_iterator(st, &it); @@ -661,16 +633,16 @@ static void t_reftable_stack_iterator(void) err = reftable_iterator_next_ref(&it, &ref); if (err > 0) break; - check(!err); - check(reftable_ref_record_equal(&ref, &refs[i], REFTABLE_HASH_SIZE_SHA1)); + cl_assert(!err); + cl_assert(reftable_ref_record_equal(&ref, &refs[i], + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_ref_record_release(&ref); } - check_int(i, ==, N); + cl_assert_equal_i(i, N); reftable_iterator_destroy(&it); - err = reftable_stack_init_log_iterator(st, &it); - check(!err); + cl_assert_equal_i(reftable_stack_init_log_iterator(st, &it), 0); reftable_iterator_seek_log(&it, logs[0].refname); for (i = 0; ; i++) { @@ -679,11 +651,12 @@ static void t_reftable_stack_iterator(void) err = reftable_iterator_next_log(&it, &log); if (err > 0) break; - check(!err); - check(reftable_log_record_equal(&log, &logs[i], REFTABLE_HASH_SIZE_SHA1)); + cl_assert(!err); + cl_assert(reftable_log_record_equal(&log, &logs[i], + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_log_record_release(&log); } - check_int(i, ==, N); + cl_assert_equal_i(i, N); reftable_stack_destroy(st); reftable_iterator_destroy(&it); @@ -694,9 +667,8 @@ static void t_reftable_stack_iterator(void) clear_dir(dir); } -static void t_reftable_stack_log_normalize(void) +void test_reftable_stack__log_normalize(void) { - int err = 0; struct reftable_write_options opts = { 0, }; @@ -721,28 +693,26 @@ static void t_reftable_stack_log_normalize(void) .update_index = 1, }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); input.value.update.message = (char *) "one\ntwo"; - err = reftable_stack_add(st, write_test_log, &arg); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg), REFTABLE_API_ERROR); input.value.update.message = (char *) "one"; - err = reftable_stack_add(st, write_test_log, &arg); - check(!err); - - err = reftable_stack_read_log(st, input.refname, &dest); - check(!err); - check_str(dest.value.update.message, "one\n"); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg), 0); + cl_assert_equal_i(reftable_stack_read_log(st, input.refname, + &dest), 0); + cl_assert_equal_s(dest.value.update.message, "one\n"); input.value.update.message = (char *) "two\n"; arg.update_index = 2; - err = reftable_stack_add(st, write_test_log, &arg); - check(!err); - err = reftable_stack_read_log(st, input.refname, &dest); - check(!err); - check_str(dest.value.update.message, "two\n"); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg), 0); + cl_assert_equal_i(reftable_stack_read_log(st, input.refname, + &dest), 0); + cl_assert_equal_s(dest.value.update.message, "two\n"); /* cleanup */ reftable_stack_destroy(st); @@ -750,20 +720,18 @@ static void t_reftable_stack_log_normalize(void) clear_dir(dir); } -static void t_reftable_stack_tombstone(void) +void test_reftable_stack__tombstone(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err; struct reftable_ref_record refs[2] = { 0 }; struct reftable_log_record logs[2] = { 0 }; size_t i, N = ARRAY_SIZE(refs); struct reftable_ref_record dest = { 0 }; struct reftable_log_record log_dest = { 0 }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); /* even entries add the refs, odd entries delete them. */ for (i = 0; i < N; i++) { @@ -772,8 +740,8 @@ static void t_reftable_stack_tombstone(void) refs[i].update_index = i + 1; if (i % 2 == 0) { refs[i].value_type = REFTABLE_REF_VAL1; - t_reftable_set_hash(refs[i].value.val1, i, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(refs[i].value.val1, i, + REFTABLE_HASH_SHA1); } logs[i].refname = xstrdup(buf); @@ -785,42 +753,36 @@ static void t_reftable_stack_tombstone(void) logs[i].update_index = 1; if (i % 2 == 0) { logs[i].value_type = REFTABLE_LOG_UPDATE; - t_reftable_set_hash(logs[i].value.update.new_hash, i, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1); logs[i].value.update.email = xstrdup("identity@invalid"); } } - for (i = 0; i < N; i++) { - int err = reftable_stack_add(st, write_test_ref, &refs[i]); - check(!err); - } + for (i = 0; i < N; i++) + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, &refs[i]), 0); for (i = 0; i < N; i++) { struct write_log_arg arg = { .log = &logs[i], .update_index = reftable_stack_next_update_index(st), }; - int err = reftable_stack_add(st, write_test_log, &arg); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, + write_test_log, &arg), 0); } - err = reftable_stack_read_ref(st, "branch", &dest); - check_int(err, ==, 1); + cl_assert_equal_i(reftable_stack_read_ref(st, "branch", + &dest), 1); reftable_ref_record_release(&dest); - err = reftable_stack_read_log(st, "branch", &log_dest); - check_int(err, ==, 1); + cl_assert_equal_i(reftable_stack_read_log(st, "branch", + &log_dest), 1); reftable_log_record_release(&log_dest); - err = reftable_stack_compact_all(st, NULL); - check(!err); - - err = reftable_stack_read_ref(st, "branch", &dest); - check_int(err, ==, 1); - - err = reftable_stack_read_log(st, "branch", &log_dest); - check_int(err, ==, 1); + cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0); + cl_assert_equal_i(reftable_stack_read_ref(st, "branch", + &dest), 1); + cl_assert_equal_i(reftable_stack_read_log(st, "branch", + &log_dest), 1); reftable_ref_record_release(&dest); reftable_log_record_release(&log_dest); @@ -833,12 +795,11 @@ static void t_reftable_stack_tombstone(void) clear_dir(dir); } -static void t_reftable_stack_hash_id(void) +void test_reftable_stack__hash_id(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err; struct reftable_ref_record ref = { .refname = (char *) "master", @@ -852,62 +813,57 @@ static void t_reftable_stack_hash_id(void) struct reftable_stack *st_default = NULL; struct reftable_ref_record dest = { 0 }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); - - err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &ref), 0); /* can't read it with the wrong hash ID. */ - err = reftable_new_stack(&st32, dir, &opts32); - check_int(err, ==, REFTABLE_FORMAT_ERROR); + cl_assert_equal_i(reftable_new_stack(&st32, dir, + &opts32), REFTABLE_FORMAT_ERROR); /* check that we can read it back with default opts too. */ - err = reftable_new_stack(&st_default, dir, &opts_default); - check(!err); - - err = reftable_stack_read_ref(st_default, "master", &dest); - check(!err); - - check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_new_stack(&st_default, dir, + &opts_default), 0); + cl_assert_equal_i(reftable_stack_read_ref(st_default, "master", + &dest), 0); + cl_assert(reftable_ref_record_equal(&ref, &dest, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_ref_record_release(&dest); reftable_stack_destroy(st); reftable_stack_destroy(st_default); clear_dir(dir); } -static void t_suggest_compaction_segment(void) +void test_reftable_stack__suggest_compaction_segment(void) { uint64_t sizes[] = { 512, 64, 17, 16, 9, 9, 9, 16, 2, 16 }; struct segment min = suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2); - check_int(min.start, ==, 1); - check_int(min.end, ==, 10); + cl_assert_equal_i(min.start, 1); + cl_assert_equal_i(min.end, 10); } -static void t_suggest_compaction_segment_nothing(void) +void test_reftable_stack__suggest_compaction_segment_nothing(void) { uint64_t sizes[] = { 64, 32, 16, 8, 4, 2 }; struct segment result = suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2); - check_int(result.start, ==, result.end); + cl_assert_equal_i(result.start, result.end); } -static void t_reflog_expire(void) +void test_reftable_stack__reflog_expire(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; struct reftable_log_record logs[20] = { 0 }; size_t i, N = ARRAY_SIZE(logs) - 1; - int err; struct reftable_log_expiry_config expiry = { .time = 10, }; struct reftable_log_record log = { 0 }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (i = 1; i <= N; i++) { char buf[256]; @@ -918,8 +874,8 @@ static void t_reflog_expire(void) logs[i].value_type = REFTABLE_LOG_UPDATE; logs[i].value.update.time = i; logs[i].value.update.email = xstrdup("identity@invalid"); - t_reftable_set_hash(logs[i].value.update.new_hash, i, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); } for (i = 1; i <= N; i++) { @@ -927,31 +883,23 @@ static void t_reflog_expire(void) .log = &logs[i], .update_index = reftable_stack_next_update_index(st), }; - int err = reftable_stack_add(st, write_test_log, &arg); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg), 0); } - err = reftable_stack_compact_all(st, NULL); - check(!err); - - err = reftable_stack_compact_all(st, &expiry); - check(!err); - - err = reftable_stack_read_log(st, logs[9].refname, &log); - check_int(err, ==, 1); - - err = reftable_stack_read_log(st, logs[11].refname, &log); - check(!err); + cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0); + cl_assert_equal_i(reftable_stack_compact_all(st, &expiry), 0); + cl_assert_equal_i(reftable_stack_read_log(st, logs[9].refname, + &log), 1); + cl_assert_equal_i(reftable_stack_read_log(st, logs[11].refname, + &log), 0); expiry.min_update_index = 15; - err = reftable_stack_compact_all(st, &expiry); - check(!err); - - err = reftable_stack_read_log(st, logs[14].refname, &log); - check_int(err, ==, 1); - - err = reftable_stack_read_log(st, logs[16].refname, &log); - check(!err); + cl_assert_equal_i(reftable_stack_compact_all(st, &expiry), 0); + cl_assert_equal_i(reftable_stack_read_log(st, logs[14].refname, + &log), 1); + cl_assert_equal_i(reftable_stack_read_log(st, logs[16].refname, + &log), 0); /* cleanup */ reftable_stack_destroy(st); @@ -963,26 +911,21 @@ static void t_reflog_expire(void) static int write_nothing(struct reftable_writer *wr, void *arg UNUSED) { - check(!reftable_writer_set_limits(wr, 1, 1)); + cl_assert_equal_i(reftable_writer_set_limits(wr, 1, 1), 0); return 0; } -static void t_empty_add(void) +void test_reftable_stack__empty_add(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err; char *dir = get_tmp_dir(__LINE__); struct reftable_stack *st2 = NULL; - err = reftable_new_stack(&st, dir, &opts); - check(!err); - - err = reftable_stack_add(st, write_nothing, NULL); - check(!err); - - err = reftable_new_stack(&st2, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_add(st, write_nothing, + NULL), 0); + cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0); clear_dir(dir); reftable_stack_destroy(st); reftable_stack_destroy(st2); @@ -998,18 +941,17 @@ static int fastlogN(uint64_t sz, uint64_t N) return l - 1; } -static void t_reftable_stack_auto_compaction(void) +void test_reftable_stack__auto_compaction(void) { struct reftable_write_options opts = { .disable_auto_compact = 1, }; struct reftable_stack *st = NULL; char *dir = get_tmp_dir(__LINE__); - int err; size_t i, N = 100; + int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (i = 0; i < N; i++) { char name[100]; @@ -1022,32 +964,31 @@ static void t_reftable_stack_auto_compaction(void) snprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i); err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); + cl_assert(!err); err = reftable_stack_auto_compact(st); - check(!err); - check(i < 2 || st->merged->tables_len < 2 * fastlogN(i, 2)); + cl_assert(!err); + cl_assert(i < 2 || st->merged->tables_len < 2 * fastlogN(i, 2)); } - check_int(reftable_stack_compaction_stats(st)->entries_written, <, - (uint64_t)(N * fastlogN(N, 2))); + cl_assert(reftable_stack_compaction_stats(st)->entries_written < + (uint64_t)(N * fastlogN(N, 2))); reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_auto_compaction_factor(void) +void test_reftable_stack__auto_compaction_factor(void) { struct reftable_write_options opts = { .auto_compaction_factor = 5, }; struct reftable_stack *st = NULL; char *dir = get_tmp_dir(__LINE__); - int err; size_t N = 100; + int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (size_t i = 0; i < N; i++) { char name[20]; @@ -1059,16 +1000,16 @@ static void t_reftable_stack_auto_compaction_factor(void) xsnprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i); err = reftable_stack_add(st, &write_test_ref, &ref); - check(!err); + cl_assert(!err); - check(i < 5 || st->merged->tables_len < 5 * fastlogN(i, 5)); + cl_assert(i < 5 || st->merged->tables_len < 5 * fastlogN(i, 5)); } reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_auto_compaction_with_locked_tables(void) +void test_reftable_stack__auto_compaction_with_locked_tables(void) { struct reftable_write_options opts = { .disable_auto_compact = 1, @@ -1078,21 +1019,20 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void) char *dir = get_tmp_dir(__LINE__); int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); write_n_ref_tables(st, 5); - check_int(st->merged->tables_len, ==, 5); + cl_assert_equal_i(st->merged->tables_len, 5); /* * Given that all tables we have written should be roughly the same * size, we expect that auto-compaction will want to compact all of the * tables. Locking any of the tables will keep it from doing so. */ - check(!reftable_buf_addstr(&buf, dir)); - check(!reftable_buf_addstr(&buf, "/")); - check(!reftable_buf_addstr(&buf, st->tables[2]->name)); - check(!reftable_buf_addstr(&buf, ".lock")); + cl_assert(!reftable_buf_addstr(&buf, dir)); + cl_assert(!reftable_buf_addstr(&buf, "/")); + cl_assert(!reftable_buf_addstr(&buf, st->tables[2]->name)); + cl_assert(!reftable_buf_addstr(&buf, ".lock")); write_file_buf(buf.buf, "", 0); /* @@ -1102,25 +1042,23 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void) * only compact the newest two tables. */ err = reftable_stack_auto_compact(st); - check(!err); - check_int(st->stats.failures, ==, 0); - check_int(st->merged->tables_len, ==, 4); + cl_assert(!err); + cl_assert_equal_i(st->stats.failures, 0); + cl_assert_equal_i(st->merged->tables_len, 4); reftable_stack_destroy(st); reftable_buf_release(&buf); clear_dir(dir); } -static void t_reftable_stack_add_performs_auto_compaction(void) +void test_reftable_stack__add_performs_auto_compaction(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; char *dir = get_tmp_dir(__LINE__); - int err; size_t i, n = 20; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (i = 0; i <= n; i++) { struct reftable_ref_record ref = { @@ -1140,8 +1078,8 @@ static void t_reftable_stack_add_performs_auto_compaction(void) snprintf(buf, sizeof(buf), "branch-%04"PRIuMAX, (uintmax_t)i); ref.refname = buf; - err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, + write_test_ref, &ref), 0); /* * The stack length should grow continuously for all runs where @@ -1149,16 +1087,16 @@ static void t_reftable_stack_add_performs_auto_compaction(void) * all tables in the stack. */ if (i != n) - check_int(st->merged->tables_len, ==, i + 1); + cl_assert_equal_i(st->merged->tables_len, i + 1); else - check_int(st->merged->tables_len, ==, 1); + cl_assert_equal_i(st->merged->tables_len, 1); } reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_compaction_with_locked_tables(void) +void test_reftable_stack__compaction_with_locked_tables(void) { struct reftable_write_options opts = { .disable_auto_compact = 1, @@ -1168,17 +1106,16 @@ static void t_reftable_stack_compaction_with_locked_tables(void) char *dir = get_tmp_dir(__LINE__); int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); write_n_ref_tables(st, 3); - check_int(st->merged->tables_len, ==, 3); + cl_assert_equal_i(st->merged->tables_len, 3); /* Lock one of the tables that we're about to compact. */ - check(!reftable_buf_addstr(&buf, dir)); - check(!reftable_buf_addstr(&buf, "/")); - check(!reftable_buf_addstr(&buf, st->tables[1]->name)); - check(!reftable_buf_addstr(&buf, ".lock")); + cl_assert(!reftable_buf_addstr(&buf, dir)); + cl_assert(!reftable_buf_addstr(&buf, "/")); + cl_assert(!reftable_buf_addstr(&buf, st->tables[1]->name)); + cl_assert(!reftable_buf_addstr(&buf, ".lock")); write_file_buf(buf.buf, "", 0); /* @@ -1186,36 +1123,31 @@ static void t_reftable_stack_compaction_with_locked_tables(void) * compact all tables. */ err = reftable_stack_compact_all(st, NULL); - check_int(err, ==, REFTABLE_LOCK_ERROR); - check_int(st->stats.failures, ==, 1); - check_int(st->merged->tables_len, ==, 3); + cl_assert_equal_i(err, REFTABLE_LOCK_ERROR); + cl_assert_equal_i(st->stats.failures, 1); + cl_assert_equal_i(st->merged->tables_len, 3); reftable_stack_destroy(st); reftable_buf_release(&buf); clear_dir(dir); } -static void t_reftable_stack_compaction_concurrent(void) +void test_reftable_stack__compaction_concurrent(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st1 = NULL, *st2 = NULL; char *dir = get_tmp_dir(__LINE__); - int err; - err = reftable_new_stack(&st1, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0); write_n_ref_tables(st1, 3); - err = reftable_new_stack(&st2, dir, &opts); - check(!err); - - err = reftable_stack_compact_all(st1, NULL); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_compact_all(st1, NULL), 0); reftable_stack_destroy(st1); reftable_stack_destroy(st2); - check_int(count_dir_entries(dir), ==, 2); + cl_assert_equal_i(count_dir_entries(dir), 2); clear_dir(dir); } @@ -1228,32 +1160,24 @@ static void unclean_stack_close(struct reftable_stack *st) REFTABLE_FREE_AND_NULL(st->tables); } -static void t_reftable_stack_compaction_concurrent_clean(void) +void test_reftable_stack__compaction_concurrent_clean(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st1 = NULL, *st2 = NULL, *st3 = NULL; char *dir = get_tmp_dir(__LINE__); - int err; - err = reftable_new_stack(&st1, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0); write_n_ref_tables(st1, 3); - err = reftable_new_stack(&st2, dir, &opts); - check(!err); - - err = reftable_stack_compact_all(st1, NULL); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_compact_all(st1, NULL), 0); unclean_stack_close(st1); unclean_stack_close(st2); - err = reftable_new_stack(&st3, dir, &opts); - check(!err); - - err = reftable_stack_clean(st3); - check(!err); - check_int(count_dir_entries(dir), ==, 2); + cl_assert_equal_i(reftable_new_stack(&st3, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_clean(st3), 0); + cl_assert_equal_i(count_dir_entries(dir), 2); reftable_stack_destroy(st1); reftable_stack_destroy(st2); @@ -1262,7 +1186,7 @@ static void t_reftable_stack_compaction_concurrent_clean(void) clear_dir(dir); } -static void t_reftable_stack_read_across_reload(void) +void test_reftable_stack__read_across_reload(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st1 = NULL, *st2 = NULL; @@ -1272,37 +1196,35 @@ static void t_reftable_stack_read_across_reload(void) int err; /* Create a first stack and set up an iterator for it. */ - err = reftable_new_stack(&st1, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0); write_n_ref_tables(st1, 2); - check_int(st1->merged->tables_len, ==, 2); + cl_assert_equal_i(st1->merged->tables_len, 2); reftable_stack_init_ref_iterator(st1, &it); - err = reftable_iterator_seek_ref(&it, ""); - check(!err); + cl_assert_equal_i(reftable_iterator_seek_ref(&it, ""), 0); /* Set up a second stack for the same directory and compact it. */ err = reftable_new_stack(&st2, dir, &opts); - check(!err); - check_int(st2->merged->tables_len, ==, 2); + cl_assert(!err); + cl_assert_equal_i(st2->merged->tables_len, 2); err = reftable_stack_compact_all(st2, NULL); - check(!err); - check_int(st2->merged->tables_len, ==, 1); + cl_assert(!err); + cl_assert_equal_i(st2->merged->tables_len, 1); /* * Verify that we can continue to use the old iterator even after we * have reloaded its stack. */ err = reftable_stack_reload(st1); - check(!err); - check_int(st1->merged->tables_len, ==, 1); + cl_assert(!err); + cl_assert_equal_i(st1->merged->tables_len, 1); err = reftable_iterator_next_ref(&it, &rec); - check(!err); - check_str(rec.refname, "refs/heads/branch-0000"); + cl_assert(!err); + cl_assert_equal_s(rec.refname, "refs/heads/branch-0000"); err = reftable_iterator_next_ref(&it, &rec); - check(!err); - check_str(rec.refname, "refs/heads/branch-0001"); + cl_assert(!err); + cl_assert_equal_s(rec.refname, "refs/heads/branch-0001"); err = reftable_iterator_next_ref(&it, &rec); - check_int(err, >, 0); + cl_assert(err > 0); reftable_ref_record_release(&rec); reftable_iterator_destroy(&it); @@ -1311,7 +1233,7 @@ static void t_reftable_stack_read_across_reload(void) clear_dir(dir); } -static void t_reftable_stack_reload_with_missing_table(void) +void test_reftable_stack__reload_with_missing_table(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; @@ -1322,46 +1244,40 @@ static void t_reftable_stack_reload_with_missing_table(void) int err; /* Create a first stack and set up an iterator for it. */ - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); write_n_ref_tables(st, 2); - check_int(st->merged->tables_len, ==, 2); + cl_assert_equal_i(st->merged->tables_len, 2); reftable_stack_init_ref_iterator(st, &it); - err = reftable_iterator_seek_ref(&it, ""); - check(!err); + cl_assert_equal_i(reftable_iterator_seek_ref(&it, ""), 0); /* * Update the tables.list file with some garbage data, while reusing * our old tables. This should trigger a partial reload of the stack, * where we try to reuse our old tables. */ - check(!reftable_buf_addstr(&content, st->tables[0]->name)); - check(!reftable_buf_addstr(&content, "\n")); - check(!reftable_buf_addstr(&content, st->tables[1]->name)); - check(!reftable_buf_addstr(&content, "\n")); - check(!reftable_buf_addstr(&content, "garbage\n")); - check(!reftable_buf_addstr(&table_path, st->list_file)); - check(!reftable_buf_addstr(&table_path, ".lock")); + cl_assert(!reftable_buf_addstr(&content, st->tables[0]->name)); + cl_assert(!reftable_buf_addstr(&content, "\n")); + cl_assert(!reftable_buf_addstr(&content, st->tables[1]->name)); + cl_assert(!reftable_buf_addstr(&content, "\n")); + cl_assert(!reftable_buf_addstr(&content, "garbage\n")); + cl_assert(!reftable_buf_addstr(&table_path, st->list_file)); + cl_assert(!reftable_buf_addstr(&table_path, ".lock")); write_file_buf(table_path.buf, content.buf, content.len); - err = rename(table_path.buf, st->list_file); - check(!err); + cl_assert_equal_i(rename(table_path.buf, st->list_file), 0); err = reftable_stack_reload(st); - check_int(err, ==, -4); - check_int(st->merged->tables_len, ==, 2); + cl_assert_equal_i(err, -4); + cl_assert_equal_i(st->merged->tables_len, 2); /* * Even though the reload has failed, we should be able to continue * using the iterator. */ - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - check_str(rec.refname, "refs/heads/branch-0000"); - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - check_str(rec.refname, "refs/heads/branch-0001"); - err = reftable_iterator_next_ref(&it, &rec); - check_int(err, >, 0); + cl_assert_equal_i(reftable_iterator_next_ref(&it, &rec), 0); + cl_assert_equal_s(rec.refname, "refs/heads/branch-0000"); + cl_assert_equal_i(reftable_iterator_next_ref(&it, &rec), 0); + cl_assert_equal_s(rec.refname, "refs/heads/branch-0001"); + cl_assert(reftable_iterator_next_ref(&it, &rec) > 0); reftable_ref_record_release(&rec); reftable_iterator_destroy(&it); @@ -1374,12 +1290,13 @@ static void t_reftable_stack_reload_with_missing_table(void) static int write_limits_after_ref(struct reftable_writer *wr, void *arg) { struct reftable_ref_record *ref = arg; - check(!reftable_writer_set_limits(wr, ref->update_index, ref->update_index)); - check(!reftable_writer_add_ref(wr, ref)); + cl_assert_equal_i(reftable_writer_set_limits(wr, + ref->update_index, ref->update_index), 0); + cl_assert_equal_i(reftable_writer_add_ref(wr, ref), 0); return reftable_writer_set_limits(wr, ref->update_index, ref->update_index); } -static void t_reftable_invalid_limit_updates(void) +void test_reftable_stack__invalid_limit_updates(void) { struct reftable_ref_record ref = { .refname = (char *) "HEAD", @@ -1393,59 +1310,22 @@ static void t_reftable_invalid_limit_updates(void) struct reftable_addition *add = NULL; char *dir = get_tmp_dir(__LINE__); struct reftable_stack *st = NULL; - int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); reftable_addition_destroy(add); - err = reftable_stack_new_addition(&add, st, 0); - check(!err); + cl_assert_equal_i(reftable_stack_new_addition(&add, st, 0), 0); /* * write_limits_after_ref also updates the update indexes after adding * the record. This should cause an err to be returned, since the limits * must be set at the start. */ - err = reftable_addition_add(add, write_limits_after_ref, &ref); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_addition_add(add, + write_limits_after_ref, &ref), REFTABLE_API_ERROR); reftable_addition_destroy(add); reftable_stack_destroy(st); clear_dir(dir); } - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_empty_add(), "empty addition to stack"); - TEST(t_read_file(), "read_lines works"); - TEST(t_reflog_expire(), "expire reflog entries"); - TEST(t_reftable_invalid_limit_updates(), "prevent limit updates after adding records"); - TEST(t_reftable_stack_add(), "add multiple refs and logs to stack"); - TEST(t_reftable_stack_add_one(), "add a single ref record to stack"); - TEST(t_reftable_stack_add_performs_auto_compaction(), "addition to stack triggers auto-compaction"); - TEST(t_reftable_stack_auto_compaction(), "stack must form geometric sequence after compaction"); - TEST(t_reftable_stack_auto_compaction_factor(), "auto-compaction with non-default geometric factor"); - TEST(t_reftable_stack_auto_compaction_fails_gracefully(), "failure on auto-compaction"); - TEST(t_reftable_stack_auto_compaction_with_locked_tables(), "auto compaction with locked tables"); - TEST(t_reftable_stack_compaction_concurrent(), "compaction with concurrent stack"); - TEST(t_reftable_stack_compaction_concurrent_clean(), "compaction with unclean stack shutdown"); - TEST(t_reftable_stack_compaction_with_locked_tables(), "compaction with locked tables"); - TEST(t_reftable_stack_hash_id(), "read stack with wrong hash ID"); - TEST(t_reftable_stack_iterator(), "log and ref iterator for reftable stack"); - TEST(t_reftable_stack_lock_failure(), "stack addition with lockfile failure"); - TEST(t_reftable_stack_log_normalize(), "log messages should be normalized"); - TEST(t_reftable_stack_read_across_reload(), "stack iterators work across reloads"); - TEST(t_reftable_stack_reload_with_missing_table(), "stack iteration with garbage tables"); - TEST(t_reftable_stack_tombstone(), "'tombstone' refs in stack"); - TEST(t_reftable_stack_transaction_api(), "update transaction to stack"); - TEST(t_reftable_stack_transaction_with_reload(), "transaction with reload"); - TEST(t_reftable_stack_transaction_api_performs_auto_compaction(), "update transaction triggers auto-compaction"); - TEST(t_reftable_stack_update_index_check(), "update transactions with equal update indices"); - TEST(t_reftable_stack_uptodate(), "stack must be reloaded before ref update"); - TEST(t_suggest_compaction_segment(), "suggest_compaction_segment with basic input"); - TEST(t_suggest_compaction_segment_nothing(), "suggest_compaction_segment with pre-compacted input"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-table.c b/t/unit-tests/u-reftable-table.c index 7e1eb533d0..14fae8b199 100644 --- a/t/unit-tests/t-reftable-table.c +++ b/t/unit-tests/u-reftable-table.c @@ -1,4 +1,4 @@ -#include "test-lib.h" +#include "unit-test.h" #include "lib-reftable.h" #include "reftable/blocksource.h" #include "reftable/constants.h" @@ -6,7 +6,7 @@ #include "reftable/table.h" #include "strbuf.h" -static int t_table_seek_once(void) +void test_reftable_table__seek_once(void) { struct reftable_ref_record records[] = { { @@ -22,32 +22,32 @@ static int t_table_seek_once(void) struct reftable_buf buf = REFTABLE_BUF_INIT; int ret; - t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); + cl_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); block_source_from_buf(&source, &buf); ret = reftable_table_new(&table, &source, "name"); - check(!ret); + cl_assert(!ret); reftable_table_init_ref_iterator(table, &it); ret = reftable_iterator_seek_ref(&it, ""); - check(!ret); + cl_assert(!ret); ret = reftable_iterator_next_ref(&it, &ref); - check(!ret); + cl_assert(!ret); - ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); - check_int(ret, ==, 1); + ret = reftable_ref_record_equal(&ref, &records[0], + REFTABLE_HASH_SIZE_SHA1); + cl_assert_equal_i(ret, 1); ret = reftable_iterator_next_ref(&it, &ref); - check_int(ret, ==, 1); + cl_assert_equal_i(ret, 1); reftable_ref_record_release(&ref); reftable_iterator_destroy(&it); reftable_table_decref(table); reftable_buf_release(&buf); - return 0; } -static int t_table_reseek(void) +void test_reftable_table__reseek(void) { struct reftable_ref_record records[] = { { @@ -63,35 +63,35 @@ static int t_table_reseek(void) struct reftable_buf buf = REFTABLE_BUF_INIT; int ret; - t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); + cl_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), + NULL, 0, NULL); block_source_from_buf(&source, &buf); ret = reftable_table_new(&table, &source, "name"); - check(!ret); + cl_assert(!ret); reftable_table_init_ref_iterator(table, &it); for (size_t i = 0; i < 5; i++) { ret = reftable_iterator_seek_ref(&it, ""); - check(!ret); + cl_assert(!ret); ret = reftable_iterator_next_ref(&it, &ref); - check(!ret); + cl_assert(!ret); ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); - check_int(ret, ==, 1); + cl_assert_equal_i(ret, 1); ret = reftable_iterator_next_ref(&it, &ref); - check_int(ret, ==, 1); + cl_assert_equal_i(ret, 1); } reftable_ref_record_release(&ref); reftable_iterator_destroy(&it); reftable_table_decref(table); reftable_buf_release(&buf); - return 0; } -static int t_table_block_iterator(void) +void test_reftable_table__block_iterator(void) { struct reftable_block_source source = { 0 }; struct reftable_table_iterator it = { 0 }; @@ -147,14 +147,14 @@ static int t_table_block_iterator(void) (uintmax_t) i); } - t_reftable_write_to_buf(&buf, records, nrecords, NULL, 0, NULL); + cl_reftable_write_to_buf(&buf, records, nrecords, NULL, 0, NULL); block_source_from_buf(&source, &buf); ret = reftable_table_new(&table, &source, "name"); - check(!ret); + cl_assert(!ret); ret = reftable_table_iterator_init(&it, table); - check(!ret); + cl_assert(!ret); for (size_t i = 0; i < ARRAY_SIZE(expected_blocks); i++) { struct reftable_iterator record_it = { 0 }; @@ -163,22 +163,26 @@ static int t_table_block_iterator(void) }; ret = reftable_table_iterator_next(&it, &block); - check(!ret); + cl_assert(!ret); - check_int(block->block_type, ==, expected_blocks[i].block_type); - check_int(block->header_off, ==, expected_blocks[i].header_off); - check_int(block->restart_count, ==, expected_blocks[i].restart_count); + cl_assert_equal_i(block->block_type, + expected_blocks[i].block_type); + cl_assert_equal_i(block->header_off, + expected_blocks[i].header_off); + cl_assert_equal_i(block->restart_count, + expected_blocks[i].restart_count); ret = reftable_block_init_iterator(block, &record_it); - check(!ret); + cl_assert(!ret); for (size_t j = 0; ; j++) { ret = iterator_next(&record_it, &record); if (ret > 0) { - check_int(j, ==, expected_blocks[i].record_count); + cl_assert_equal_i(j, + expected_blocks[i].record_count); break; } - check(!ret); + cl_assert(!ret); } reftable_iterator_destroy(&record_it); @@ -186,7 +190,7 @@ static int t_table_block_iterator(void) } ret = reftable_table_iterator_next(&it, &block); - check_int(ret, ==, 1); + cl_assert_equal_i(ret, 1); for (size_t i = 0; i < nrecords; i++) reftable_free(records[i].refname); @@ -194,13 +198,4 @@ static int t_table_block_iterator(void) reftable_table_decref(table); reftable_buf_release(&buf); reftable_free(records); - return 0; -} - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_table_seek_once(), "table can seek once"); - TEST(t_table_reseek(), "table can reseek multiple times"); - TEST(t_table_block_iterator(), "table can iterate through blocks"); - return test_done(); } @@ -14,6 +14,7 @@ #include "blob.h" #include "refs.h" #include "progress.h" +#include "prio-queue.h" static struct object_id current_commit_oid; @@ -78,7 +79,7 @@ static int process_tree(struct walker *walker, struct tree *tree) #define SEEN (1U << 1) #define TO_SCAN (1U << 2) -static struct commit_list *complete = NULL; +static struct prio_queue complete = { compare_commits_by_commit_date }; static int process_commit(struct walker *walker, struct commit *commit) { @@ -87,7 +88,10 @@ static int process_commit(struct walker *walker, struct commit *commit) if (repo_parse_commit(the_repository, commit)) return -1; - while (complete && complete->item->date >= commit->date) { + while (complete.nr) { + struct commit *item = prio_queue_peek(&complete); + if (item->date < commit->date) + break; pop_most_recent_commit(&complete, COMPLETE); } @@ -233,7 +237,7 @@ static int mark_complete(const char *path UNUSED, if (commit) { commit->object.flags |= COMPLETE; - commit_list_insert(commit, &complete); + prio_queue_put(&complete, commit); } return 0; } @@ -302,7 +306,6 @@ int walker_fetch(struct walker *walker, int targets, char **target, if (!walker->get_recover) { refs_for_each_ref(get_main_ref_store(the_repository), mark_complete, NULL); - commit_list_sort_by_date(&complete); } for (i = 0; i < targets; i++) { |
