It's occasionally useful when testing or debugging to be able to do raw zlib inflate/deflate operations (e.g., to check the bytes of a specific loose or packed object). Even though zlib's deflate algorithm is used by many other programs, this is surprisingly hard to do in a portable way. E.g., gzip can do this if you manually munge some header bytes. But the result is somewhat arcane, and we don't assume gzip is available anyway. Likewise, pigz will handle raw zlib, but we can't assume it is available. So let's introduce a short test helper for just doing zlib operations. We'll use it in subsequent patches to add some new tests, but it would also have come in handy a few times in the past: - The hard-coded pack data from3b910d0c5e(add tests for indexing packs with delta cycles, 2013-08-23) could probably be generated on the fly. - Likewise we could avoid the hard-coded data from0b1493c2d4(git_inflate(): skip zlib_post_call() sanity check on Z_NEED_DICT, 2025-02-25). Though note this would require support for more zlib options. - It would have helped with the debugging documented in41dfbb2dbe(howto: add article on recovering a corrupted object, 2013-10-25). I'll leave refactoring existing tests for another day, but I hope the examples above show the general utility. I aimed for simplicity in the code. In particular, it will read all input into a memory buffer, rather than streaming. That makes the zlib loops harder to get wrong (which has been a source of subtle bugs in the past). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
140 lines
4.2 KiB
C
140 lines
4.2 KiB
C
#include "git-compat-util.h"
|
|
#include "test-tool.h"
|
|
#include "test-tool-utils.h"
|
|
#include "trace2.h"
|
|
#include "parse-options.h"
|
|
|
|
static const char * const test_tool_usage[] = {
|
|
"test-tool [-C <directory>] <command [<arguments>...]]",
|
|
NULL
|
|
};
|
|
|
|
static struct test_cmd cmds[] = {
|
|
{ "advise", cmd__advise_if_enabled },
|
|
{ "bitmap", cmd__bitmap },
|
|
{ "bloom", cmd__bloom },
|
|
{ "bundle-uri", cmd__bundle_uri },
|
|
{ "cache-tree", cmd__cache_tree },
|
|
{ "chmtime", cmd__chmtime },
|
|
{ "config", cmd__config },
|
|
{ "crontab", cmd__crontab },
|
|
{ "csprng", cmd__csprng },
|
|
{ "date", cmd__date },
|
|
{ "delete-gpgsig", cmd__delete_gpgsig },
|
|
{ "delta", cmd__delta },
|
|
{ "dir-iterator", cmd__dir_iterator },
|
|
{ "drop-caches", cmd__drop_caches },
|
|
{ "dump-cache-tree", cmd__dump_cache_tree },
|
|
{ "dump-fsmonitor", cmd__dump_fsmonitor },
|
|
{ "dump-reftable", cmd__dump_reftable },
|
|
{ "dump-split-index", cmd__dump_split_index },
|
|
{ "dump-untracked-cache", cmd__dump_untracked_cache },
|
|
{ "env-helper", cmd__env_helper },
|
|
{ "example-tap", cmd__example_tap },
|
|
{ "find-pack", cmd__find_pack },
|
|
{ "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 },
|
|
{ "json-writer", cmd__json_writer },
|
|
{ "lazy-init-name-hash", cmd__lazy_init_name_hash },
|
|
{ "match-trees", cmd__match_trees },
|
|
{ "mergesort", cmd__mergesort },
|
|
{ "mktemp", cmd__mktemp },
|
|
{ "name-hash", cmd__name_hash },
|
|
{ "online-cpus", cmd__online_cpus },
|
|
{ "pack-deltas", cmd__pack_deltas },
|
|
{ "pack-mtimes", cmd__pack_mtimes },
|
|
{ "parse-options", cmd__parse_options },
|
|
{ "parse-options-flags", cmd__parse_options_flags },
|
|
{ "parse-pathspec-file", cmd__parse_pathspec_file },
|
|
{ "parse-subcommand", cmd__parse_subcommand },
|
|
{ "partial-clone", cmd__partial_clone },
|
|
{ "path-utils", cmd__path_utils },
|
|
{ "path-walk", cmd__path_walk },
|
|
{ "pcre2-config", cmd__pcre2_config },
|
|
{ "pkt-line", cmd__pkt_line },
|
|
{ "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 },
|
|
{ "rot13-filter", cmd__rot13_filter },
|
|
{ "regex", cmd__regex },
|
|
{ "repository", cmd__repository },
|
|
{ "revision-walking", cmd__revision_walking },
|
|
{ "run-command", cmd__run_command },
|
|
{ "scrap-cache-tree", cmd__scrap_cache_tree },
|
|
{ "serve-v2", cmd__serve_v2 },
|
|
{ "sha1", cmd__sha1 },
|
|
{ "sha1-is-sha1dc", cmd__sha1_is_sha1dc },
|
|
{ "sha1-unsafe", cmd__sha1_unsafe },
|
|
{ "sha256", cmd__sha256 },
|
|
{ "sigchain", cmd__sigchain },
|
|
{ "simple-ipc", cmd__simple_ipc },
|
|
{ "string-list", cmd__string_list },
|
|
{ "submodule", cmd__submodule },
|
|
{ "submodule-config", cmd__submodule_config },
|
|
{ "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
|
|
{ "subprocess", cmd__subprocess },
|
|
{ "trace2", cmd__trace2 },
|
|
{ "truncate", cmd__truncate },
|
|
{ "userdiff", cmd__userdiff },
|
|
{ "xml-encode", cmd__xml_encode },
|
|
{ "wildmatch", cmd__wildmatch },
|
|
#ifdef GIT_WINDOWS_NATIVE
|
|
{ "windows-named-pipe", cmd__windows_named_pipe },
|
|
#endif
|
|
{ "write-cache", cmd__write_cache },
|
|
{ "zlib", cmd__zlib },
|
|
};
|
|
|
|
static NORETURN void die_usage(void)
|
|
{
|
|
size_t i;
|
|
|
|
fprintf(stderr, "usage: test-tool <toolname> [args]\n");
|
|
for (i = 0; i < ARRAY_SIZE(cmds); i++)
|
|
fprintf(stderr, " %s\n", cmds[i].name);
|
|
exit(128);
|
|
}
|
|
|
|
int cmd_main(int argc, const char **argv)
|
|
{
|
|
const char *working_directory = NULL;
|
|
struct option options[] = {
|
|
OPT_STRING('C', NULL, &working_directory, "directory",
|
|
"change the working directory"),
|
|
OPT_END()
|
|
};
|
|
|
|
BUG_exit_code = 99;
|
|
argc = parse_options(argc, argv, NULL, options, test_tool_usage,
|
|
PARSE_OPT_STOP_AT_NON_OPTION |
|
|
PARSE_OPT_KEEP_ARGV0);
|
|
|
|
if (argc < 2)
|
|
die_usage();
|
|
|
|
if (working_directory && chdir(working_directory) < 0)
|
|
die("Could not cd to '%s'", working_directory);
|
|
|
|
for (size_t i = 0; i < ARRAY_SIZE(cmds); i++) {
|
|
if (!strcmp(cmds[i].name, argv[1])) {
|
|
argv++;
|
|
argc--;
|
|
trace2_cmd_name(cmds[i].name);
|
|
trace2_cmd_list_config();
|
|
trace2_cmd_list_env_vars();
|
|
return cmds[i].fn(argc, argv);
|
|
}
|
|
}
|
|
error("there is no tool named '%s'", argv[1]);
|
|
die_usage();
|
|
}
|