diff options
Diffstat (limited to 't/helper')
| -rw-r--r-- | t/helper/test-chmtime.c | 15 | ||||
| -rw-r--r-- | t/helper/test-csprng.c | 29 | ||||
| -rw-r--r-- | t/helper/test-date.c | 5 | ||||
| -rw-r--r-- | t/helper/test-drop-caches.c | 4 | ||||
| -rw-r--r-- | t/helper/test-fast-rebase.c | 23 | ||||
| -rw-r--r-- | t/helper/test-fsmonitor-client.c | 222 | ||||
| -rw-r--r-- | t/helper/test-genzeros.c | 21 | ||||
| -rw-r--r-- | t/helper/test-hexdump.c | 30 | ||||
| -rw-r--r-- | t/helper/test-pack-mtimes.c | 56 | ||||
| -rw-r--r-- | t/helper/test-progress.c | 50 | ||||
| -rw-r--r-- | t/helper/test-read-cache.c | 63 | ||||
| -rw-r--r-- | t/helper/test-read-graph.c | 13 | ||||
| -rw-r--r-- | t/helper/test-read-midx.c | 3 | ||||
| -rw-r--r-- | t/helper/test-ref-store.c | 91 | ||||
| -rw-r--r-- | t/helper/test-reftable.c | 22 | ||||
| -rw-r--r-- | t/helper/test-revision-walking.c | 1 | ||||
| -rw-r--r-- | t/helper/test-run-command.c | 25 | ||||
| -rw-r--r-- | t/helper/test-subprocess.c | 2 | ||||
| -rw-r--r-- | t/helper/test-tool.c | 8 | ||||
| -rw-r--r-- | t/helper/test-tool.h | 6 | ||||
| -rw-r--r-- | t/helper/test-trace2.c | 34 |
21 files changed, 608 insertions, 115 deletions
diff --git a/t/helper/test-chmtime.c b/t/helper/test-chmtime.c index 524b55ca49..dc28890a18 100644 --- a/t/helper/test-chmtime.c +++ b/t/helper/test-chmtime.c @@ -134,6 +134,21 @@ int cmd__chmtime(int argc, const char **argv) } if (utb.modtime != sb.st_mtime && utime(argv[i], &utb) < 0) { +#ifdef GIT_WINDOWS_NATIVE + if (S_ISDIR(sb.st_mode)) { + /* + * NEEDSWORK: The Windows version of `utime()` + * (aka `mingw_utime()`) does not correctly + * handle directory arguments, since it uses + * `_wopen()`. Ignore it for now since this + * is just a test. + */ + fprintf(stderr, + ("Failed to modify time on directory %s. " + "Skipping\n"), argv[i]); + continue; + } +#endif fprintf(stderr, "Failed to modify time on %s: %s\n", argv[i], strerror(errno)); return 1; diff --git a/t/helper/test-csprng.c b/t/helper/test-csprng.c new file mode 100644 index 0000000000..65d14973c5 --- /dev/null +++ b/t/helper/test-csprng.c @@ -0,0 +1,29 @@ +#include "test-tool.h" +#include "git-compat-util.h" + + +int cmd__csprng(int argc, const char **argv) +{ + unsigned long count; + unsigned char buf[1024]; + + if (argc > 2) { + fprintf(stderr, "usage: %s [<size>]\n", argv[0]); + return 2; + } + + count = (argc == 2) ? strtoul(argv[1], NULL, 0) : -1L; + + while (count) { + unsigned long chunk = count < sizeof(buf) ? count : sizeof(buf); + if (csprng_bytes(buf, chunk) < 0) { + perror("failed to read"); + return 5; + } + if (fwrite(buf, chunk, 1, stdout) != chunk) + return 1; + count -= chunk; + } + + return 0; +} diff --git a/t/helper/test-date.c b/t/helper/test-date.c index 099eff4f0f..45951b1df8 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -1,5 +1,6 @@ #include "test-tool.h" #include "cache.h" +#include "date.h" static const char *usage_msg = "\n" " test-tool date relative [time_t]...\n" @@ -34,7 +35,7 @@ static void show_human_dates(const char **argv) static void show_dates(const char **argv, const char *format) { - struct date_mode mode; + struct date_mode mode = DATE_MODE_INIT; parse_date_format(format, &mode); for (; *argv; argv++) { @@ -53,6 +54,8 @@ static void show_dates(const char **argv, const char *format) printf("%s -> %s\n", *argv, show_date(t, tz, &mode)); } + + date_mode_release(&mode); } static void parse_dates(const char **argv) diff --git a/t/helper/test-drop-caches.c b/t/helper/test-drop-caches.c index 7b4278462b..e37396dd9c 100644 --- a/t/helper/test-drop-caches.c +++ b/t/helper/test-drop-caches.c @@ -3,6 +3,7 @@ #if defined(GIT_WINDOWS_NATIVE) #include "lazyload.h" +#include <winnt.h> static int cmd_sync(void) { @@ -86,7 +87,8 @@ static int cmd_dropcaches(void) { HANDLE hProcess = GetCurrentProcess(); HANDLE hToken; - DECLARE_PROC_ADDR(ntdll.dll, DWORD, NtSetSystemInformation, INT, PVOID, ULONG); + DECLARE_PROC_ADDR(ntdll.dll, DWORD, NTAPI, NtSetSystemInformation, INT, PVOID, + ULONG); SYSTEM_MEMORY_LIST_COMMAND command; int status; diff --git a/t/helper/test-fast-rebase.c b/t/helper/test-fast-rebase.c index fc2d460904..4e5553e202 100644 --- a/t/helper/test-fast-rebase.c +++ b/t/helper/test-fast-rebase.c @@ -99,6 +99,7 @@ int cmd__fast_rebase(int argc, const char **argv) struct merge_result result; struct strbuf reflog_msg = STRBUF_INIT; struct strbuf branch_name = STRBUF_INIT; + int ret = 0; /* * test-tool stuff doesn't set up the git directory by default; need to @@ -137,13 +138,17 @@ int cmd__fast_rebase(int argc, const char **argv) revs.topo_order = 1; strvec_pushl(&rev_walk_args, "", argv[4], "--not", argv[3], NULL); - if (setup_revisions(rev_walk_args.nr, rev_walk_args.v, &revs, NULL) > 1) - return error(_("unhandled options")); + if (setup_revisions(rev_walk_args.nr, rev_walk_args.v, &revs, NULL) > 1) { + ret = error(_("unhandled options")); + goto cleanup; + } strvec_clear(&rev_walk_args); - if (prepare_revision_walk(&revs) < 0) - return error(_("error preparing revisions")); + if (prepare_revision_walk(&revs) < 0) { + ret = error(_("error preparing revisions")); + goto cleanup; + } init_merge_options(&merge_opt, the_repository); memset(&result, 0, sizeof(result)); @@ -201,8 +206,6 @@ int cmd__fast_rebase(int argc, const char **argv) } if (create_symref("HEAD", branch_name.buf, reflog_msg.buf) < 0) die(_("unable to update HEAD")); - strbuf_release(&reflog_msg); - strbuf_release(&branch_name); prime_cache_tree(the_repository, the_repository->index, result.tree); @@ -221,5 +224,11 @@ int cmd__fast_rebase(int argc, const char **argv) if (write_locked_index(&the_index, &lock, COMMIT_LOCK | SKIP_IF_UNCHANGED)) die(_("unable to write %s"), get_index_file()); - return (result.clean == 0); + + ret = (result.clean == 0); +cleanup: + strbuf_release(&reflog_msg); + strbuf_release(&branch_name); + release_revisions(&revs); + return ret; } diff --git a/t/helper/test-fsmonitor-client.c b/t/helper/test-fsmonitor-client.c new file mode 100644 index 0000000000..54a4856c48 --- /dev/null +++ b/t/helper/test-fsmonitor-client.c @@ -0,0 +1,222 @@ +/* + * test-fsmonitor-client.c: client code to send commands/requests to + * a `git fsmonitor--daemon` daemon. + */ + +#include "test-tool.h" +#include "cache.h" +#include "parse-options.h" +#include "fsmonitor-ipc.h" +#include "thread-utils.h" +#include "trace2.h" + +#ifndef HAVE_FSMONITOR_DAEMON_BACKEND +int cmd__fsmonitor_client(int argc, const char **argv) +{ + die("fsmonitor--daemon not available on this platform"); +} +#else + +/* + * Read the `.git/index` to get the last token written to the + * FSMonitor Index Extension. + */ +static const char *get_token_from_index(void) +{ + struct index_state *istate = the_repository->index; + + if (do_read_index(istate, the_repository->index_file, 0) < 0) + die("unable to read index file"); + if (!istate->fsmonitor_last_update) + die("index file does not have fsmonitor extension"); + + return istate->fsmonitor_last_update; +} + +/* + * Send an IPC query to a `git-fsmonitor--daemon` daemon and + * ask for the changes since the given token or from the last + * token in the index extension. + * + * This will implicitly start a daemon process if necessary. The + * daemon process will persist after we exit. + */ +static int do_send_query(const char *token) +{ + struct strbuf answer = STRBUF_INIT; + int ret; + + if (!token || !*token) + token = get_token_from_index(); + + ret = fsmonitor_ipc__send_query(token, &answer); + if (ret < 0) + die("could not query fsmonitor--daemon"); + + write_in_full(1, answer.buf, answer.len); + strbuf_release(&answer); + + return 0; +} + +/* + * Send a "flush" command to the `git-fsmonitor--daemon` (if running) + * and tell it to flush its cache. + * + * This feature is primarily used by the test suite to simulate a loss of + * sync with the filesystem where we miss kernel events. + */ +static int do_send_flush(void) +{ + struct strbuf answer = STRBUF_INIT; + int ret; + + ret = fsmonitor_ipc__send_command("flush", &answer); + if (ret) + return ret; + + write_in_full(1, answer.buf, answer.len); + strbuf_release(&answer); + + return 0; +} + +struct hammer_thread_data +{ + pthread_t pthread_id; + int thread_nr; + + int nr_requests; + const char *token; + + int sum_successful; + int sum_errors; +}; + +static void *hammer_thread_proc(void *_hammer_thread_data) +{ + struct hammer_thread_data *data = _hammer_thread_data; + struct strbuf answer = STRBUF_INIT; + int k; + int ret; + + trace2_thread_start("hammer"); + + for (k = 0; k < data->nr_requests; k++) { + strbuf_reset(&answer); + + ret = fsmonitor_ipc__send_query(data->token, &answer); + if (ret < 0) + data->sum_errors++; + else + data->sum_successful++; + } + + strbuf_release(&answer); + trace2_thread_exit(); + return NULL; +} + +/* + * Start a pool of client threads that will each send a series of + * commands to the daemon. + * + * The goal is to overload the daemon with a sustained series of + * concurrent requests. + */ +static int do_hammer(const char *token, int nr_threads, int nr_requests) +{ + struct hammer_thread_data *data = NULL; + int k; + int sum_join_errors = 0; + int sum_commands = 0; + int sum_errors = 0; + + if (!token || !*token) + token = get_token_from_index(); + if (nr_threads < 1) + nr_threads = 1; + if (nr_requests < 1) + nr_requests = 1; + + CALLOC_ARRAY(data, nr_threads); + + for (k = 0; k < nr_threads; k++) { + struct hammer_thread_data *p = &data[k]; + p->thread_nr = k; + p->nr_requests = nr_requests; + p->token = token; + + if (pthread_create(&p->pthread_id, NULL, hammer_thread_proc, p)) { + warning("failed to create thread[%d] skipping remainder", k); + nr_threads = k; + break; + } + } + + for (k = 0; k < nr_threads; k++) { + struct hammer_thread_data *p = &data[k]; + + if (pthread_join(p->pthread_id, NULL)) + sum_join_errors++; + sum_commands += p->sum_successful; + sum_errors += p->sum_errors; + } + + fprintf(stderr, "HAMMER: [threads %d][requests %d] [ok %d][err %d][join %d]\n", + nr_threads, nr_requests, sum_commands, sum_errors, sum_join_errors); + + free(data); + + /* + * Return an error if any of the _send_query requests failed. + * We don't care about thread create/join errors. + */ + return sum_errors > 0; +} + +int cmd__fsmonitor_client(int argc, const char **argv) +{ + const char *subcmd; + const char *token = NULL; + int nr_threads = 1; + int nr_requests = 1; + + const char * const fsmonitor_client_usage[] = { + "test-tool fsmonitor-client query [<token>]", + "test-tool fsmonitor-client flush", + "test-tool fsmonitor-client hammer [<token>] [<threads>] [<requests>]", + NULL, + }; + + struct option options[] = { + OPT_STRING(0, "token", &token, "token", + "command token to send to the server"), + + OPT_INTEGER(0, "threads", &nr_threads, "number of client threads"), + OPT_INTEGER(0, "requests", &nr_requests, "number of requests per thread"), + + OPT_END() + }; + + argc = parse_options(argc, argv, NULL, options, fsmonitor_client_usage, 0); + + if (argc != 1) + usage_with_options(fsmonitor_client_usage, options); + + subcmd = argv[0]; + + setup_git_directory(); + + if (!strcmp(subcmd, "query")) + return !!do_send_query(token); + + if (!strcmp(subcmd, "flush")) + return !!do_send_flush(); + + if (!strcmp(subcmd, "hammer")) + return !!do_hammer(token, nr_threads, nr_requests); + + die("Unhandled subcommand: '%s'", subcmd); +} +#endif diff --git a/t/helper/test-genzeros.c b/t/helper/test-genzeros.c index 9532f5bac9..8ca988d621 100644 --- a/t/helper/test-genzeros.c +++ b/t/helper/test-genzeros.c @@ -3,18 +3,31 @@ int cmd__genzeros(int argc, const char **argv) { - long count; + /* static, so that it is NUL-initialized */ + static const char zeros[256 * 1024]; + intmax_t count; + ssize_t n; if (argc > 2) { fprintf(stderr, "usage: %s [<count>]\n", argv[0]); return 1; } - count = argc > 1 ? strtol(argv[1], NULL, 0) : -1L; + count = argc > 1 ? strtoimax(argv[1], NULL, 0) : -1; - while (count < 0 || count--) { - if (putchar(0) == EOF) + /* Writing out individual NUL bytes is slow... */ + while (count < 0) + if (write(1, zeros, ARRAY_SIZE(zeros)) < 0) return -1; + + while (count > 0) { + n = write(1, zeros, count < ARRAY_SIZE(zeros) ? + count : ARRAY_SIZE(zeros)); + + if (n < 0) + return -1; + + count -= n; } return 0; diff --git a/t/helper/test-hexdump.c b/t/helper/test-hexdump.c new file mode 100644 index 0000000000..811e89c1bc --- /dev/null +++ b/t/helper/test-hexdump.c @@ -0,0 +1,30 @@ +#include "test-tool.h" +#include "git-compat-util.h" + +/* + * Read stdin and print a hexdump to stdout. + */ +int cmd__hexdump(int argc, const char **argv) +{ + char buf[1024]; + ssize_t i, len; + int have_data = 0; + + for (;;) { + len = xread(0, buf, sizeof(buf)); + if (len < 0) + die_errno("failure reading stdin"); + if (!len) + break; + + have_data = 1; + + for (i = 0; i < len; i++) + printf("%02x ", (unsigned char)buf[i]); + } + + if (have_data) + putchar('\n'); + + return 0; +} diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c new file mode 100644 index 0000000000..f7b79daf4c --- /dev/null +++ b/t/helper/test-pack-mtimes.c @@ -0,0 +1,56 @@ +#include "git-compat-util.h" +#include "test-tool.h" +#include "strbuf.h" +#include "object-store.h" +#include "packfile.h" +#include "pack-mtimes.h" + +static void dump_mtimes(struct packed_git *p) +{ + uint32_t i; + if (load_pack_mtimes(p) < 0) + die("could not load pack .mtimes"); + + for (i = 0; i < p->num_objects; i++) { + struct object_id oid; + if (nth_packed_object_id(&oid, p, i) < 0) + die("could not load object id at position %"PRIu32, i); + + printf("%s %"PRIu32"\n", + oid_to_hex(&oid), nth_packed_mtime(p, i)); + } +} + +static const char *pack_mtimes_usage = "\n" +" test-tool pack-mtimes <pack-name.mtimes>"; + +int cmd__pack_mtimes(int argc, const char **argv) +{ + struct strbuf buf = STRBUF_INIT; + struct packed_git *p; + + setup_git_directory(); + + if (argc != 2) + usage(pack_mtimes_usage); + + for (p = get_all_packs(the_repository); p; p = p->next) { + strbuf_addstr(&buf, basename(p->pack_name)); + strbuf_strip_suffix(&buf, ".pack"); + strbuf_addstr(&buf, ".mtimes"); + + if (!strcmp(buf.buf, argv[1])) + break; + + strbuf_reset(&buf); + } + + strbuf_release(&buf); + + if (!p) + die("could not find pack '%s'", argv[1]); + + dump_mtimes(p); + + return 0; +} diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c index 5d05cbe789..6cc9735b60 100644 --- a/t/helper/test-progress.c +++ b/t/helper/test-progress.c @@ -3,6 +3,9 @@ * * Reads instructions from standard input, one instruction per line: * + * "start <total>[ <title>]" - Call start_progress(title, total), + * Uses the default title of "Working hard" + * if the " <title>" is omitted. * "progress <items>" - Call display_progress() with the given item count * as parameter. * "throughput <bytes> <millis> - Call display_throughput() with the given @@ -10,6 +13,7 @@ * specify the time elapsed since the * start_progress() call. * "update" - Set the 'progress_update' flag. + * "stop" - Call stop_progress(). * * See 't0500-progress-display.sh' for examples. */ @@ -19,34 +23,50 @@ #include "parse-options.h" #include "progress.h" #include "strbuf.h" +#include "string-list.h" int cmd__progress(int argc, const char **argv) { - int total = 0; - const char *title; + const char *const default_title = "Working hard"; + struct string_list titles = STRING_LIST_INIT_DUP; struct strbuf line = STRBUF_INIT; - struct progress *progress; + struct progress *progress = NULL; const char *usage[] = { - "test-tool progress [--total=<n>] <progress-title>", + "test-tool progress <stdin", NULL }; struct option options[] = { - OPT_INTEGER(0, "total", &total, "total number of items"), OPT_END(), }; argc = parse_options(argc, argv, NULL, options, usage, 0); - if (argc != 1) - die("need a title for the progress output"); - title = argv[0]; + if (argc) + usage_with_options(usage, options); progress_testing = 1; - progress = start_progress(title, total); while (strbuf_getline(&line, stdin) != EOF) { char *end; - if (skip_prefix(line.buf, "progress ", (const char **) &end)) { + if (skip_prefix(line.buf, "start ", (const char **) &end)) { + uint64_t total = strtoull(end, &end, 10); + const char *title; + + /* + * We can't use "end + 1" as an argument to + * start_progress(), it doesn't xstrdup() its + * "title" argument. We need to hold onto a + * valid "char *" for it until the end. + */ + if (!*end) + title = default_title; + else if (*end == ' ') + title = string_list_insert(&titles, end + 1)->string; + else + die("invalid input: '%s'\n", line.buf); + + progress = start_progress(title, total); + } else if (skip_prefix(line.buf, "progress ", (const char **) &end)) { uint64_t item_count = strtoull(end, &end, 10); if (*end != '\0') die("invalid input: '%s'\n", line.buf); @@ -63,12 +83,16 @@ int cmd__progress(int argc, const char **argv) die("invalid input: '%s'\n", line.buf); progress_test_ns = test_ms * 1000 * 1000; display_throughput(progress, byte_count); - } else if (!strcmp(line.buf, "update")) + } else if (!strcmp(line.buf, "update")) { progress_test_force_update(); - else + } else if (!strcmp(line.buf, "stop")) { + stop_progress(&progress); + } else { die("invalid input: '%s'\n", line.buf); + } } - stop_progress(&progress); + strbuf_release(&line); + string_list_clear(&titles, 0); return 0; } diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c index b52c174acc..b736ef1642 100644 --- a/t/helper/test-read-cache.c +++ b/t/helper/test-read-cache.c @@ -1,82 +1,39 @@ #include "test-tool.h" #include "cache.h" #include "config.h" -#include "blob.h" -#include "commit.h" -#include "tree.h" -#include "sparse-index.h" - -static void print_cache_entry(struct cache_entry *ce) -{ - const char *type; - printf("%06o ", ce->ce_mode & 0177777); - - if (S_ISSPARSEDIR(ce->ce_mode)) - type = tree_type; - else if (S_ISGITLINK(ce->ce_mode)) - type = commit_type; - else - type = blob_type; - - printf("%s %s\t%s\n", - type, - oid_to_hex(&ce->oid), - ce->name); -} - -static void print_cache(struct index_state *istate) -{ - int i; - for (i = 0; i < istate->cache_nr; i++) - print_cache_entry(istate->cache[i]); -} int cmd__read_cache(int argc, const char **argv) { - struct repository *r = the_repository; int i, cnt = 1; const char *name = NULL; - int table = 0, expand = 0; initialize_the_repository(); - prepare_repo_settings(r); - r->settings.command_requires_full_index = 0; - for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) { - if (skip_prefix(*argv, "--print-and-refresh=", &name)) - continue; - if (!strcmp(*argv, "--table")) - table = 1; - else if (!strcmp(*argv, "--expand")) - expand = 1; + if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) { + argc--; + argv++; } - if (argc == 1) - cnt = strtol(argv[0], NULL, 0); + if (argc == 2) + cnt = strtol(argv[1], NULL, 0); setup_git_directory(); git_config(git_default_config, NULL); for (i = 0; i < cnt; i++) { - repo_read_index(r); - - if (expand) - ensure_full_index(r->index); - + read_cache(); if (name) { int pos; - refresh_index(r->index, REFRESH_QUIET, + refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL); - pos = index_name_pos(r->index, name, strlen(name)); + pos = index_name_pos(&the_index, name, strlen(name)); if (pos < 0) die("%s not in index", name); printf("%s is%s up to date\n", name, - ce_uptodate(r->index->cache[pos]) ? "" : " not"); + ce_uptodate(the_index.cache[pos]) ? "" : " not"); write_file(name, "%d\n", i); } - if (table) - print_cache(r->index); - discard_index(r->index); + discard_cache(); } return 0; } diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c index 75927b2c81..98b73bb8f2 100644 --- a/t/helper/test-read-graph.c +++ b/t/helper/test-read-graph.c @@ -3,6 +3,7 @@ #include "commit-graph.h" #include "repository.h" #include "object-store.h" +#include "bloom.h" int cmd__read_graph(int argc, const char **argv) { @@ -45,6 +46,18 @@ int cmd__read_graph(int argc, const char **argv) printf(" bloom_data"); printf("\n"); + printf("options:"); + if (graph->bloom_filter_settings) + printf(" bloom(%"PRIu32",%"PRIu32",%"PRIu32")", + graph->bloom_filter_settings->hash_version, + graph->bloom_filter_settings->bits_per_entry, + graph->bloom_filter_settings->num_hashes); + if (graph->read_generation_data) + printf(" read_generation_data"); + if (graph->topo_levels) + printf(" topo_levels"); + printf("\n"); + UNLEAK(graph); return 0; diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c index 9d6fa7a377..27072ba94d 100644 --- a/t/helper/test-read-midx.c +++ b/t/helper/test-read-midx.c @@ -55,9 +55,10 @@ static int read_midx_file(const char *object_dir, int show_objects) printf("%s %"PRIu64"\t%s\n", oid_to_hex(&oid), e.offset, e.p->pack_name); } - return 0; } + close_midx(m); + return 0; } diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index b314b81a45..9646d85fc8 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -5,6 +5,48 @@ #include "object-store.h" #include "repository.h" +struct flag_definition { + const char *name; + uint64_t mask; +}; + +#define FLAG_DEF(x) \ + { \ +#x, (x) \ + } + +static unsigned int parse_flags(const char *str, struct flag_definition *defs) +{ + struct string_list masks = STRING_LIST_INIT_DUP; + int i = 0; + unsigned int result = 0; + + if (!strcmp(str, "0")) + return 0; + + string_list_split(&masks, str, ',', 64); + for (; i < masks.nr; i++) { + const char *name = masks.items[i].string; + struct flag_definition *def = defs; + int found = 0; + while (def->name) { + if (!strcmp(def->name, name)) { + result |= def->mask; + found = 1; + break; + } + def++; + } + if (!found) + die("unknown flag \"%s\"", name); + } + + string_list_clear(&masks, 0); + return result; +} + +static struct flag_definition empty_flags[] = { { NULL, 0 } }; + static const char *notnull(const char *arg, const char *name) { if (!arg) @@ -12,9 +54,10 @@ static const char *notnull(const char *arg, const char *name) return arg; } -static unsigned int arg_flags(const char *arg, const char *name) +static unsigned int arg_flags(const char *arg, const char *name, + struct flag_definition *defs) { - return atoi(notnull(arg, name)); + return parse_flags(notnull(arg, name), defs); } static const char **get_store(const char **argv, struct ref_store **refs) @@ -64,10 +107,13 @@ static const char **get_store(const char **argv, struct ref_store **refs) return argv + 1; } +static struct flag_definition pack_flags[] = { FLAG_DEF(PACK_REFS_PRUNE), + FLAG_DEF(PACK_REFS_ALL), + { NULL, 0 } }; static int cmd_pack_refs(struct ref_store *refs, const char **argv) { - unsigned int flags = arg_flags(*argv++, "flags"); + unsigned int flags = arg_flags(*argv++, "flags", pack_flags); return refs_pack_refs(refs, flags); } @@ -81,16 +127,27 @@ static int cmd_create_symref(struct ref_store *refs, const char **argv) return refs_create_symref(refs, refname, target, logmsg); } +static struct flag_definition transaction_flags[] = { + FLAG_DEF(REF_NO_DEREF), + FLAG_DEF(REF_FORCE_CREATE_REFLOG), + FLAG_DEF(REF_SKIP_OID_VERIFICATION), + FLAG_DEF(REF_SKIP_REFNAME_VERIFICATION), + { NULL, 0 } +}; + static int cmd_delete_refs(struct ref_store *refs, const char **argv) { - unsigned int flags = arg_flags(*argv++, "flags"); + unsigned int flags = arg_flags(*argv++, "flags", transaction_flags); const char *msg = *argv++; struct string_list refnames = STRING_LIST_INIT_NODUP; + int result; while (*argv) string_list_append(&refnames, *argv++); - return refs_delete_refs(refs, msg, &refnames, flags); + result = refs_delete_refs(refs, msg, &refnames, flags); + string_list_clear(&refnames, 0); + return result; } static int cmd_rename_ref(struct ref_store *refs, const char **argv) @@ -120,7 +177,7 @@ static int cmd_resolve_ref(struct ref_store *refs, const char **argv) { struct object_id oid = *null_oid(); const char *refname = notnull(*argv++, "refname"); - int resolve_flags = arg_flags(*argv++, "resolve-flags"); + int resolve_flags = arg_flags(*argv++, "resolve-flags", empty_flags); int flags; const char *ref; @@ -151,9 +208,9 @@ static int each_reflog(struct object_id *old_oid, struct object_id *new_oid, const char *committer, timestamp_t timestamp, int tz, const char *msg, void *cb_data) { - printf("%s %s %s %"PRItime" %d %s\n", - oid_to_hex(old_oid), oid_to_hex(new_oid), - committer, timestamp, tz, msg); + printf("%s %s %s %" PRItime " %+05d%s%s", oid_to_hex(old_oid), + oid_to_hex(new_oid), committer, timestamp, tz, + *msg == '\n' ? "" : "\t", msg); return 0; } @@ -181,11 +238,10 @@ static int cmd_reflog_exists(struct ref_store *refs, const char **argv) static int cmd_create_reflog(struct ref_store *refs, const char **argv) { const char *refname = notnull(*argv++, "refname"); - int force_create = arg_flags(*argv++, "force-create"); struct strbuf err = STRBUF_INIT; int ret; - ret = refs_create_reflog(refs, refname, force_create, &err); + ret = refs_create_reflog(refs, refname, &err); if (err.len) puts(err.buf); return ret; @@ -208,11 +264,11 @@ static int cmd_delete_ref(struct ref_store *refs, const char **argv) const char *msg = notnull(*argv++, "msg"); const char *refname = notnull(*argv++, "refname"); const char *sha1_buf = notnull(*argv++, "old-sha1"); - unsigned int flags = arg_flags(*argv++, "flags"); + unsigned int flags = arg_flags(*argv++, "flags", transaction_flags); struct object_id old_oid; if (get_oid_hex(sha1_buf, &old_oid)) - die("not sha-1"); + die("cannot parse %s as %s", sha1_buf, the_hash_algo->name); return refs_delete_ref(refs, msg, refname, &old_oid, flags); } @@ -223,13 +279,14 @@ static int cmd_update_ref(struct ref_store *refs, const char **argv) const char *refname = notnull(*argv++, "refname"); const char *new_sha1_buf = notnull(*argv++, "new-sha1"); const char *old_sha1_buf = notnull(*argv++, "old-sha1"); - unsigned int flags = arg_flags(*argv++, "flags"); + unsigned int flags = arg_flags(*argv++, "flags", transaction_flags); struct object_id old_oid; struct object_id new_oid; - if (get_oid_hex(old_sha1_buf, &old_oid) || - get_oid_hex(new_sha1_buf, &new_oid)) - die("not sha-1"); + if (get_oid_hex(old_sha1_buf, &old_oid)) + die("cannot parse %s as %s", old_sha1_buf, the_hash_algo->name); + if (get_oid_hex(new_sha1_buf, &new_oid)) + die("cannot parse %s as %s", new_sha1_buf, the_hash_algo->name); return refs_update_ref(refs, msg, refname, &new_oid, &old_oid, diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c new file mode 100644 index 0000000000..1f0a28cbb6 --- /dev/null +++ b/t/helper/test-reftable.c @@ -0,0 +1,22 @@ +#include "reftable/reftable-tests.h" +#include "test-tool.h" + +int cmd__reftable(int argc, const char **argv) +{ + /* test from simple to complex. */ + basics_test_main(argc, argv); + record_test_main(argc, argv); + block_test_main(argc, argv); + tree_test_main(argc, argv); + pq_test_main(argc, argv); + readwrite_test_main(argc, argv); + merged_test_main(argc, argv); + stack_test_main(argc, argv); + refname_test_main(argc, argv); + return 0; +} + +int cmd__dump_reftable(int argc, const char **argv) +{ + return reftable_dump_main(argc, (char *const *)argv); +} diff --git a/t/helper/test-revision-walking.c b/t/helper/test-revision-walking.c index 625b2dbf82..4a45d5bac2 100644 --- a/t/helper/test-revision-walking.c +++ b/t/helper/test-revision-walking.c @@ -43,6 +43,7 @@ static int run_revision_walk(void) } reset_revision_walk(); + release_revisions(&rev); return got_revision; } diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c index 3c4fb86223..9050e3113c 100644 --- a/t/helper/test-run-command.c +++ b/t/helper/test-run-command.c @@ -19,7 +19,6 @@ #include "thread-utils.h" #include "wildmatch.h" #include "gettext.h" -#include "parse-options.h" static int number_callbacks; static int parallel_next(struct child_process *cp, @@ -31,7 +30,7 @@ static int parallel_next(struct child_process *cp, if (number_callbacks >= 4) return 0; - strvec_pushv(&cp->args, d->argv); + strvec_pushv(&cp->args, d->args.v); strbuf_addstr(err, "preloaded output of a child\n"); number_callbacks++; return 1; @@ -180,15 +179,16 @@ static int testsuite(int argc, const char **argv) if (max_jobs > suite.tests.nr) max_jobs = suite.tests.nr; - fprintf(stderr, "Running %d tests (%d at a time)\n", - suite.tests.nr, max_jobs); + fprintf(stderr, "Running %"PRIuMAX" tests (%d at a time)\n", + (uintmax_t)suite.tests.nr, max_jobs); ret = run_processes_parallel(max_jobs, next_test, test_failed, test_finished, &suite); if (suite.failed.nr > 0) { ret = 1; - fprintf(stderr, "%d tests failed:\n\n", suite.failed.nr); + fprintf(stderr, "%"PRIuMAX" tests failed:\n\n", + (uintmax_t)suite.failed.nr); for (i = 0; i < suite.failed.nr; i++) fprintf(stderr, "\t%s\n", suite.failed.items[i].string); } @@ -221,9 +221,9 @@ static int quote_stress_test(int argc, const char **argv) struct strbuf out = STRBUF_INIT; struct strvec args = STRVEC_INIT; struct option options[] = { - OPT_INTEGER('n', "trials", &trials, "Number of trials"), - OPT_INTEGER('s', "skip", &skip, "Skip <n> trials"), - OPT_BOOL('m', "msys2", &msys2, "Test quoting for MSYS2's sh"), + OPT_INTEGER('n', "trials", &trials, "number of trials"), + OPT_INTEGER('s', "skip", &skip, "skip <n> trials"), + OPT_BOOL('m', "msys2", &msys2, "test quoting for MSYS2's sh"), OPT_END() }; const char * const usage[] = { @@ -274,7 +274,7 @@ static int quote_stress_test(int argc, const char **argv) if (i < skip) continue; - cp.argv = args.v; + strvec_pushv(&cp.args, args.v); strbuf_reset(&out); if (pipe_command(&cp, NULL, 0, &out, 0, NULL, 0) < 0) return error("Failed to spawn child process"); @@ -390,13 +390,13 @@ int cmd__run_command(int argc, const char **argv) while (!strcmp(argv[1], "env")) { if (!argv[2]) die("env specifier without a value"); - strvec_push(&proc.env_array, argv[2]); + strvec_push(&proc.env, argv[2]); argv += 2; argc -= 2; } if (argc < 3) return 1; - proc.argv = (const char **)argv + 2; + strvec_pushv(&proc.args, (const char **)argv + 2); if (!strcmp(argv[1], "start-command-ENOENT")) { if (start_command(&proc) < 0 && errno == ENOENT) @@ -408,7 +408,8 @@ int cmd__run_command(int argc, const char **argv) exit(run_command(&proc)); jobs = atoi(argv[2]); - proc.argv = (const char **)argv + 3; + strvec_clear(&proc.args); + strvec_pushv(&proc.args, (const char **)argv + 3); if (!strcmp(argv[1], "run-command-parallel")) exit(run_processes_parallel(jobs, parallel_next, diff --git a/t/helper/test-subprocess.c b/t/helper/test-subprocess.c index 92b69de635..ff22f2fa2c 100644 --- a/t/helper/test-subprocess.c +++ b/t/helper/test-subprocess.c @@ -15,6 +15,6 @@ int cmd__subprocess(int argc, const char **argv) argv++; } cp.git_cmd = 1; - cp.argv = (const char **)argv + 1; + strvec_pushv(&cp.args, (const char **)argv + 1); return run_command(&cp); } diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 3ce5585e53..318fdbab0c 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -20,6 +20,7 @@ static struct test_cmd cmds[] = { { "chmtime", cmd__chmtime }, { "config", cmd__config }, { "crontab", cmd__crontab }, + { "csprng", cmd__csprng }, { "ctype", cmd__ctype }, { "date", cmd__date }, { "delta", cmd__delta }, @@ -31,11 +32,13 @@ static struct test_cmd cmds[] = { { "dump-untracked-cache", cmd__dump_untracked_cache }, { "example-decorate", cmd__example_decorate }, { "fast-rebase", cmd__fast_rebase }, + { "fsmonitor-client", cmd__fsmonitor_client }, { "genrandom", cmd__genrandom }, { "genzeros", cmd__genzeros }, { "getcwd", cmd__getcwd }, { "hashmap", cmd__hashmap }, { "hash-speed", cmd__hash_speed }, + { "hexdump", cmd__hexdump }, { "index-version", cmd__index_version }, { "json-writer", cmd__json_writer }, { "lazy-init-name-hash", cmd__lazy_init_name_hash }, @@ -46,6 +49,7 @@ static struct test_cmd cmds[] = { { "oidmap", cmd__oidmap }, { "oidtree", cmd__oidtree }, { "online-cpus", cmd__online_cpus }, + { "pack-mtimes", cmd__pack_mtimes }, { "parse-options", cmd__parse_options }, { "parse-pathspec-file", cmd__parse_pathspec_file }, { "partial-clone", cmd__partial_clone }, @@ -53,13 +57,15 @@ static struct test_cmd cmds[] = { { "pcre2-config", cmd__pcre2_config }, { "pkt-line", cmd__pkt_line }, { "prio-queue", cmd__prio_queue }, - { "proc-receive", cmd__proc_receive}, + { "proc-receive", cmd__proc_receive }, { "progress", cmd__progress }, { "reach", cmd__reach }, { "read-cache", cmd__read_cache }, { "read-graph", cmd__read_graph }, { "read-midx", cmd__read_midx }, { "ref-store", cmd__ref_store }, + { "reftable", cmd__reftable }, + { "dump-reftable", cmd__dump_reftable }, { "regex", cmd__regex }, { "repository", cmd__repository }, { "revision-walking", cmd__revision_walking }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 9f0f522850..bb79927163 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -10,6 +10,7 @@ int cmd__bloom(int argc, const char **argv); int cmd__chmtime(int argc, const char **argv); int cmd__config(int argc, const char **argv); int cmd__crontab(int argc, const char **argv); +int cmd__csprng(int argc, const char **argv); int cmd__ctype(int argc, const char **argv); int cmd__date(int argc, const char **argv); int cmd__delta(int argc, const char **argv); @@ -19,13 +20,16 @@ int cmd__dump_cache_tree(int argc, const char **argv); int cmd__dump_fsmonitor(int argc, const char **argv); int cmd__dump_split_index(int argc, const char **argv); int cmd__dump_untracked_cache(int argc, const char **argv); +int cmd__dump_reftable(int argc, const char **argv); int cmd__example_decorate(int argc, const char **argv); int cmd__fast_rebase(int argc, const char **argv); +int cmd__fsmonitor_client(int argc, const char **argv); int cmd__genrandom(int argc, const char **argv); int cmd__genzeros(int argc, const char **argv); int cmd__getcwd(int argc, const char **argv); int cmd__hashmap(int argc, const char **argv); int cmd__hash_speed(int argc, const char **argv); +int cmd__hexdump(int argc, const char **argv); int cmd__index_version(int argc, const char **argv); int cmd__json_writer(int argc, const char **argv); int cmd__lazy_init_name_hash(int argc, const char **argv); @@ -35,6 +39,7 @@ int cmd__mktemp(int argc, const char **argv); int cmd__oidmap(int argc, const char **argv); int cmd__oidtree(int argc, const char **argv); int cmd__online_cpus(int argc, const char **argv); +int cmd__pack_mtimes(int argc, const char **argv); int cmd__parse_options(int argc, const char **argv); int cmd__parse_pathspec_file(int argc, const char** argv); int cmd__partial_clone(int argc, const char **argv); @@ -49,6 +54,7 @@ int cmd__read_cache(int argc, const char **argv); int cmd__read_graph(int argc, const char **argv); int cmd__read_midx(int argc, const char **argv); int cmd__ref_store(int argc, const char **argv); +int cmd__reftable(int argc, const char **argv); int cmd__regex(int argc, const char **argv); int cmd__repository(int argc, const char **argv); int cmd__revision_walking(int argc, const char **argv); diff --git a/t/helper/test-trace2.c b/t/helper/test-trace2.c index f93633f895..180c7f53f3 100644 --- a/t/helper/test-trace2.c +++ b/t/helper/test-trace2.c @@ -198,7 +198,7 @@ static int ut_006data(int argc, const char **argv) return 0; } -static int ut_007bug(int argc, const char **argv) +static int ut_007BUG(int argc, const char **argv) { /* * Exercise BUG() to ensure that the message is printed to trace2. @@ -206,6 +206,28 @@ static int ut_007bug(int argc, const char **argv) BUG("the bug message"); } +static int ut_008bug(int argc, const char **argv) +{ + bug("a bug message"); + bug("another bug message"); + BUG_if_bug("an explicit BUG_if_bug() following bug() call(s) is nice, but not required"); + return 0; +} + +static int ut_009bug_BUG(int argc, const char **argv) +{ + bug("a bug message"); + bug("another bug message"); + /* The BUG_if_bug(...) isn't here, but we'll spot bug() calls on exit()! */ + return 0; +} + +static int ut_010bug_BUG(int argc, const char **argv) +{ + bug("a bug message"); + BUG("a BUG message"); +} + /* * Usage: * test-tool trace2 <ut_name_1> <ut_usage_1> @@ -222,7 +244,10 @@ static struct unit_test ut_table[] = { { ut_004child, "004child", "[<child_command_line>]" }, { ut_005exec, "005exec", "<git_command_args>" }, { ut_006data, "006data", "[<category> <key> <value>]+" }, - { ut_007bug, "007bug", "" }, + { ut_007BUG, "007bug", "" }, + { ut_008bug, "008bug", "" }, + { ut_009bug_BUG, "009bug_BUG","" }, + { ut_010bug_BUG, "010bug_BUG","" }, }; /* clang-format on */ @@ -262,8 +287,9 @@ static int print_usage(void) * [] the "cmd_name" event has been generated. * [] this writes various "def_param" events for interesting config values. * - * We further assume that if we return (rather than exit()), trace2_cmd_exit() - * will be called by test-tool.c:cmd_main(). + * We return from here and let test-tool.c::cmd_main() pass the exit + * code to common-main.c::main(), which will use it to call + * trace2_cmd_exit(). */ int cmd__trace2(int argc, const char **argv) { |
