summaryrefslogtreecommitdiff
path: root/t/helper
diff options
context:
space:
mode:
Diffstat (limited to 't/helper')
-rw-r--r--t/helper/test-chmtime.c59
-rw-r--r--t/helper/test-config.c5
-rw-r--r--t/helper/test-ctype.c3
-rw-r--r--t/helper/test-date.c17
-rw-r--r--t/helper/test-delta.c13
-rw-r--r--t/helper/test-drop-caches.c23
-rw-r--r--t/helper/test-dump-cache-tree.c5
-rw-r--r--t/helper/test-dump-fsmonitor.c3
-rw-r--r--t/helper/test-dump-split-index.c7
-rw-r--r--t/helper/test-dump-untracked-cache.c5
-rw-r--r--t/helper/test-example-decorate.c19
-rw-r--r--t/helper/test-genrandom.c3
-rw-r--r--t/helper/test-hashmap.c5
-rw-r--r--t/helper/test-index-version.c3
-rw-r--r--t/helper/test-json-writer.c565
-rw-r--r--t/helper/test-lazy-init-name-hash.c13
-rw-r--r--t/helper/test-match-trees.c3
-rw-r--r--t/helper/test-mergesort.c3
-rw-r--r--t/helper/test-mktemp.c3
-rw-r--r--t/helper/test-online-cpus.c3
-rw-r--r--t/helper/test-parse-options.c7
-rw-r--r--t/helper/test-path-utils.c23
-rw-r--r--t/helper/test-pkt-line.c98
-rw-r--r--t/helper/test-prio-queue.c29
-rw-r--r--t/helper/test-reach.c168
-rw-r--r--t/helper/test-read-cache.c3
-rw-r--r--t/helper/test-read-midx.c51
-rw-r--r--t/helper/test-ref-store.c7
-rw-r--r--t/helper/test-regex.c7
-rw-r--r--t/helper/test-repository.c88
-rw-r--r--t/helper/test-revision-walking.c5
-rw-r--r--t/helper/test-run-command.c3
-rw-r--r--t/helper/test-scrap-cache-tree.c7
-rw-r--r--t/helper/test-sha1-array.c3
-rw-r--r--t/helper/test-sha1.c3
-rwxr-xr-xt/helper/test-sha1.sh4
-rw-r--r--t/helper/test-sigchain.c3
-rw-r--r--t/helper/test-strcmp-offset.c3
-rw-r--r--t/helper/test-string-list.c3
-rw-r--r--t/helper/test-submodule-config.c11
-rw-r--r--t/helper/test-submodule-nested-repo-config.c30
-rw-r--r--t/helper/test-subprocess.c3
-rw-r--r--t/helper/test-tool.c86
-rw-r--r--t/helper/test-tool.h54
-rw-r--r--t/helper/test-urlmatch-normalization.c5
-rw-r--r--t/helper/test-wildmatch.c3
-rw-r--r--t/helper/test-windows-named-pipe.c72
-rw-r--r--t/helper/test-write-cache.c17
48 files changed, 1428 insertions, 128 deletions
diff --git a/t/helper/test-chmtime.c b/t/helper/test-chmtime.c
index e760256406..aa22af48c2 100644
--- a/t/helper/test-chmtime.c
+++ b/t/helper/test-chmtime.c
@@ -5,32 +5,43 @@
*
* The mtime can be changed to an absolute value:
*
- * test-chmtime =<seconds> file...
+ * test-tool chmtime =<seconds> file...
*
* Relative to the current time as returned by time(3):
*
- * test-chmtime =+<seconds> (or =-<seconds>) file...
+ * test-tool chmtime =+<seconds> (or =-<seconds>) file...
*
* Or relative to the current mtime of the file:
*
- * test-chmtime <seconds> file...
- * test-chmtime +<seconds> (or -<seconds>) file...
+ * test-tool chmtime <seconds> file...
+ * test-tool chmtime +<seconds> (or -<seconds>) file...
*
* Examples:
*
- * To just print the mtime use --verbose and set the file mtime offset to 0:
+ * To print the mtime and the file name use --verbose and set
+ * the file mtime offset to 0:
*
- * test-chmtime -v +0 file
+ * test-tool chmtime -v +0 file
+ *
+ * To print only the mtime use --get:
+ *
+ * test-tool chmtime --get file
*
* To set the mtime to current time:
*
- * test-chmtime =+0 file
+ * test-tool chmtime =+0 file
+ *
+ * To set the file mtime offset to +1 and print the new value:
+ *
+ * test-tool chmtime --get +1 file
*
*/
+#include "test-tool.h"
#include "git-compat-util.h"
#include <utime.h>
-static const char usage_str[] = "-v|--verbose (+|=|=+|=-|-)<seconds> <file>...";
+static const char usage_str[] =
+ "(-v|--verbose|-g|--get) (+|=|=+|=-|-)<seconds> <file>...";
static int timespec_arg(const char *arg, long int *set_time, int *set_eq)
{
@@ -46,7 +57,6 @@ static int timespec_arg(const char *arg, long int *set_time, int *set_eq)
}
*set_time = strtol(timespec, &test, 10);
if (*test) {
- fprintf(stderr, "Not a base-10 integer: %s\n", arg + 1);
return 0;
}
if ((*set_eq && *set_time < 0) || *set_eq == 2) {
@@ -56,9 +66,10 @@ static int timespec_arg(const char *arg, long int *set_time, int *set_eq)
return 1;
}
-int cmd_main(int argc, const char **argv)
+int cmd__chmtime(int argc, const char **argv)
{
static int verbose;
+ static int get;
int i = 1;
/* no mtime change by default */
@@ -68,18 +79,34 @@ int cmd_main(int argc, const char **argv)
if (argc < 3)
goto usage;
- if (strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) {
+ if (strcmp(argv[i], "--get") == 0 || strcmp(argv[i], "-g") == 0) {
+ get = 1;
+ ++i;
+ } else if (strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) {
verbose = 1;
++i;
}
- if (timespec_arg(argv[i], &set_time, &set_eq))
+
+ if (i == argc) {
+ goto usage;
+ }
+
+ if (timespec_arg(argv[i], &set_time, &set_eq)) {
++i;
- else
+ } else {
+ if (get == 0) {
+ fprintf(stderr, "Not a base-10 integer: %s\n", argv[i] + 1);
+ goto usage;
+ }
+ }
+
+ if (i == argc)
goto usage;
for (; i < argc; i++) {
struct stat sb;
struct utimbuf utb;
+ uintmax_t mtime;
if (stat(argv[i], &sb) < 0) {
fprintf(stderr, "Failed to stat %s: %s\n",
@@ -99,8 +126,10 @@ int cmd_main(int argc, const char **argv)
utb.actime = sb.st_atime;
utb.modtime = set_eq ? set_time : sb.st_mtime + set_time;
- if (verbose) {
- uintmax_t mtime = utb.modtime < 0 ? 0: utb.modtime;
+ mtime = utb.modtime < 0 ? 0: utb.modtime;
+ if (get) {
+ printf("%"PRIuMAX"\n", mtime);
+ } else if (verbose) {
printf("%"PRIuMAX"\t%s\n", mtime, argv[i]);
}
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 1a7b8bd3d6..214003d5b2 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "config.h"
#include "string-list.h"
@@ -32,7 +33,7 @@
* Examples:
*
* To print the value with highest priority for key "foo.bAr Baz.rock":
- * test-config get_value "foo.bAr Baz.rock"
+ * test-tool config get_value "foo.bAr Baz.rock"
*
*/
@@ -77,7 +78,7 @@ static int early_config_cb(const char *var, const char *value, void *vdata)
return 0;
}
-int cmd_main(int argc, const char **argv)
+int cmd__config(int argc, const char **argv)
{
int i, val;
const char *v;
diff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c
index bb72c47df5..92c4c2313e 100644
--- a/t/helper/test-ctype.c
+++ b/t/helper/test-ctype.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
static int rc;
@@ -28,7 +29,7 @@ static int is_in(const char *s, int ch)
#define LOWER "abcdefghijklmnopqrstuvwxyz"
#define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-int cmd_main(int argc, const char **argv)
+int cmd__ctype(int argc, const char **argv)
{
TEST_CLASS(isdigit, DIGIT);
TEST_CLASS(isspace, " \n\r\t");
diff --git a/t/helper/test-date.c b/t/helper/test-date.c
index ac83687970..a0837371ab 100644
--- a/t/helper/test-date.c
+++ b/t/helper/test-date.c
@@ -1,13 +1,14 @@
+#include "test-tool.h"
#include "cache.h"
static const char *usage_msg = "\n"
-" test-date relative [time_t]...\n"
-" test-date show:<format> [time_t]...\n"
-" test-date parse [date]...\n"
-" test-date approxidate [date]...\n"
-" test-date timestamp [date]...\n"
-" test-date is64bit\n"
-" test-date time_t-is64bit\n";
+" test-tool date relative [time_t]...\n"
+" test-tool date show:<format> [time_t]...\n"
+" test-tool date parse [date]...\n"
+" test-tool date approxidate [date]...\n"
+" test-tool date timestamp [date]...\n"
+" test-tool date is64bit\n"
+" test-tool date time_t-is64bit\n";
static void show_relative_dates(const char **argv, struct timeval *now)
{
@@ -81,7 +82,7 @@ static void parse_approx_timestamp(const char **argv, struct timeval *now)
}
}
-int cmd_main(int argc, const char **argv)
+int cmd__date(int argc, const char **argv)
{
struct timeval now;
const char *x;
diff --git a/t/helper/test-delta.c b/t/helper/test-delta.c
index 591730adc4..e749a49c88 100644
--- a/t/helper/test-delta.c
+++ b/t/helper/test-delta.c
@@ -8,14 +8,15 @@
* published by the Free Software Foundation.
*/
+#include "test-tool.h"
#include "git-compat-util.h"
#include "delta.h"
#include "cache.h"
static const char usage_str[] =
- "test-delta (-d|-p) <from_file> <data_file> <out_file>";
+ "test-tool delta (-d|-p) <from_file> <data_file> <out_file>";
-int cmd_main(int argc, const char **argv)
+int cmd__delta(int argc, const char **argv)
{
int fd;
struct stat st;
@@ -33,8 +34,8 @@ int cmd_main(int argc, const char **argv)
return 1;
}
from_size = st.st_size;
- from_buf = mmap(NULL, from_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (from_buf == MAP_FAILED) {
+ from_buf = xmalloc(from_size);
+ if (read_in_full(fd, from_buf, from_size) < 0) {
perror(argv[2]);
close(fd);
return 1;
@@ -47,8 +48,8 @@ int cmd_main(int argc, const char **argv)
return 1;
}
data_size = st.st_size;
- data_buf = mmap(NULL, data_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (data_buf == MAP_FAILED) {
+ data_buf = xmalloc(data_size);
+ if (read_in_full(fd, data_buf, data_size) < 0) {
perror(argv[3]);
close(fd);
return 1;
diff --git a/t/helper/test-drop-caches.c b/t/helper/test-drop-caches.c
index bd1a857d52..f65e301f9d 100644
--- a/t/helper/test-drop-caches.c
+++ b/t/helper/test-drop-caches.c
@@ -1,6 +1,8 @@
+#include "test-tool.h"
#include "git-compat-util.h"
#if defined(GIT_WINDOWS_NATIVE)
+#include "lazyload.h"
static int cmd_sync(void)
{
@@ -14,8 +16,8 @@ static int cmd_sync(void)
if ((0 == dwRet) || (dwRet > MAX_PATH))
return error("Error getting current directory");
- if ((Buffer[0] < 'A') || (Buffer[0] > 'Z'))
- return error("Invalid drive letter '%c'", Buffer[0]);
+ if (!has_dos_drive_prefix(Buffer))
+ return error("'%s': invalid drive letter", Buffer);
szVolumeAccessPath[4] = Buffer[0];
hVolWrite = CreateFile(szVolumeAccessPath, GENERIC_READ | GENERIC_WRITE,
@@ -81,8 +83,7 @@ static int cmd_dropcaches(void)
{
HANDLE hProcess = GetCurrentProcess();
HANDLE hToken;
- HMODULE ntdll;
- DWORD(WINAPI *NtSetSystemInformation)(INT, PVOID, ULONG);
+ DECLARE_PROC_ADDR(ntdll.dll, DWORD, NtSetSystemInformation, INT, PVOID, ULONG);
SYSTEM_MEMORY_LIST_COMMAND command;
int status;
@@ -94,14 +95,8 @@ static int cmd_dropcaches(void)
CloseHandle(hToken);
- ntdll = LoadLibrary("ntdll.dll");
- if (!ntdll)
- return error("Can't load ntdll.dll, wrong Windows version?");
-
- NtSetSystemInformation =
- (DWORD(WINAPI *)(INT, PVOID, ULONG))GetProcAddress(ntdll, "NtSetSystemInformation");
- if (!NtSetSystemInformation)
- return error("Can't get function addresses, wrong Windows version?");
+ if (!INIT_PROC_ADDR(NtSetSystemInformation))
+ return error("Could not find NtSetSystemInformation() function");
command = MemoryPurgeStandbyList;
status = NtSetSystemInformation(
@@ -114,8 +109,6 @@ static int cmd_dropcaches(void)
else if (status != STATUS_SUCCESS)
error("Unable to execute the memory list command %d", status);
- FreeLibrary(ntdll);
-
return status;
}
@@ -157,7 +150,7 @@ static int cmd_dropcaches(void)
#endif
-int cmd_main(int argc, const char **argv)
+int cmd__drop_caches(int argc, const char **argv)
{
cmd_sync();
return cmd_dropcaches();
diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c
index ebf3aab22d..6a3f88f5f5 100644
--- a/t/helper/test-dump-cache-tree.c
+++ b/t/helper/test-dump-cache-tree.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "tree.h"
#include "cache-tree.h"
@@ -32,7 +33,7 @@ static int dump_cache_tree(struct cache_tree *it,
}
else {
dump_one(it, pfx, "");
- if (oidcmp(&it->oid, &ref->oid) ||
+ if (!oideq(&it->oid, &ref->oid) ||
ref->entry_count != it->entry_count ||
ref->subtree_nr != it->subtree_nr) {
/* claims to be valid but is lying */
@@ -54,7 +55,7 @@ static int dump_cache_tree(struct cache_tree *it,
return errs;
}
-int cmd_main(int ac, const char **av)
+int cmd__dump_cache_tree(int ac, const char **av)
{
struct index_state istate;
struct cache_tree *another = cache_tree();
diff --git a/t/helper/test-dump-fsmonitor.c b/t/helper/test-dump-fsmonitor.c
index ad452707e8..08e3684aff 100644
--- a/t/helper/test-dump-fsmonitor.c
+++ b/t/helper/test-dump-fsmonitor.c
@@ -1,6 +1,7 @@
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int ac, const char **av)
+int cmd__dump_fsmonitor(int ac, const char **av)
{
struct index_state *istate = &the_index;
int i;
diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c
index e44430b699..63c689d6ee 100644
--- a/t/helper/test-dump-split-index.c
+++ b/t/helper/test-dump-split-index.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "split-index.h"
#include "ewah/ewok.h"
@@ -7,19 +8,19 @@ static void show_bit(size_t pos, void *data)
printf(" %d", (int)pos);
}
-int cmd_main(int ac, const char **av)
+int cmd__dump_split_index(int ac, const char **av)
{
struct split_index *si;
int i;
do_read_index(&the_index, av[1], 1);
- printf("own %s\n", sha1_to_hex(the_index.sha1));
+ printf("own %s\n", oid_to_hex(&the_index.oid));
si = the_index.split_index;
if (!si) {
printf("not a split index\n");
return 0;
}
- printf("base %s\n", sha1_to_hex(si->base_sha1));
+ printf("base %s\n", oid_to_hex(&si->base_oid));
for (i = 0; i < the_index.cache_nr; i++) {
struct cache_entry *ce = the_index.cache[i];
printf("%06o %s %d\t%s\n", ce->ce_mode,
diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index d7c55c2355..52870ebbb3 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "dir.h"
@@ -23,7 +24,7 @@ static void dump(struct untracked_cache_dir *ucd, struct strbuf *base)
len = base->len;
strbuf_addf(base, "%s/", ucd->name);
printf("%s %s", base->buf,
- sha1_to_hex(ucd->exclude_sha1));
+ oid_to_hex(&ucd->exclude_oid));
if (ucd->recurse)
fputs(" recurse", stdout);
if (ucd->check_only)
@@ -38,7 +39,7 @@ static void dump(struct untracked_cache_dir *ucd, struct strbuf *base)
strbuf_setlen(base, len);
}
-int cmd_main(int ac, const char **av)
+int cmd__dump_untracked_cache(int ac, const char **av)
{
struct untracked_cache *uc;
struct strbuf base = STRBUF_INIT;
diff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c
index 90dc97a9d0..a20a6161e4 100644
--- a/t/helper/test-example-decorate.c
+++ b/t/helper/test-example-decorate.c
@@ -1,8 +1,9 @@
+#include "test-tool.h"
#include "cache.h"
#include "object.h"
#include "decorate.h"
-int cmd_main(int argc, const char **argv)
+int cmd__example_decorate(int argc, const char **argv)
{
struct decoration n;
struct object_id one_oid = { {1} };
@@ -29,10 +30,10 @@ int cmd_main(int argc, const char **argv)
two = lookup_unknown_object(two_oid.hash);
ret = add_decoration(&n, one, &decoration_a);
if (ret)
- die("BUG: when adding a brand-new object, NULL should be returned");
+ BUG("when adding a brand-new object, NULL should be returned");
ret = add_decoration(&n, two, NULL);
if (ret)
- die("BUG: when adding a brand-new object, NULL should be returned");
+ BUG("when adding a brand-new object, NULL should be returned");
/*
* When re-adding an already existing object, the old decoration is
@@ -40,10 +41,10 @@ int cmd_main(int argc, const char **argv)
*/
ret = add_decoration(&n, one, NULL);
if (ret != &decoration_a)
- die("BUG: when readding an already existing object, existing decoration should be returned");
+ BUG("when readding an already existing object, existing decoration should be returned");
ret = add_decoration(&n, two, &decoration_b);
if (ret)
- die("BUG: when readding an already existing object, existing decoration should be returned");
+ BUG("when readding an already existing object, existing decoration should be returned");
/*
* Lookup returns the added declarations, or NULL if the object was
@@ -51,14 +52,14 @@ int cmd_main(int argc, const char **argv)
*/
ret = lookup_decoration(&n, one);
if (ret)
- die("BUG: lookup should return added declaration");
+ BUG("lookup should return added declaration");
ret = lookup_decoration(&n, two);
if (ret != &decoration_b)
- die("BUG: lookup should return added declaration");
+ BUG("lookup should return added declaration");
three = lookup_unknown_object(three_oid.hash);
ret = lookup_decoration(&n, three);
if (ret)
- die("BUG: lookup for unknown object should return NULL");
+ BUG("lookup for unknown object should return NULL");
/*
* The user can also loop through all entries.
@@ -68,7 +69,7 @@ int cmd_main(int argc, const char **argv)
objects_noticed++;
}
if (objects_noticed != 2)
- die("BUG: should have 2 objects");
+ BUG("should have 2 objects");
return 0;
}
diff --git a/t/helper/test-genrandom.c b/t/helper/test-genrandom.c
index 8d11d22d98..99b8dc1e2d 100644
--- a/t/helper/test-genrandom.c
+++ b/t/helper/test-genrandom.c
@@ -4,9 +4,10 @@
* Copyright (C) 2007 by Nicolas Pitre, licensed under the GPL version 2.
*/
+#include "test-tool.h"
#include "git-compat-util.h"
-int cmd_main(int argc, const char **argv)
+int cmd__genrandom(int argc, const char **argv)
{
unsigned long count, next = 0;
unsigned char *c;
diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c
index 9ae9281c07..23d2b172fe 100644
--- a/t/helper/test-hashmap.c
+++ b/t/helper/test-hashmap.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "git-compat-util.h"
#include "hashmap.h"
#include "strbuf.h"
@@ -77,7 +78,7 @@ static unsigned int hash(unsigned int method, unsigned int i, const char *key)
/*
* Test performance of hashmap.[ch]
- * Usage: time echo "perfhashmap method rounds" | test-hashmap
+ * Usage: time echo "perfhashmap method rounds" | test-tool hashmap
*/
static void perf_hashmap(unsigned int method, unsigned int rounds)
{
@@ -144,7 +145,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
*
* perfhashmap method rounds -> test hashmap.[ch] performance
*/
-int cmd_main(int argc, const char **argv)
+int cmd__hashmap(int argc, const char **argv)
{
struct strbuf line = STRBUF_INIT;
struct hashmap map;
diff --git a/t/helper/test-index-version.c b/t/helper/test-index-version.c
index f569f6b7ef..fcd10968cc 100644
--- a/t/helper/test-index-version.c
+++ b/t/helper/test-index-version.c
@@ -1,6 +1,7 @@
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int argc, const char **argv)
+int cmd__index_version(int argc, const char **argv)
{
struct cache_header hdr;
int version;
diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c
new file mode 100644
index 0000000000..37c452535f
--- /dev/null
+++ b/t/helper/test-json-writer.c
@@ -0,0 +1,565 @@
+#include "test-tool.h"
+#include "cache.h"
+#include "json-writer.h"
+
+static const char *expect_obj1 = "{\"a\":\"abc\",\"b\":42,\"c\":true}";
+static const char *expect_obj2 = "{\"a\":-1,\"b\":2147483647,\"c\":0}";
+static const char *expect_obj3 = "{\"a\":0,\"b\":4294967295,\"c\":9223372036854775807}";
+static const char *expect_obj4 = "{\"t\":true,\"f\":false,\"n\":null}";
+static const char *expect_obj5 = "{\"abc\\tdef\":\"abc\\\\def\"}";
+static const char *expect_obj6 = "{\"a\":3.14}";
+
+static const char *pretty_obj1 = ("{\n"
+ " \"a\": \"abc\",\n"
+ " \"b\": 42,\n"
+ " \"c\": true\n"
+ "}");
+static const char *pretty_obj2 = ("{\n"
+ " \"a\": -1,\n"
+ " \"b\": 2147483647,\n"
+ " \"c\": 0\n"
+ "}");
+static const char *pretty_obj3 = ("{\n"
+ " \"a\": 0,\n"
+ " \"b\": 4294967295,\n"
+ " \"c\": 9223372036854775807\n"
+ "}");
+static const char *pretty_obj4 = ("{\n"
+ " \"t\": true,\n"
+ " \"f\": false,\n"
+ " \"n\": null\n"
+ "}");
+
+static struct json_writer obj1 = JSON_WRITER_INIT;
+static struct json_writer obj2 = JSON_WRITER_INIT;
+static struct json_writer obj3 = JSON_WRITER_INIT;
+static struct json_writer obj4 = JSON_WRITER_INIT;
+static struct json_writer obj5 = JSON_WRITER_INIT;
+static struct json_writer obj6 = JSON_WRITER_INIT;
+
+static void make_obj1(int pretty)
+{
+ jw_object_begin(&obj1, pretty);
+ {
+ jw_object_string(&obj1, "a", "abc");
+ jw_object_intmax(&obj1, "b", 42);
+ jw_object_true(&obj1, "c");
+ }
+ jw_end(&obj1);
+}
+
+static void make_obj2(int pretty)
+{
+ jw_object_begin(&obj2, pretty);
+ {
+ jw_object_intmax(&obj2, "a", -1);
+ jw_object_intmax(&obj2, "b", 0x7fffffff);
+ jw_object_intmax(&obj2, "c", 0);
+ }
+ jw_end(&obj2);
+}
+
+static void make_obj3(int pretty)
+{
+ jw_object_begin(&obj3, pretty);
+ {
+ jw_object_intmax(&obj3, "a", 0);
+ jw_object_intmax(&obj3, "b", 0xffffffff);
+ jw_object_intmax(&obj3, "c", 0x7fffffffffffffffULL);
+ }
+ jw_end(&obj3);
+}
+
+static void make_obj4(int pretty)
+{
+ jw_object_begin(&obj4, pretty);
+ {
+ jw_object_true(&obj4, "t");
+ jw_object_false(&obj4, "f");
+ jw_object_null(&obj4, "n");
+ }
+ jw_end(&obj4);
+}
+
+static void make_obj5(int pretty)
+{
+ jw_object_begin(&obj5, pretty);
+ {
+ jw_object_string(&obj5, "abc" "\x09" "def", "abc" "\\" "def");
+ }
+ jw_end(&obj5);
+}
+
+static void make_obj6(int pretty)
+{
+ jw_object_begin(&obj6, pretty);
+ {
+ jw_object_double(&obj6, "a", 2, 3.14159);
+ }
+ jw_end(&obj6);
+}
+
+static const char *expect_arr1 = "[\"abc\",42,true]";
+static const char *expect_arr2 = "[-1,2147483647,0]";
+static const char *expect_arr3 = "[0,4294967295,9223372036854775807]";
+static const char *expect_arr4 = "[true,false,null]";
+
+static const char *pretty_arr1 = ("[\n"
+ " \"abc\",\n"
+ " 42,\n"
+ " true\n"
+ "]");
+static const char *pretty_arr2 = ("[\n"
+ " -1,\n"
+ " 2147483647,\n"
+ " 0\n"
+ "]");
+static const char *pretty_arr3 = ("[\n"
+ " 0,\n"
+ " 4294967295,\n"
+ " 9223372036854775807\n"
+ "]");
+static const char *pretty_arr4 = ("[\n"
+ " true,\n"
+ " false,\n"
+ " null\n"
+ "]");
+
+static struct json_writer arr1 = JSON_WRITER_INIT;
+static struct json_writer arr2 = JSON_WRITER_INIT;
+static struct json_writer arr3 = JSON_WRITER_INIT;
+static struct json_writer arr4 = JSON_WRITER_INIT;
+
+static void make_arr1(int pretty)
+{
+ jw_array_begin(&arr1, pretty);
+ {
+ jw_array_string(&arr1, "abc");
+ jw_array_intmax(&arr1, 42);
+ jw_array_true(&arr1);
+ }
+ jw_end(&arr1);
+}
+
+static void make_arr2(int pretty)
+{
+ jw_array_begin(&arr2, pretty);
+ {
+ jw_array_intmax(&arr2, -1);
+ jw_array_intmax(&arr2, 0x7fffffff);
+ jw_array_intmax(&arr2, 0);
+ }
+ jw_end(&arr2);
+}
+
+static void make_arr3(int pretty)
+{
+ jw_array_begin(&arr3, pretty);
+ {
+ jw_array_intmax(&arr3, 0);
+ jw_array_intmax(&arr3, 0xffffffff);
+ jw_array_intmax(&arr3, 0x7fffffffffffffffULL);
+ }
+ jw_end(&arr3);
+}
+
+static void make_arr4(int pretty)
+{
+ jw_array_begin(&arr4, pretty);
+ {
+ jw_array_true(&arr4);
+ jw_array_false(&arr4);
+ jw_array_null(&arr4);
+ }
+ jw_end(&arr4);
+}
+
+static char *expect_nest1 =
+ "{\"obj1\":{\"a\":\"abc\",\"b\":42,\"c\":true},\"arr1\":[\"abc\",42,true]}";
+
+static struct json_writer nest1 = JSON_WRITER_INIT;
+
+static void make_nest1(int pretty)
+{
+ jw_object_begin(&nest1, pretty);
+ {
+ jw_object_sub_jw(&nest1, "obj1", &obj1);
+ jw_object_sub_jw(&nest1, "arr1", &arr1);
+ }
+ jw_end(&nest1);
+}
+
+static char *expect_inline1 =
+ "{\"obj1\":{\"a\":\"abc\",\"b\":42,\"c\":true},\"arr1\":[\"abc\",42,true]}";
+
+static char *pretty_inline1 =
+ ("{\n"
+ " \"obj1\": {\n"
+ " \"a\": \"abc\",\n"
+ " \"b\": 42,\n"
+ " \"c\": true\n"
+ " },\n"
+ " \"arr1\": [\n"
+ " \"abc\",\n"
+ " 42,\n"
+ " true\n"
+ " ]\n"
+ "}");
+
+static struct json_writer inline1 = JSON_WRITER_INIT;
+
+static void make_inline1(int pretty)
+{
+ jw_object_begin(&inline1, pretty);
+ {
+ jw_object_inline_begin_object(&inline1, "obj1");
+ {
+ jw_object_string(&inline1, "a", "abc");
+ jw_object_intmax(&inline1, "b", 42);
+ jw_object_true(&inline1, "c");
+ }
+ jw_end(&inline1);
+ jw_object_inline_begin_array(&inline1, "arr1");
+ {
+ jw_array_string(&inline1, "abc");
+ jw_array_intmax(&inline1, 42);
+ jw_array_true(&inline1);
+ }
+ jw_end(&inline1);
+ }
+ jw_end(&inline1);
+}
+
+static char *expect_inline2 =
+ "[[1,2],[3,4],{\"a\":\"abc\"}]";
+
+static char *pretty_inline2 =
+ ("[\n"
+ " [\n"
+ " 1,\n"
+ " 2\n"
+ " ],\n"
+ " [\n"
+ " 3,\n"
+ " 4\n"
+ " ],\n"
+ " {\n"
+ " \"a\": \"abc\"\n"
+ " }\n"
+ "]");
+
+static struct json_writer inline2 = JSON_WRITER_INIT;
+
+static void make_inline2(int pretty)
+{
+ jw_array_begin(&inline2, pretty);
+ {
+ jw_array_inline_begin_array(&inline2);
+ {
+ jw_array_intmax(&inline2, 1);
+ jw_array_intmax(&inline2, 2);
+ }
+ jw_end(&inline2);
+ jw_array_inline_begin_array(&inline2);
+ {
+ jw_array_intmax(&inline2, 3);
+ jw_array_intmax(&inline2, 4);
+ }
+ jw_end(&inline2);
+ jw_array_inline_begin_object(&inline2);
+ {
+ jw_object_string(&inline2, "a", "abc");
+ }
+ jw_end(&inline2);
+ }
+ jw_end(&inline2);
+}
+
+/*
+ * When super is compact, we expect subs to be compacted (even if originally
+ * pretty).
+ */
+static const char *expect_mixed1 =
+ ("{\"obj1\":{\"a\":\"abc\",\"b\":42,\"c\":true},"
+ "\"arr1\":[\"abc\",42,true]}");
+
+/*
+ * When super is pretty, a compact sub (obj1) is kept compact and a pretty
+ * sub (arr1) is re-indented.
+ */
+static const char *pretty_mixed1 =
+ ("{\n"
+ " \"obj1\": {\"a\":\"abc\",\"b\":42,\"c\":true},\n"
+ " \"arr1\": [\n"
+ " \"abc\",\n"
+ " 42,\n"
+ " true\n"
+ " ]\n"
+ "}");
+
+static struct json_writer mixed1 = JSON_WRITER_INIT;
+
+static void make_mixed1(int pretty)
+{
+ jw_init(&obj1);
+ jw_init(&arr1);
+
+ make_obj1(0); /* obj1 is compact */
+ make_arr1(1); /* arr1 is pretty */
+
+ jw_object_begin(&mixed1, pretty);
+ {
+ jw_object_sub_jw(&mixed1, "obj1", &obj1);
+ jw_object_sub_jw(&mixed1, "arr1", &arr1);
+ }
+ jw_end(&mixed1);
+}
+
+static void cmp(const char *test, const struct json_writer *jw, const char *exp)
+{
+ if (!strcmp(jw->json.buf, exp))
+ return;
+
+ printf("error[%s]: observed '%s' expected '%s'\n",
+ test, jw->json.buf, exp);
+ exit(1);
+}
+
+#define t(v) do { make_##v(0); cmp(#v, &v, expect_##v); } while (0)
+#define p(v) do { make_##v(1); cmp(#v, &v, pretty_##v); } while (0)
+
+/*
+ * Run some basic regression tests with some known patterns.
+ * These tests also demonstrate how to use the jw_ API.
+ */
+static int unit_tests(void)
+{
+ /* comptact (canonical) forms */
+ t(obj1);
+ t(obj2);
+ t(obj3);
+ t(obj4);
+ t(obj5);
+ t(obj6);
+
+ t(arr1);
+ t(arr2);
+ t(arr3);
+ t(arr4);
+
+ t(nest1);
+
+ t(inline1);
+ t(inline2);
+
+ jw_init(&obj1);
+ jw_init(&obj2);
+ jw_init(&obj3);
+ jw_init(&obj4);
+
+ jw_init(&arr1);
+ jw_init(&arr2);
+ jw_init(&arr3);
+ jw_init(&arr4);
+
+ jw_init(&inline1);
+ jw_init(&inline2);
+
+ /* pretty forms */
+ p(obj1);
+ p(obj2);
+ p(obj3);
+ p(obj4);
+
+ p(arr1);
+ p(arr2);
+ p(arr3);
+ p(arr4);
+
+ p(inline1);
+ p(inline2);
+
+ /* mixed forms */
+ t(mixed1);
+ jw_init(&mixed1);
+ p(mixed1);
+
+ return 0;
+}
+
+static void get_s(int line_nr, char **s_in)
+{
+ *s_in = strtok(NULL, " ");
+ if (!*s_in)
+ die("line[%d]: expected: <s>", line_nr);
+}
+
+static void get_i(int line_nr, intmax_t *s_in)
+{
+ char *s;
+ char *endptr;
+
+ get_s(line_nr, &s);
+
+ *s_in = strtol(s, &endptr, 10);
+ if (*endptr || errno == ERANGE)
+ die("line[%d]: invalid integer value", line_nr);
+}
+
+static void get_d(int line_nr, double *s_in)
+{
+ char *s;
+ char *endptr;
+
+ get_s(line_nr, &s);
+
+ *s_in = strtod(s, &endptr);
+ if (*endptr || errno == ERANGE)
+ die("line[%d]: invalid float value", line_nr);
+}
+
+static int pretty;
+
+#define MAX_LINE_LENGTH (64 * 1024)
+
+static char *get_trimmed_line(char *buf, int buf_size)
+{
+ int len;
+
+ if (!fgets(buf, buf_size, stdin))
+ return NULL;
+
+ len = strlen(buf);
+ while (len > 0) {
+ char c = buf[len - 1];
+ if (c == '\n' || c == '\r' || c == ' ' || c == '\t')
+ buf[--len] = 0;
+ else
+ break;
+ }
+
+ while (*buf == ' ' || *buf == '\t')
+ buf++;
+
+ return buf;
+}
+
+static int scripted(void)
+{
+ struct json_writer jw = JSON_WRITER_INIT;
+ char buf[MAX_LINE_LENGTH];
+ char *line;
+ int line_nr = 0;
+
+ line = get_trimmed_line(buf, MAX_LINE_LENGTH);
+ if (!line)
+ return 0;
+
+ if (!strcmp(line, "object"))
+ jw_object_begin(&jw, pretty);
+ else if (!strcmp(line, "array"))
+ jw_array_begin(&jw, pretty);
+ else
+ die("expected first line to be 'object' or 'array'");
+
+ while ((line = get_trimmed_line(buf, MAX_LINE_LENGTH)) != NULL) {
+ char *verb;
+ char *key;
+ char *s_value;
+ intmax_t i_value;
+ double d_value;
+
+ line_nr++;
+
+ verb = strtok(line, " ");
+
+ if (!strcmp(verb, "end")) {
+ jw_end(&jw);
+ }
+ else if (!strcmp(verb, "object-string")) {
+ get_s(line_nr, &key);
+ get_s(line_nr, &s_value);
+ jw_object_string(&jw, key, s_value);
+ }
+ else if (!strcmp(verb, "object-int")) {
+ get_s(line_nr, &key);
+ get_i(line_nr, &i_value);
+ jw_object_intmax(&jw, key, i_value);
+ }
+ else if (!strcmp(verb, "object-double")) {
+ get_s(line_nr, &key);
+ get_i(line_nr, &i_value);
+ get_d(line_nr, &d_value);
+ jw_object_double(&jw, key, i_value, d_value);
+ }
+ else if (!strcmp(verb, "object-true")) {
+ get_s(line_nr, &key);
+ jw_object_true(&jw, key);
+ }
+ else if (!strcmp(verb, "object-false")) {
+ get_s(line_nr, &key);
+ jw_object_false(&jw, key);
+ }
+ else if (!strcmp(verb, "object-null")) {
+ get_s(line_nr, &key);
+ jw_object_null(&jw, key);
+ }
+ else if (!strcmp(verb, "object-object")) {
+ get_s(line_nr, &key);
+ jw_object_inline_begin_object(&jw, key);
+ }
+ else if (!strcmp(verb, "object-array")) {
+ get_s(line_nr, &key);
+ jw_object_inline_begin_array(&jw, key);
+ }
+ else if (!strcmp(verb, "array-string")) {
+ get_s(line_nr, &s_value);
+ jw_array_string(&jw, s_value);
+ }
+ else if (!strcmp(verb, "array-int")) {
+ get_i(line_nr, &i_value);
+ jw_array_intmax(&jw, i_value);
+ }
+ else if (!strcmp(verb, "array-double")) {
+ get_i(line_nr, &i_value);
+ get_d(line_nr, &d_value);
+ jw_array_double(&jw, i_value, d_value);
+ }
+ else if (!strcmp(verb, "array-true"))
+ jw_array_true(&jw);
+ else if (!strcmp(verb, "array-false"))
+ jw_array_false(&jw);
+ else if (!strcmp(verb, "array-null"))
+ jw_array_null(&jw);
+ else if (!strcmp(verb, "array-object"))
+ jw_array_inline_begin_object(&jw);
+ else if (!strcmp(verb, "array-array"))
+ jw_array_inline_begin_array(&jw);
+ else
+ die("unrecognized token: '%s'", verb);
+ }
+
+ if (!jw_is_terminated(&jw))
+ die("json not terminated: '%s'", jw.json.buf);
+
+ printf("%s\n", jw.json.buf);
+
+ strbuf_release(&jw.json);
+ return 0;
+}
+
+int cmd__json_writer(int argc, const char **argv)
+{
+ argc--; /* skip over "json-writer" arg */
+ argv++;
+
+ if (argc > 0 && argv[0][0] == '-') {
+ if (!strcmp(argv[0], "-u") || !strcmp(argv[0], "--unit"))
+ return unit_tests();
+
+ if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--pretty"))
+ pretty = 1;
+ }
+
+ return scripted();
+}
diff --git a/t/helper/test-lazy-init-name-hash.c b/t/helper/test-lazy-init-name-hash.c
index 297fb01d61..b99a37080d 100644
--- a/t/helper/test-lazy-init-name-hash.c
+++ b/t/helper/test-lazy-init-name-hash.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "parse-options.h"
@@ -184,14 +185,14 @@ static void analyze_run(void)
}
}
-int cmd_main(int argc, const char **argv)
+int cmd__lazy_init_name_hash(int argc, const char **argv)
{
const char *usage[] = {
- "test-lazy-init-name-hash -d (-s | -m)",
- "test-lazy-init-name-hash -p [-c c]",
- "test-lazy-init-name-hash -a a [--step s] [-c c]",
- "test-lazy-init-name-hash (-s | -m) [-c c]",
- "test-lazy-init-name-hash -s -m [-c c]",
+ "test-tool lazy-init-name-hash -d (-s | -m)",
+ "test-tool lazy-init-name-hash -p [-c c]",
+ "test-tool lazy-init-name-hash -a a [--step s] [-c c]",
+ "test-tool lazy-init-name-hash (-s | -m) [-c c]",
+ "test-tool lazy-init-name-hash -s -m [-c c]",
NULL
};
struct option options[] = {
diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c
index 356d8edef1..96857f26ac 100644
--- a/t/helper/test-match-trees.c
+++ b/t/helper/test-match-trees.c
@@ -1,7 +1,8 @@
+#include "test-tool.h"
#include "cache.h"
#include "tree.h"
-int cmd_main(int ac, const char **av)
+int cmd__match_trees(int ac, const char **av)
{
struct object_id hash1, hash2, shifted;
struct tree *one, *two;
diff --git a/t/helper/test-mergesort.c b/t/helper/test-mergesort.c
index 335cf6b626..c5cffaa4b7 100644
--- a/t/helper/test-mergesort.c
+++ b/t/helper/test-mergesort.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "mergesort.h"
@@ -22,7 +23,7 @@ static int compare_strings(const void *a, const void *b)
return strcmp(x->text, y->text);
}
-int cmd_main(int argc, const char **argv)
+int cmd__mergesort(int argc, const char **argv)
{
struct line *line, *p = NULL, *lines = NULL;
struct strbuf sb = STRBUF_INIT;
diff --git a/t/helper/test-mktemp.c b/t/helper/test-mktemp.c
index 89d9b2f7be..2290688940 100644
--- a/t/helper/test-mktemp.c
+++ b/t/helper/test-mktemp.c
@@ -1,9 +1,10 @@
/*
* test-mktemp.c: code to exercise the creation of temporary files
*/
+#include "test-tool.h"
#include "git-compat-util.h"
-int cmd_main(int argc, const char **argv)
+int cmd__mktemp(int argc, const char **argv)
{
if (argc != 2)
usage("Expected 1 parameter defining the temporary file template");
diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
index 06c09c6b88..8cb0d53840 100644
--- a/t/helper/test-online-cpus.c
+++ b/t/helper/test-online-cpus.c
@@ -1,7 +1,8 @@
+#include "test-tool.h"
#include "git-compat-util.h"
#include "thread-utils.h"
-int cmd_main(int argc, const char **argv)
+int cmd__online_cpus(int argc, const char **argv)
{
printf("%d\n", online_cpus());
return 0;
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index 630c76d127..47fee660b8 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "parse-options.h"
#include "string-list.h"
@@ -35,6 +36,7 @@ static int length_callback(const struct option *opt, const char *arg, int unset)
static int number_callback(const struct option *opt, const char *arg, int unset)
{
+ BUG_ON_OPT_NEG(unset);
*(int *)opt->value = strtol(arg, NULL, 10);
return 0;
}
@@ -94,11 +96,11 @@ static void show(struct string_list *expect, int *status, const char *fmt, ...)
strbuf_release(&buf);
}
-int cmd_main(int argc, const char **argv)
+int cmd__parse_options(int argc, const char **argv)
{
const char *prefix = "prefix/";
const char *usage[] = {
- "test-parse-options <options>",
+ "test-tool parse-options <options>",
"",
"A helper function for the parse-options API.",
NULL
@@ -118,7 +120,6 @@ int cmd_main(int argc, const char **argv)
OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"),
OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
- OPT_DATE('t', NULL, &timestamp, "get timestamp of <time>"),
OPT_CALLBACK('L', "length", &integer, "str",
"get length of <str>", length_callback),
OPT_FILENAME('F', "file", &file, "set file to <file>"),
diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c
index 2b3c5092a1..ae091d9b3e 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -1,5 +1,7 @@
+#include "test-tool.h"
#include "cache.h"
#include "string-list.h"
+#include "utf8.h"
/*
* A "string_list_each_func_t" function that normalizes an entry from
@@ -170,7 +172,12 @@ static struct test_data dirname_data[] = {
{ NULL, NULL }
};
-int cmd_main(int argc, const char **argv)
+static int is_dotgitmodules(const char *path)
+{
+ return is_hfs_dotgitmodules(path) || is_ntfs_dotgitmodules(path);
+}
+
+int cmd__path_utils(int argc, const char **argv)
{
if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) {
char *buf = xmallocz(strlen(argv[2]));
@@ -270,6 +277,20 @@ int cmd_main(int argc, const char **argv)
if (argc == 2 && !strcmp(argv[1], "dirname"))
return test_function(dirname_data, posix_dirname, argv[1]);
+ if (argc > 2 && !strcmp(argv[1], "is_dotgitmodules")) {
+ int res = 0, expect = 1, i;
+ for (i = 2; i < argc; i++)
+ if (!strcmp("--not", argv[i]))
+ expect = !expect;
+ else if (expect != is_dotgitmodules(argv[i]))
+ res = error("'%s' is %s.gitmodules", argv[i],
+ expect ? "not " : "");
+ else
+ fprintf(stderr, "ok: '%s' is %s.gitmodules\n",
+ argv[i], expect ? "" : "not ");
+ return !!res;
+ }
+
fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
argv[1] ? argv[1] : "(there was none)");
return 1;
diff --git a/t/helper/test-pkt-line.c b/t/helper/test-pkt-line.c
new file mode 100644
index 0000000000..282d536384
--- /dev/null
+++ b/t/helper/test-pkt-line.c
@@ -0,0 +1,98 @@
+#include "cache.h"
+#include "test-tool.h"
+#include "pkt-line.h"
+
+static void pack_line(const char *line)
+{
+ if (!strcmp(line, "0000") || !strcmp(line, "0000\n"))
+ packet_flush(1);
+ else if (!strcmp(line, "0001") || !strcmp(line, "0001\n"))
+ packet_delim(1);
+ else
+ packet_write_fmt(1, "%s", line);
+}
+
+static void pack(int argc, const char **argv)
+{
+ if (argc) { /* read from argv */
+ int i;
+ for (i = 0; i < argc; i++)
+ pack_line(argv[i]);
+ } else { /* read from stdin */
+ char line[LARGE_PACKET_MAX];
+ while (fgets(line, sizeof(line), stdin)) {
+ pack_line(line);
+ }
+ }
+}
+
+static void unpack(void)
+{
+ struct packet_reader reader;
+ packet_reader_init(&reader, 0, NULL, 0,
+ PACKET_READ_GENTLE_ON_EOF |
+ PACKET_READ_CHOMP_NEWLINE);
+
+ while (packet_reader_read(&reader) != PACKET_READ_EOF) {
+ switch (reader.status) {
+ case PACKET_READ_EOF:
+ break;
+ case PACKET_READ_NORMAL:
+ printf("%s\n", reader.line);
+ break;
+ case PACKET_READ_FLUSH:
+ printf("0000\n");
+ break;
+ case PACKET_READ_DELIM:
+ printf("0001\n");
+ break;
+ }
+ }
+}
+
+static void unpack_sideband(void)
+{
+ struct packet_reader reader;
+ packet_reader_init(&reader, 0, NULL, 0,
+ PACKET_READ_GENTLE_ON_EOF |
+ PACKET_READ_CHOMP_NEWLINE);
+
+ while (packet_reader_read(&reader) != PACKET_READ_EOF) {
+ int band;
+ int fd;
+
+ switch (reader.status) {
+ case PACKET_READ_EOF:
+ break;
+ case PACKET_READ_NORMAL:
+ band = reader.line[0] & 0xff;
+ if (band < 1 || band > 2)
+ die("unexpected side band %d", band);
+ fd = band;
+
+ write_or_die(fd, reader.line + 1, reader.pktlen - 1);
+ break;
+ case PACKET_READ_FLUSH:
+ return;
+ case PACKET_READ_DELIM:
+ break;
+ }
+ }
+}
+
+int cmd__pkt_line(int argc, const char **argv)
+{
+ if (argc < 2)
+ die("too few arguments");
+
+ if (!strcmp(argv[1], "pack"))
+ pack(argc - 2, argv + 2);
+ else if (!strcmp(argv[1], "unpack"))
+ unpack();
+ else if (!strcmp(argv[1], "unpack-sideband"))
+ unpack_sideband();
+ else
+ die("invalid argument '%s'", argv[1]);
+
+ return 0;
+}
diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c
index ae58fff359..5bc9c46ea5 100644
--- a/t/helper/test-prio-queue.c
+++ b/t/helper/test-prio-queue.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "prio-queue.h"
@@ -16,19 +17,29 @@ static void show(int *v)
free(v);
}
-int cmd_main(int argc, const char **argv)
+int cmd__prio_queue(int argc, const char **argv)
{
struct prio_queue pq = { intcmp };
while (*++argv) {
- if (!strcmp(*argv, "get"))
- show(prio_queue_get(&pq));
- else if (!strcmp(*argv, "dump")) {
- int *v;
- while ((v = prio_queue_get(&pq)))
- show(v);
- }
- else {
+ if (!strcmp(*argv, "get")) {
+ void *peek = prio_queue_peek(&pq);
+ void *get = prio_queue_get(&pq);
+ if (peek != get)
+ BUG("peek and get results do not match");
+ show(get);
+ } else if (!strcmp(*argv, "dump")) {
+ void *peek;
+ void *get;
+ while ((peek = prio_queue_peek(&pq))) {
+ get = prio_queue_get(&pq);
+ if (peek != get)
+ BUG("peek and get results do not match");
+ show(get);
+ }
+ } else if (!strcmp(*argv, "stack")) {
+ pq.compare = NULL;
+ } else {
int *v = malloc(sizeof(*v));
*v = atoi(*argv);
prio_queue_put(&pq, v);
diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
new file mode 100644
index 0000000000..a0272178b7
--- /dev/null
+++ b/t/helper/test-reach.c
@@ -0,0 +1,168 @@
+#include "test-tool.h"
+#include "cache.h"
+#include "commit.h"
+#include "commit-reach.h"
+#include "config.h"
+#include "parse-options.h"
+#include "ref-filter.h"
+#include "string-list.h"
+#include "tag.h"
+
+static void print_sorted_commit_ids(struct commit_list *list)
+{
+ int i;
+ struct string_list s = STRING_LIST_INIT_DUP;
+
+ while (list) {
+ string_list_append(&s, oid_to_hex(&list->item->object.oid));
+ list = list->next;
+ }
+
+ string_list_sort(&s);
+
+ for (i = 0; i < s.nr; i++)
+ printf("%s\n", s.items[i].string);
+
+ string_list_clear(&s, 0);
+}
+
+int cmd__reach(int ac, const char **av)
+{
+ struct object_id oid_A, oid_B;
+ struct commit *A, *B;
+ struct commit_list *X, *Y;
+ struct object_array X_obj = OBJECT_ARRAY_INIT;
+ struct commit **X_array, **Y_array;
+ int X_nr, X_alloc, Y_nr, Y_alloc;
+ struct strbuf buf = STRBUF_INIT;
+ struct repository *r = the_repository;
+
+ setup_git_directory();
+
+ if (ac < 2)
+ exit(1);
+
+ A = B = NULL;
+ X = Y = NULL;
+ X_nr = Y_nr = 0;
+ X_alloc = Y_alloc = 16;
+ ALLOC_ARRAY(X_array, X_alloc);
+ ALLOC_ARRAY(Y_array, Y_alloc);
+
+ while (strbuf_getline(&buf, stdin) != EOF) {
+ struct object_id oid;
+ struct object *orig;
+ struct object *peeled;
+ struct commit *c;
+ if (buf.len < 3)
+ continue;
+
+ if (get_oid_committish(buf.buf + 2, &oid))
+ die("failed to resolve %s", buf.buf + 2);
+
+ orig = parse_object(r, &oid);
+ peeled = deref_tag_noverify(orig);
+
+ if (!peeled)
+ die("failed to load commit for input %s resulting in oid %s\n",
+ buf.buf, oid_to_hex(&oid));
+
+ c = object_as_type(r, peeled, OBJ_COMMIT, 0);
+
+ if (!c)
+ die("failed to load commit for input %s resulting in oid %s\n",
+ buf.buf, oid_to_hex(&oid));
+
+ switch (buf.buf[0]) {
+ case 'A':
+ oidcpy(&oid_A, &oid);
+ A = c;
+ break;
+
+ case 'B':
+ oidcpy(&oid_B, &oid);
+ B = c;
+ break;
+
+ case 'X':
+ commit_list_insert(c, &X);
+ ALLOC_GROW(X_array, X_nr + 1, X_alloc);
+ X_array[X_nr++] = c;
+ add_object_array(orig, NULL, &X_obj);
+ break;
+
+ case 'Y':
+ commit_list_insert(c, &Y);
+ ALLOC_GROW(Y_array, Y_nr + 1, Y_alloc);
+ Y_array[Y_nr++] = c;
+ break;
+
+ default:
+ die("unexpected start of line: %c", buf.buf[0]);
+ }
+ }
+ strbuf_release(&buf);
+
+ if (!strcmp(av[1], "ref_newer"))
+ printf("%s(A,B):%d\n", av[1], ref_newer(&oid_A, &oid_B));
+ else if (!strcmp(av[1], "in_merge_bases"))
+ printf("%s(A,B):%d\n", av[1], in_merge_bases(A, B));
+ else if (!strcmp(av[1], "is_descendant_of"))
+ printf("%s(A,X):%d\n", av[1], is_descendant_of(A, X));
+ else if (!strcmp(av[1], "get_merge_bases_many")) {
+ struct commit_list *list = get_merge_bases_many(A, X_nr, X_array);
+ printf("%s(A,X):\n", av[1]);
+ print_sorted_commit_ids(list);
+ } else if (!strcmp(av[1], "reduce_heads")) {
+ struct commit_list *list = reduce_heads(X);
+ printf("%s(X):\n", av[1]);
+ print_sorted_commit_ids(list);
+ } else if (!strcmp(av[1], "can_all_from_reach")) {
+ printf("%s(X,Y):%d\n", av[1], can_all_from_reach(X, Y, 1));
+ } else if (!strcmp(av[1], "can_all_from_reach_with_flag")) {
+ struct commit_list *iter = Y;
+
+ while (iter) {
+ iter->item->object.flags |= 2;
+ iter = iter->next;
+ }
+
+ printf("%s(X,_,_,0,0):%d\n", av[1], can_all_from_reach_with_flag(&X_obj, 2, 4, 0, 0));
+ } else if (!strcmp(av[1], "commit_contains")) {
+ struct ref_filter filter;
+ struct contains_cache cache;
+ init_contains_cache(&cache);
+
+ if (ac > 2 && !strcmp(av[2], "--tag"))
+ filter.with_commit_tag_algo = 1;
+ else
+ filter.with_commit_tag_algo = 0;
+
+ printf("%s(_,A,X,_):%d\n", av[1], commit_contains(&filter, A, X, &cache));
+ } else if (!strcmp(av[1], "get_reachable_subset")) {
+ const int reachable_flag = 1;
+ int i, count = 0;
+ struct commit_list *current;
+ struct commit_list *list = get_reachable_subset(X_array, X_nr,
+ Y_array, Y_nr,
+ reachable_flag);
+ printf("get_reachable_subset(X,Y)\n");
+ for (current = list; current; current = current->next) {
+ if (!(list->item->object.flags & reachable_flag))
+ die(_("commit %s is not marked reachable"),
+ oid_to_hex(&list->item->object.oid));
+ count++;
+ }
+ for (i = 0; i < Y_nr; i++) {
+ if (Y_array[i]->object.flags & reachable_flag)
+ count--;
+ }
+
+ if (count < 0)
+ die(_("too many commits marked reachable"));
+
+ print_sorted_commit_ids(list);
+ }
+
+ exit(0);
+}
diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index 48255eef31..d674c88ba0 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -1,6 +1,7 @@
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int argc, const char **argv)
+int cmd__read_cache(int argc, const char **argv)
{
int i, cnt = 1;
if (argc == 2)
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
new file mode 100644
index 0000000000..831b586d02
--- /dev/null
+++ b/t/helper/test-read-midx.c
@@ -0,0 +1,51 @@
+#include "test-tool.h"
+#include "cache.h"
+#include "midx.h"
+#include "repository.h"
+#include "object-store.h"
+
+static int read_midx_file(const char *object_dir)
+{
+ uint32_t i;
+ struct multi_pack_index *m = load_multi_pack_index(object_dir, 1);
+
+ if (!m)
+ return 1;
+
+ printf("header: %08x %d %d %d\n",
+ m->signature,
+ m->version,
+ m->num_chunks,
+ m->num_packs);
+
+ printf("chunks:");
+
+ if (m->chunk_pack_names)
+ printf(" pack-names");
+ if (m->chunk_oid_fanout)
+ printf(" oid-fanout");
+ if (m->chunk_oid_lookup)
+ printf(" oid-lookup");
+ if (m->chunk_object_offsets)
+ printf(" object-offsets");
+ if (m->chunk_large_offsets)
+ printf(" large-offsets");
+
+ printf("\nnum_objects: %d\n", m->num_objects);
+
+ printf("packs:\n");
+ for (i = 0; i < m->num_packs; i++)
+ printf("%s\n", m->pack_names[i]);
+
+ printf("object-dir: %s\n", m->object_dir);
+
+ return 0;
+}
+
+int cmd__read_midx(int argc, const char **argv)
+{
+ if (argc != 2)
+ usage("read-midx <object-dir>");
+
+ return read_midx_file(argv[1]);
+}
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 7120634b04..e9e0541276 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -1,6 +1,9 @@
+#include "test-tool.h"
#include "cache.h"
#include "refs.h"
#include "worktree.h"
+#include "object-store.h"
+#include "repository.h"
static const char *notnull(const char *arg, const char *name)
{
@@ -21,7 +24,7 @@ static const char **get_store(const char **argv, struct ref_store **refs)
if (!argv[0]) {
die("ref store required");
} else if (!strcmp(argv[0], "main")) {
- *refs = get_main_ref_store();
+ *refs = get_main_ref_store(the_repository);
} else if (skip_prefix(argv[0], "submodule:", &gitdir)) {
struct strbuf sb = STRBUF_INIT;
int ret;
@@ -274,7 +277,7 @@ static struct command commands[] = {
{ NULL, NULL }
};
-int cmd_main(int argc, const char **argv)
+int cmd__ref_store(int argc, const char **argv)
{
struct ref_store *refs;
const char *func;
diff --git a/t/helper/test-regex.c b/t/helper/test-regex.c
index b5ea8a97c5..10284cc56f 100644
--- a/t/helper/test-regex.c
+++ b/t/helper/test-regex.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "git-compat-util.h"
#include "gettext.h"
@@ -36,7 +37,7 @@ static int test_regex_bug(void)
return 0;
}
-int cmd_main(int argc, const char **argv)
+int cmd__regex(int argc, const char **argv)
{
const char *pat;
const char *str;
@@ -47,8 +48,8 @@ int cmd_main(int argc, const char **argv)
if (argc == 2 && !strcmp(argv[1], "--bug"))
return test_regex_bug();
else if (argc < 3)
- usage("test-regex --bug\n"
- "test-regex <pattern> <string> [<options>]");
+ usage("test-tool regex --bug\n"
+ "test-tool regex <pattern> <string> [<options>]");
argv++;
pat = *argv++;
diff --git a/t/helper/test-repository.c b/t/helper/test-repository.c
new file mode 100644
index 0000000000..6a84a53efb
--- /dev/null
+++ b/t/helper/test-repository.c
@@ -0,0 +1,88 @@
+#include "test-tool.h"
+#include "cache.h"
+#include "commit-graph.h"
+#include "commit.h"
+#include "config.h"
+#include "object-store.h"
+#include "object.h"
+#include "repository.h"
+#include "tree.h"
+
+static void test_parse_commit_in_graph(const char *gitdir, const char *worktree,
+ const struct object_id *commit_oid)
+{
+ struct repository r;
+ struct commit *c;
+ struct commit_list *parent;
+
+ setup_git_env(gitdir);
+
+ if (repo_init(&r, gitdir, worktree))
+ die("Couldn't init repo");
+
+ c = lookup_commit(&r, commit_oid);
+
+ if (!parse_commit_in_graph(&r, c))
+ die("Couldn't parse commit");
+
+ printf("%"PRItime, c->date);
+ for (parent = c->parents; parent; parent = parent->next)
+ printf(" %s", oid_to_hex(&parent->item->object.oid));
+ printf("\n");
+
+ repo_clear(&r);
+}
+
+static void test_get_commit_tree_in_graph(const char *gitdir,
+ const char *worktree,
+ const struct object_id *commit_oid)
+{
+ struct repository r;
+ struct commit *c;
+ struct tree *tree;
+
+ setup_git_env(gitdir);
+
+ if (repo_init(&r, gitdir, worktree))
+ die("Couldn't init repo");
+
+ c = lookup_commit(&r, commit_oid);
+
+ /*
+ * get_commit_tree_in_graph does not automatically parse the commit, so
+ * parse it first.
+ */
+ if (!parse_commit_in_graph(&r, c))
+ die("Couldn't parse commit");
+ tree = get_commit_tree_in_graph(&r, c);
+ if (!tree)
+ die("Couldn't get commit tree");
+
+ printf("%s\n", oid_to_hex(&tree->object.oid));
+
+ repo_clear(&r);
+}
+
+int cmd__repository(int argc, const char **argv)
+{
+ if (argc < 2)
+ die("must have at least 2 arguments");
+ if (!strcmp(argv[1], "parse_commit_in_graph")) {
+ struct object_id oid;
+ if (argc < 5)
+ die("not enough arguments");
+ if (parse_oid_hex(argv[4], &oid, &argv[4]))
+ die("cannot parse oid '%s'", argv[4]);
+ test_parse_commit_in_graph(argv[2], argv[3], &oid);
+ } else if (!strcmp(argv[1], "get_commit_tree_in_graph")) {
+ struct object_id oid;
+ if (argc < 5)
+ die("not enough arguments");
+ if (parse_oid_hex(argv[4], &oid, &argv[4]))
+ die("cannot parse oid '%s'", argv[4]);
+ test_get_commit_tree_in_graph(argv[2], argv[3], &oid);
+ } else {
+ die("unrecognized '%s'", argv[1]);
+ }
+ return 0;
+}
diff --git a/t/helper/test-revision-walking.c b/t/helper/test-revision-walking.c
index b8e6fe1d00..625b2dbf82 100644
--- a/t/helper/test-revision-walking.c
+++ b/t/helper/test-revision-walking.c
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
+#include "test-tool.h"
#include "cache.h"
#include "commit.h"
#include "diff.h"
@@ -31,7 +32,7 @@ static int run_revision_walk(void)
int argc = ARRAY_SIZE(argv) - 1;
int got_revision = 0;
- init_revisions(&rev, NULL);
+ repo_init_revisions(the_repository, &rev, NULL);
setup_revisions(argc, argv, &rev, NULL);
if (prepare_revision_walk(&rev))
die("revision walk setup failed");
@@ -45,7 +46,7 @@ static int run_revision_walk(void)
return got_revision;
}
-int cmd_main(int argc, const char **argv)
+int cmd__revision_walking(int argc, const char **argv)
{
if (argc < 2)
return 1;
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index 153342e44d..2cc93bb69c 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
+#include "test-tool.h"
#include "git-compat-util.h"
#include "run-command.h"
#include "argv-array.h"
@@ -49,7 +50,7 @@ static int task_finished(int result,
return 1;
}
-int cmd_main(int argc, const char **argv)
+int cmd__run_command(int argc, const char **argv)
{
struct child_process proc = CHILD_PROCESS_INIT;
int jobs;
diff --git a/t/helper/test-scrap-cache-tree.c b/t/helper/test-scrap-cache-tree.c
index d2a63bea43..393f1604ff 100644
--- a/t/helper/test-scrap-cache-tree.c
+++ b/t/helper/test-scrap-cache-tree.c
@@ -1,12 +1,13 @@
+#include "test-tool.h"
#include "cache.h"
#include "lockfile.h"
#include "tree.h"
#include "cache-tree.h"
-static struct lock_file index_lock;
-
-int cmd_main(int ac, const char **av)
+int cmd__scrap_cache_tree(int ac, const char **av)
{
+ struct lock_file index_lock = LOCK_INIT;
+
setup_git_directory();
hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
if (read_cache() < 0)
diff --git a/t/helper/test-sha1-array.c b/t/helper/test-sha1-array.c
index edfd52d82a..ad5e69f9d3 100644
--- a/t/helper/test-sha1-array.c
+++ b/t/helper/test-sha1-array.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "sha1-array.h"
@@ -7,7 +8,7 @@ static int print_oid(const struct object_id *oid, void *data)
return 0;
}
-int cmd_main(int argc, const char **argv)
+int cmd__sha1_array(int argc, const char **argv)
{
struct oid_array array = OID_ARRAY_INIT;
struct strbuf line = STRBUF_INIT;
diff --git a/t/helper/test-sha1.c b/t/helper/test-sha1.c
index a1c13f54ec..1ba0675c75 100644
--- a/t/helper/test-sha1.c
+++ b/t/helper/test-sha1.c
@@ -1,6 +1,7 @@
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int ac, const char **av)
+int cmd__sha1(int ac, const char **av)
{
git_SHA_CTX ctx;
unsigned char sha1[20];
diff --git a/t/helper/test-sha1.sh b/t/helper/test-sha1.sh
index 750b95a0a1..84594885c7 100755
--- a/t/helper/test-sha1.sh
+++ b/t/helper/test-sha1.sh
@@ -1,7 +1,7 @@
#!/bin/sh
dd if=/dev/zero bs=1048576 count=100 2>/dev/null |
-/usr/bin/time t/helper/test-sha1 >/dev/null
+/usr/bin/time t/helper/test-tool sha1 >/dev/null
while read expect cnt pfx
do
@@ -11,7 +11,7 @@ do
test -z "$pfx" || echo "$pfx"
dd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null |
perl -pe 'y/\000/g/'
- } | ./t/helper/test-sha1 $cnt
+ } | ./t/helper/test-tool sha1 $cnt
)
if test "$expect" = "$actual"
then
diff --git a/t/helper/test-sigchain.c b/t/helper/test-sigchain.c
index b71edbd442..77ac5bc33f 100644
--- a/t/helper/test-sigchain.c
+++ b/t/helper/test-sigchain.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "sigchain.h"
@@ -13,7 +14,7 @@ X(two)
X(three)
#undef X
-int cmd_main(int argc, const char **argv) {
+int cmd__sigchain(int argc, const char **argv) {
sigchain_push(SIGTERM, one);
sigchain_push(SIGTERM, two);
sigchain_push(SIGTERM, three);
diff --git a/t/helper/test-strcmp-offset.c b/t/helper/test-strcmp-offset.c
index e159c9a127..44e4a6d143 100644
--- a/t/helper/test-strcmp-offset.c
+++ b/t/helper/test-strcmp-offset.c
@@ -1,6 +1,7 @@
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int argc, const char **argv)
+int cmd__strcmp_offset(int argc, const char **argv)
{
int result;
size_t offset;
diff --git a/t/helper/test-string-list.c b/t/helper/test-string-list.c
index 829ec3d7d2..2123dda85b 100644
--- a/t/helper/test-string-list.c
+++ b/t/helper/test-string-list.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "string-list.h"
@@ -41,7 +42,7 @@ static int prefix_cb(struct string_list_item *item, void *cb_data)
return starts_with(item->string, prefix);
}
-int cmd_main(int argc, const char **argv)
+int cmd__string_list(int argc, const char **argv)
{
if (argc == 5 && !strcmp(argv[1], "split")) {
struct string_list list = STRING_LIST_INIT_DUP;
diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index f23db3b19a..e2692746df 100644
--- a/t/helper/test-submodule-config.c
+++ b/t/helper/test-submodule-config.c
@@ -1,3 +1,4 @@
+#include "test-tool.h"
#include "cache.h"
#include "config.h"
#include "submodule-config.h"
@@ -10,7 +11,7 @@ static void die_usage(int argc, const char **argv, const char *msg)
exit(1);
}
-int cmd_main(int argc, const char **argv)
+int cmd__submodule_config(int argc, const char **argv)
{
const char **arg = argv;
int my_argc = argc;
@@ -48,9 +49,11 @@ int cmd_main(int argc, const char **argv)
die_usage(argc, argv, "Commit not found.");
if (lookup_name) {
- submodule = submodule_from_name(&commit_oid, path_or_name);
+ submodule = submodule_from_name(the_repository,
+ &commit_oid, path_or_name);
} else
- submodule = submodule_from_path(&commit_oid, path_or_name);
+ submodule = submodule_from_path(the_repository,
+ &commit_oid, path_or_name);
if (!submodule)
die_usage(argc, argv, "Submodule not found.");
@@ -64,7 +67,7 @@ int cmd_main(int argc, const char **argv)
arg += 2;
}
- submodule_free();
+ submodule_free(the_repository);
return 0;
}
diff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c
new file mode 100644
index 0000000000..a31e2a9bea
--- /dev/null
+++ b/t/helper/test-submodule-nested-repo-config.c
@@ -0,0 +1,30 @@
+#include "test-tool.h"
+#include "submodule-config.h"
+
+static void die_usage(int argc, const char **argv, const char *msg)
+{
+ fprintf(stderr, "%s\n", msg);
+ fprintf(stderr, "Usage: %s <submodulepath> <config name>\n", argv[0]);
+ exit(1);
+}
+
+int cmd__submodule_nested_repo_config(int argc, const char **argv)
+{
+ struct repository submodule;
+
+ if (argc < 3)
+ die_usage(argc, argv, "Wrong number of arguments.");
+
+ setup_git_directory();
+
+ if (repo_submodule_init(&submodule, the_repository, argv[1])) {
+ die_usage(argc, argv, "Submodule not found.");
+ }
+
+ /* Read the config of _child_ submodules. */
+ print_config_from_gitmodules(&submodule, argv[2]);
+
+ submodule_free(the_repository);
+
+ return 0;
+}
diff --git a/t/helper/test-subprocess.c b/t/helper/test-subprocess.c
index 30c5765bfc..92b69de635 100644
--- a/t/helper/test-subprocess.c
+++ b/t/helper/test-subprocess.c
@@ -1,7 +1,8 @@
+#include "test-tool.h"
#include "cache.h"
#include "run-command.h"
-int cmd_main(int argc, const char **argv)
+int cmd__subprocess(int argc, const char **argv)
{
struct child_process cp = CHILD_PROCESS_INIT;
int nogit = 0;
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
new file mode 100644
index 0000000000..bfb195b1a8
--- /dev/null
+++ b/t/helper/test-tool.c
@@ -0,0 +1,86 @@
+#include "git-compat-util.h"
+#include "test-tool.h"
+
+struct test_cmd {
+ const char *name;
+ int (*fn)(int argc, const char **argv);
+};
+
+static struct test_cmd cmds[] = {
+ { "chmtime", cmd__chmtime },
+ { "config", cmd__config },
+ { "ctype", cmd__ctype },
+ { "date", cmd__date },
+ { "delta", cmd__delta },
+ { "drop-caches", cmd__drop_caches },
+ { "dump-cache-tree", cmd__dump_cache_tree },
+ { "dump-fsmonitor", cmd__dump_fsmonitor },
+ { "dump-split-index", cmd__dump_split_index },
+ { "dump-untracked-cache", cmd__dump_untracked_cache },
+ { "example-decorate", cmd__example_decorate },
+ { "genrandom", cmd__genrandom },
+ { "hashmap", cmd__hashmap },
+ { "index-version", cmd__index_version },
+ { "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 },
+ { "online-cpus", cmd__online_cpus },
+ { "parse-options", cmd__parse_options },
+ { "path-utils", cmd__path_utils },
+ { "pkt-line", cmd__pkt_line },
+ { "prio-queue", cmd__prio_queue },
+ { "reach", cmd__reach },
+ { "read-cache", cmd__read_cache },
+ { "read-midx", cmd__read_midx },
+ { "ref-store", cmd__ref_store },
+ { "regex", cmd__regex },
+ { "repository", cmd__repository },
+ { "revision-walking", cmd__revision_walking },
+ { "run-command", cmd__run_command },
+ { "scrap-cache-tree", cmd__scrap_cache_tree },
+ { "sha1", cmd__sha1 },
+ { "sha1-array", cmd__sha1_array },
+ { "sigchain", cmd__sigchain },
+ { "strcmp-offset", cmd__strcmp_offset },
+ { "string-list", cmd__string_list },
+ { "submodule-config", cmd__submodule_config },
+ { "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
+ { "subprocess", cmd__subprocess },
+ { "urlmatch-normalization", cmd__urlmatch_normalization },
+ { "wildmatch", cmd__wildmatch },
+#ifdef GIT_WINDOWS_NATIVE
+ { "windows-named-pipe", cmd__windows_named_pipe },
+#endif
+ { "write-cache", cmd__write_cache },
+};
+
+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)
+{
+ int i;
+
+ BUG_exit_code = 99;
+ if (argc < 2)
+ die_usage();
+
+ for (i = 0; i < ARRAY_SIZE(cmds); i++) {
+ if (!strcmp(cmds[i].name, argv[1])) {
+ argv++;
+ argc--;
+ return cmds[i].fn(argc, argv);
+ }
+ }
+ error("there is no tool named '%s'", argv[1]);
+ die_usage();
+}
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
new file mode 100644
index 0000000000..042f12464b
--- /dev/null
+++ b/t/helper/test-tool.h
@@ -0,0 +1,54 @@
+#ifndef TEST_TOOL_H
+#define TEST_TOOL_H
+
+#include "git-compat-util.h"
+
+int cmd__chmtime(int argc, const char **argv);
+int cmd__config(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);
+int cmd__drop_caches(int argc, const char **argv);
+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__example_decorate(int argc, const char **argv);
+int cmd__genrandom(int argc, const char **argv);
+int cmd__hashmap(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);
+int cmd__match_trees(int argc, const char **argv);
+int cmd__mergesort(int argc, const char **argv);
+int cmd__mktemp(int argc, const char **argv);
+int cmd__online_cpus(int argc, const char **argv);
+int cmd__parse_options(int argc, const char **argv);
+int cmd__path_utils(int argc, const char **argv);
+int cmd__pkt_line(int argc, const char **argv);
+int cmd__prio_queue(int argc, const char **argv);
+int cmd__reach(int argc, const char **argv);
+int cmd__read_cache(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__regex(int argc, const char **argv);
+int cmd__repository(int argc, const char **argv);
+int cmd__revision_walking(int argc, const char **argv);
+int cmd__run_command(int argc, const char **argv);
+int cmd__scrap_cache_tree(int argc, const char **argv);
+int cmd__sha1(int argc, const char **argv);
+int cmd__sha1_array(int argc, const char **argv);
+int cmd__sigchain(int argc, const char **argv);
+int cmd__strcmp_offset(int argc, const char **argv);
+int cmd__string_list(int argc, const char **argv);
+int cmd__submodule_config(int argc, const char **argv);
+int cmd__submodule_nested_repo_config(int argc, const char **argv);
+int cmd__subprocess(int argc, const char **argv);
+int cmd__urlmatch_normalization(int argc, const char **argv);
+int cmd__wildmatch(int argc, const char **argv);
+#ifdef GIT_WINDOWS_NATIVE
+int cmd__windows_named_pipe(int argc, const char **argv);
+#endif
+int cmd__write_cache(int argc, const char **argv);
+
+#endif
diff --git a/t/helper/test-urlmatch-normalization.c b/t/helper/test-urlmatch-normalization.c
index 49b6e836be..8f4d67e646 100644
--- a/t/helper/test-urlmatch-normalization.c
+++ b/t/helper/test-urlmatch-normalization.c
@@ -1,9 +1,10 @@
+#include "test-tool.h"
#include "git-compat-util.h"
#include "urlmatch.h"
-int cmd_main(int argc, const char **argv)
+int cmd__urlmatch_normalization(int argc, const char **argv)
{
- const char usage[] = "test-urlmatch-normalization [-p | -l] <url1> | <url1> <url2>";
+ const char usage[] = "test-tool urlmatch-normalization [-p | -l] <url1> | <url1> <url2>";
char *url1, *url2;
int opt_p = 0, opt_l = 0;
diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c
index 66d33dfcfd..2c103d1824 100644
--- a/t/helper/test-wildmatch.c
+++ b/t/helper/test-wildmatch.c
@@ -1,6 +1,7 @@
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int argc, const char **argv)
+int cmd__wildmatch(int argc, const char **argv)
{
int i;
for (i = 2; i < argc; i++) {
diff --git a/t/helper/test-windows-named-pipe.c b/t/helper/test-windows-named-pipe.c
new file mode 100644
index 0000000000..b4b752b01a
--- /dev/null
+++ b/t/helper/test-windows-named-pipe.c
@@ -0,0 +1,72 @@
+#include "test-tool.h"
+#include "git-compat-util.h"
+#include "strbuf.h"
+
+#ifdef GIT_WINDOWS_NATIVE
+static const char *usage_string = "<pipe-filename>";
+
+#define TEST_BUFSIZE (4096)
+
+int cmd__windows_named_pipe(int argc, const char **argv)
+{
+ const char *filename;
+ struct strbuf pathname = STRBUF_INIT;
+ int err;
+ HANDLE h;
+ BOOL connected;
+ char buf[TEST_BUFSIZE + 1];
+
+ if (argc < 2)
+ goto print_usage;
+ filename = argv[1];
+ if (strchr(filename, '/') || strchr(filename, '\\'))
+ goto print_usage;
+ strbuf_addf(&pathname, "//./pipe/%s", filename);
+
+ /*
+ * Create a single instance of the server side of the named pipe.
+ * This will allow exactly one client instance to connect to it.
+ */
+ h = CreateNamedPipeA(
+ pathname.buf,
+ PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES,
+ TEST_BUFSIZE, TEST_BUFSIZE, 0, NULL);
+ if (h == INVALID_HANDLE_VALUE) {
+ err = err_win_to_posix(GetLastError());
+ fprintf(stderr, "CreateNamedPipe failed: %s\n",
+ strerror(err));
+ return err;
+ }
+
+ connected = ConnectNamedPipe(h, NULL)
+ ? TRUE
+ : (GetLastError() == ERROR_PIPE_CONNECTED);
+ if (!connected) {
+ err = err_win_to_posix(GetLastError());
+ fprintf(stderr, "ConnectNamedPipe failed: %s\n",
+ strerror(err));
+ CloseHandle(h);
+ return err;
+ }
+
+ while (1) {
+ DWORD nbr;
+ BOOL success = ReadFile(h, buf, TEST_BUFSIZE, &nbr, NULL);
+ if (!success || nbr == 0)
+ break;
+ buf[nbr] = 0;
+
+ write(1, buf, nbr);
+ }
+
+ DisconnectNamedPipe(h);
+ CloseHandle(h);
+ return 0;
+
+print_usage:
+ fprintf(stderr, "usage: %s %s\n", argv[0], usage_string);
+ return 1;
+}
+#endif
diff --git a/t/helper/test-write-cache.c b/t/helper/test-write-cache.c
index b7ee039669..8837717d36 100644
--- a/t/helper/test-write-cache.c
+++ b/t/helper/test-write-cache.c
@@ -1,22 +1,19 @@
+#include "test-tool.h"
#include "cache.h"
#include "lockfile.h"
-static struct lock_file index_lock;
-
-int cmd_main(int argc, const char **argv)
+int cmd__write_cache(int argc, const char **argv)
{
- int i, cnt = 1, lockfd;
+ struct lock_file index_lock = LOCK_INIT;
+ int i, cnt = 1;
if (argc == 2)
cnt = strtol(argv[1], NULL, 0);
setup_git_directory();
read_cache();
for (i = 0; i < cnt; i++) {
- lockfd = hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
- if (0 <= lockfd) {
- write_locked_index(&the_index, &index_lock, COMMIT_LOCK);
- } else {
- rollback_lock_file(&index_lock);
- }
+ hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
+ if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
+ die("unable to write index file");
}
return 0;