revert(3p/git): Revert merge of git upstream at v2.26.2

This causes cgit to serve error pages, which is undesirable.

This reverts commit 5229c9b232, reversing
changes made to f2b211131f.
This commit is contained in:
Vincent Ambo 2020-05-26 00:06:52 +01:00
parent 6f8fbf4aa4
commit 93ba78d6f4
1006 changed files with 60537 additions and 148724 deletions

View file

@ -1,4 +1,5 @@
/test-tool
/test-fake-ssh
/test-line-buffer
/test-svn-fe
*
!*.sh
!*.[ch]
!*.gitignore

View file

@ -37,6 +37,21 @@
*
*/
static const char *scope_name(enum config_scope scope)
{
switch (scope) {
case CONFIG_SCOPE_SYSTEM:
return "system";
case CONFIG_SCOPE_GLOBAL:
return "global";
case CONFIG_SCOPE_REPO:
return "repo";
case CONFIG_SCOPE_CMDLINE:
return "cmdline";
default:
return "unknown";
}
}
static int iterate_cb(const char *var, const char *value, void *data)
{
static int nr;
@ -48,8 +63,7 @@ static int iterate_cb(const char *var, const char *value, void *data)
printf("value=%s\n", value ? value : "(null)");
printf("origin=%s\n", current_config_origin_type());
printf("name=%s\n", current_config_name());
printf("lno=%d\n", current_config_line());
printf("scope=%s\n", config_scope_name(current_config_scope()));
printf("scope=%s\n", scope_name(current_config_scope()));
return 0;
}

View file

@ -12,13 +12,13 @@ static const char *usage_msg = "\n"
" test-tool date is64bit\n"
" test-tool date time_t-is64bit\n";
static void show_relative_dates(const char **argv)
static void show_relative_dates(const char **argv, struct timeval *now)
{
struct strbuf buf = STRBUF_INIT;
for (; *argv; argv++) {
time_t t = atoi(*argv);
show_date_relative(t, &buf);
show_date_relative(t, now, &buf);
printf("%s -> %s\n", *argv, buf.buf);
}
strbuf_release(&buf);
@ -74,20 +74,20 @@ static void parse_dates(const char **argv)
strbuf_release(&result);
}
static void parse_approxidate(const char **argv)
static void parse_approxidate(const char **argv, struct timeval *now)
{
for (; *argv; argv++) {
timestamp_t t;
t = approxidate_relative(*argv);
t = approxidate_relative(*argv, now);
printf("%s -> %s\n", *argv, show_date(t, 0, DATE_MODE(ISO8601)));
}
}
static void parse_approx_timestamp(const char **argv)
static void parse_approx_timestamp(const char **argv, struct timeval *now)
{
for (; *argv; argv++) {
timestamp_t t;
t = approxidate_relative(*argv);
t = approxidate_relative(*argv, now);
printf("%s -> %"PRItime"\n", *argv, t);
}
}
@ -103,13 +103,22 @@ static void getnanos(const char **argv)
int cmd__date(int argc, const char **argv)
{
struct timeval now;
const char *x;
x = getenv("GIT_TEST_DATE_NOW");
if (x) {
now.tv_sec = atoi(x);
now.tv_usec = 0;
}
else
gettimeofday(&now, NULL);
argv++;
if (!*argv)
usage(usage_msg);
if (!strcmp(*argv, "relative"))
show_relative_dates(argv+1);
show_relative_dates(argv+1, &now);
else if (!strcmp(*argv, "human"))
show_human_dates(argv+1);
else if (skip_prefix(*argv, "show:", &x))
@ -117,9 +126,9 @@ int cmd__date(int argc, const char **argv)
else if (!strcmp(*argv, "parse"))
parse_dates(argv+1);
else if (!strcmp(*argv, "approxidate"))
parse_approxidate(argv+1);
parse_approxidate(argv+1, &now);
else if (!strcmp(*argv, "timestamp"))
parse_approx_timestamp(argv+1);
parse_approx_timestamp(argv+1, &now);
else if (!strcmp(*argv, "getnanos"))
getnanos(argv+1);
else if (!strcmp(*argv, "is64bit"))

View file

@ -8,21 +8,18 @@ static int cmd_sync(void)
{
char Buffer[MAX_PATH];
DWORD dwRet;
char szVolumeAccessPath[] = "\\\\.\\XXXX:";
char szVolumeAccessPath[] = "\\\\.\\X:";
HANDLE hVolWrite;
int success = 0, dos_drive_prefix;
int success = 0;
dwRet = GetCurrentDirectory(MAX_PATH, Buffer);
if ((0 == dwRet) || (dwRet > MAX_PATH))
return error("Error getting current directory");
dos_drive_prefix = has_dos_drive_prefix(Buffer);
if (!dos_drive_prefix)
if (!has_dos_drive_prefix(Buffer))
return error("'%s': invalid drive letter", Buffer);
memcpy(szVolumeAccessPath, Buffer, dos_drive_prefix);
szVolumeAccessPath[dos_drive_prefix] = '\0';
szVolumeAccessPath[4] = Buffer[0];
hVolWrite = CreateFile(szVolumeAccessPath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == hVolWrite)

View file

@ -13,7 +13,7 @@ int cmd__dump_fsmonitor(int ac, const char **av)
printf("no fsmonitor\n");
return 0;
}
printf("fsmonitor last update %s\n", istate->fsmonitor_last_update);
printf("fsmonitor last update %"PRIuMAX"\n", (uintmax_t)istate->fsmonitor_last_update);
for (i = 0; i < istate->cache_nr; i++)
printf((istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) ? "+" : "-");

View file

@ -5,7 +5,6 @@
struct test_entry
{
int padding; /* hashmap entry no longer needs to be the first member */
struct hashmap_entry ent;
/* key and value as two \0-terminated strings */
char key[FLEX_ARRAY];
@ -17,17 +16,15 @@ static const char *get_value(const struct test_entry *e)
}
static int test_entry_cmp(const void *cmp_data,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *entry,
const void *entry_or_key,
const void *keydata)
{
const int ignore_case = cmp_data ? *((int *)cmp_data) : 0;
const struct test_entry *e1, *e2;
const struct test_entry *e1 = entry;
const struct test_entry *e2 = entry_or_key;
const char *key = keydata;
e1 = container_of(eptr, const struct test_entry, ent);
e2 = container_of(entry_or_key, const struct test_entry, ent);
if (ignore_case)
return strcasecmp(e1->key, key ? key : e2->key);
else
@ -40,7 +37,7 @@ static struct test_entry *alloc_test_entry(unsigned int hash,
size_t klen = strlen(key);
size_t vlen = strlen(value);
struct test_entry *entry = xmalloc(st_add4(sizeof(*entry), klen, vlen, 2));
hashmap_entry_init(&entry->ent, hash);
hashmap_entry_init(entry, hash);
memcpy(entry->key, key, klen + 1);
memcpy(entry->key + klen + 1, value, vlen + 1);
return entry;
@ -106,11 +103,11 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
/* add entries */
for (i = 0; i < TEST_SIZE; i++) {
hashmap_entry_init(&entries[i]->ent, hashes[i]);
hashmap_add(&map, &entries[i]->ent);
hashmap_entry_init(entries[i], hashes[i]);
hashmap_add(&map, entries[i]);
}
hashmap_free(&map);
hashmap_free(&map, 0);
}
} else {
/* test map lookups */
@ -119,8 +116,8 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
/* fill the map (sparsely if specified) */
j = (method & TEST_SPARSE) ? TEST_SIZE / 10 : TEST_SIZE;
for (i = 0; i < j; i++) {
hashmap_entry_init(&entries[i]->ent, hashes[i]);
hashmap_add(&map, &entries[i]->ent);
hashmap_entry_init(entries[i], hashes[i]);
hashmap_add(&map, entries[i]);
}
for (j = 0; j < rounds; j++) {
@ -130,7 +127,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
}
}
hashmap_free(&map);
hashmap_free(&map, 0);
}
}
@ -182,7 +179,7 @@ int cmd__hashmap(int argc, const char **argv)
entry = alloc_test_entry(hash, p1, p2);
/* add to hashmap */
hashmap_add(&map, &entry->ent);
hashmap_add(&map, entry);
} else if (!strcmp("put", cmd) && p1 && p2) {
@ -190,44 +187,43 @@ int cmd__hashmap(int argc, const char **argv)
entry = alloc_test_entry(hash, p1, p2);
/* add / replace entry */
entry = hashmap_put_entry(&map, entry, ent);
entry = hashmap_put(&map, entry);
/* print and free replaced entry, if any */
puts(entry ? get_value(entry) : "NULL");
free(entry);
} else if (!strcmp("get", cmd) && p1) {
/* lookup entry in hashmap */
entry = hashmap_get_entry_from_hash(&map, hash, p1,
struct test_entry, ent);
entry = hashmap_get_from_hash(&map, hash, p1);
/* print result */
if (!entry)
puts("NULL");
hashmap_for_each_entry_from(&map, entry, ent)
while (entry) {
puts(get_value(entry));
entry = hashmap_get_next(&map, entry);
}
} else if (!strcmp("remove", cmd) && p1) {
/* setup static key */
struct hashmap_entry key;
struct hashmap_entry *rm;
hashmap_entry_init(&key, hash);
/* remove entry from hashmap */
rm = hashmap_remove(&map, &key, p1);
entry = rm ? container_of(rm, struct test_entry, ent)
: NULL;
entry = hashmap_remove(&map, &key, p1);
/* print result and free entry*/
puts(entry ? get_value(entry) : "NULL");
free(entry);
} else if (!strcmp("iterate", cmd)) {
struct hashmap_iter iter;
hashmap_for_each_entry(&map, &iter, entry,
ent /* member name */)
struct hashmap_iter iter;
hashmap_iter_init(&map, &iter);
while ((entry = hashmap_iter_next(&iter)))
printf("%s %s\n", entry->key, get_value(entry));
} else if (!strcmp("size", cmd)) {
@ -262,6 +258,6 @@ int cmd__hashmap(int argc, const char **argv)
}
strbuf_release(&line);
hashmap_free_entries(&map, struct test_entry, ent);
hashmap_free(&map, 1);
return 0;
}

View file

@ -41,13 +41,17 @@ static void dump_run(void)
die("non-threaded code path used");
}
hashmap_for_each_entry(&the_index.dir_hash, &iter_dir, dir,
ent /* member name */)
dir = hashmap_iter_first(&the_index.dir_hash, &iter_dir);
while (dir) {
printf("dir %08x %7d %s\n", dir->ent.hash, dir->nr, dir->name);
dir = hashmap_iter_next(&iter_dir);
}
hashmap_for_each_entry(&the_index.name_hash, &iter_cache, ce,
ent /* member name */)
ce = hashmap_iter_first(&the_index.name_hash, &iter_cache);
while (ce) {
printf("name %08x %s\n", ce->ent.hash, ce->name);
ce = hashmap_iter_next(&iter_cache);
}
discard_cache();
}

View file

@ -121,8 +121,6 @@ int cmd__parse_options(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_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1),
OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2),
OPT_CALLBACK('L', "length", &integer, "str",
"get length of <str>", length_callback),
OPT_FILENAME('F', "file", &file, "set file to <file>"),

View file

@ -1,33 +0,0 @@
#include "test-tool.h"
#include "parse-options.h"
#include "pathspec.h"
#include "gettext.h"
int cmd__parse_pathspec_file(int argc, const char **argv)
{
struct pathspec pathspec;
const char *pathspec_from_file = 0;
int pathspec_file_nul = 0, i;
static const char *const usage[] = {
"test-tool parse-pathspec-file --pathspec-from-file [--pathspec-file-nul]",
NULL
};
struct option options[] = {
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
OPT_END()
};
parse_options(argc, argv, 0, options, usage, 0);
parse_pathspec_file(&pathspec, 0, 0, 0, pathspec_from_file,
pathspec_file_nul);
for (i = 0; i < pathspec.nr; i++)
printf("%s\n", pathspec.items[i].original);
clear_pathspec(&pathspec);
return 0;
}

View file

@ -185,99 +185,6 @@ static int cmp_by_st_size(const void *a, const void *b)
return x > y ? -1 : (x < y ? +1 : 0);
}
/*
* A very simple, reproducible pseudo-random generator. Copied from
* `test-genrandom.c`.
*/
static uint64_t my_random_value = 1234;
static uint64_t my_random(void)
{
my_random_value = my_random_value * 1103515245 + 12345;
return my_random_value;
}
/*
* A fast approximation of the square root, without requiring math.h.
*
* It uses Newton's method to approximate the solution of 0 = x^2 - value.
*/
static double my_sqrt(double value)
{
const double epsilon = 1e-6;
double x = value;
if (value == 0)
return 0;
for (;;) {
double delta = (value / x - x) / 2;
if (delta < epsilon && delta > -epsilon)
return x + delta;
x += delta;
}
}
static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
{
size_t i, j, nr, min_len = 3, max_len = 20;
char **names;
int repetitions = 15, file_mode = 0100644;
uint64_t begin, end;
double m[3][2], v[3][2];
uint64_t cumul;
double cumul2;
if (argc > 1 && !strcmp(argv[1], "--with-symlink-mode")) {
file_mode = 0120000;
argc--;
argv++;
}
nr = argc > 1 ? strtoul(argv[1], NULL, 0) : 1000000;
ALLOC_ARRAY(names, nr);
if (argc > 2) {
min_len = strtoul(argv[2], NULL, 0);
if (argc > 3)
max_len = strtoul(argv[3], NULL, 0);
if (min_len > max_len)
die("min_len > max_len");
}
for (i = 0; i < nr; i++) {
size_t len = min_len + (my_random() % (max_len + 1 - min_len));
names[i] = xmallocz(len);
while (len > 0)
names[i][--len] = (char)(' ' + (my_random() % ('\x7f' - ' ')));
}
for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++)
for (protect_hfs = 0; protect_hfs < 2; protect_hfs++) {
cumul = 0;
cumul2 = 0;
for (i = 0; i < repetitions; i++) {
begin = getnanotime();
for (j = 0; j < nr; j++)
verify_path(names[j], file_mode);
end = getnanotime();
printf("protect_ntfs = %d, protect_hfs = %d: %lfms\n", protect_ntfs, protect_hfs, (end-begin) / (double)1e6);
cumul += end - begin;
cumul2 += (end - begin) * (end - begin);
}
m[protect_ntfs][protect_hfs] = cumul / (double)repetitions;
v[protect_ntfs][protect_hfs] = my_sqrt(cumul2 / (double)repetitions - m[protect_ntfs][protect_hfs] * m[protect_ntfs][protect_hfs]);
printf("mean: %lfms, stddev: %lfms\n", m[protect_ntfs][protect_hfs] / (double)1e6, v[protect_ntfs][protect_hfs] / (double)1e6);
}
for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++)
for (protect_hfs = 0; protect_hfs < 2; protect_hfs++)
printf("ntfs=%d/hfs=%d: %lf%% slower\n", protect_ntfs, protect_hfs, (m[protect_ntfs][protect_hfs] - m[0][0]) * 100 / m[0][0]);
return 0;
}
int cmd__path_utils(int argc, const char **argv)
{
if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) {
@ -448,26 +355,6 @@ int cmd__path_utils(int argc, const char **argv)
return !!res;
}
if (argc > 1 && !strcmp(argv[1], "protect_ntfs_hfs"))
return !!protect_ntfs_hfs_benchmark(argc - 1, argv + 1);
if (argc > 1 && !strcmp(argv[1], "is_valid_path")) {
int res = 0, expect = 1, i;
for (i = 2; i < argc; i++)
if (!strcmp("--not", argv[i]))
expect = 0;
else if (expect != is_valid_path(argv[i]))
res = error("'%s' is%s a valid path",
argv[i], expect ? " not" : "");
else
fprintf(stderr,
"'%s' is%s a valid path\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;

View file

@ -1,81 +0,0 @@
/*
* A test helper to exercise the progress display.
*
* Reads instructions from standard input, one instruction per line:
*
* "progress <items>" - Call display_progress() with the given item count
* as parameter.
* "throughput <bytes> <millis> - Call display_throughput() with the given
* byte count as parameter. The 'millis'
* specify the time elapsed since the
* start_progress() call.
* "update" - Set the 'progress_update' flag.
*
* See 't0500-progress-display.sh' for examples.
*/
#include "test-tool.h"
#include "gettext.h"
#include "parse-options.h"
#include "progress.h"
#include "strbuf.h"
/*
* These are defined in 'progress.c', but are not exposed in 'progress.h',
* because they are exclusively for testing.
*/
extern int progress_testing;
extern uint64_t progress_test_ns;
void progress_test_force_update(void);
int cmd__progress(int argc, const char **argv)
{
int total = 0;
const char *title;
struct strbuf line = STRBUF_INIT;
struct progress *progress;
const char *usage[] = {
"test-tool progress [--total=<n>] <progress-title>",
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];
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)) {
uint64_t item_count = strtoull(end, &end, 10);
if (*end != '\0')
die("invalid input: '%s'\n", line.buf);
display_progress(progress, item_count);
} else if (skip_prefix(line.buf, "throughput ",
(const char **) &end)) {
uint64_t byte_count, test_ms;
byte_count = strtoull(end, &end, 10);
if (*end != ' ')
die("invalid input: '%s'\n", line.buf);
test_ms = strtoull(end + 1, &end, 10);
if (*end != '\0')
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"))
progress_test_force_update();
else
die("invalid input: '%s'\n", line.buf);
}
stop_progress(&progress);
return 0;
}

View file

@ -4,10 +4,11 @@
int cmd__read_cache(int argc, const char **argv)
{
int i, cnt = 1;
int i, cnt = 1, namelen;
const char *name = NULL;
if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) {
namelen = strlen(name);
argc--;
argv++;
}
@ -23,7 +24,7 @@ int cmd__read_cache(int argc, const char **argv)
refresh_index(&the_index, REFRESH_QUIET,
NULL, NULL, NULL);
pos = index_name_pos(&the_index, name, strlen(name));
pos = index_name_pos(&the_index, name, namelen);
if (pos < 0)
die("%s not in index", name);
printf("%s is%s up to date\n", name,

View file

@ -1,53 +0,0 @@
#include "test-tool.h"
#include "cache.h"
#include "commit-graph.h"
#include "repository.h"
#include "object-store.h"
int cmd__read_graph(int argc, const char **argv)
{
struct commit_graph *graph = NULL;
char *graph_name;
int open_ok;
int fd;
struct stat st;
struct object_directory *odb;
setup_git_directory();
odb = the_repository->objects->odb;
graph_name = get_commit_graph_filename(odb);
open_ok = open_commit_graph(graph_name, &fd, &st);
if (!open_ok)
die_errno(_("Could not open commit-graph '%s'"), graph_name);
graph = load_commit_graph_one_fd_st(fd, &st, odb);
if (!graph)
return 1;
FREE_AND_NULL(graph_name);
printf("header: %08x %d %d %d %d\n",
ntohl(*(uint32_t*)graph->data),
*(unsigned char*)(graph->data + 4),
*(unsigned char*)(graph->data + 5),
*(unsigned char*)(graph->data + 6),
*(unsigned char*)(graph->data + 7));
printf("num_commits: %u\n", graph->num_commits);
printf("chunks:");
if (graph->chunk_oid_fanout)
printf(" oid_fanout");
if (graph->chunk_oid_lookup)
printf(" oid_lookup");
if (graph->chunk_commit_data)
printf(" commit_metadata");
if (graph->chunk_extra_edges)
printf(" extra_edges");
printf("\n");
UNLEAK(graph);
return 0;
}

View file

@ -10,16 +10,11 @@
#include "test-tool.h"
#include "git-compat-util.h"
#include "cache.h"
#include "run-command.h"
#include "argv-array.h"
#include "strbuf.h"
#include "parse-options.h"
#include "string-list.h"
#include "thread-utils.h"
#include "wildmatch.h"
#include "gettext.h"
#include "parse-options.h"
#include <string.h>
#include <errno.h>
static int number_callbacks;
static int parallel_next(struct child_process *cp,
@ -55,337 +50,11 @@ static int task_finished(int result,
return 1;
}
struct testsuite {
struct string_list tests, failed;
int next;
int quiet, immediate, verbose, verbose_log, trace, write_junit_xml;
};
#define TESTSUITE_INIT \
{ STRING_LIST_INIT_DUP, STRING_LIST_INIT_DUP, -1, 0, 0, 0, 0, 0, 0 }
static int next_test(struct child_process *cp, struct strbuf *err, void *cb,
void **task_cb)
{
struct testsuite *suite = cb;
const char *test;
if (suite->next >= suite->tests.nr)
return 0;
test = suite->tests.items[suite->next++].string;
argv_array_pushl(&cp->args, "sh", test, NULL);
if (suite->quiet)
argv_array_push(&cp->args, "--quiet");
if (suite->immediate)
argv_array_push(&cp->args, "-i");
if (suite->verbose)
argv_array_push(&cp->args, "-v");
if (suite->verbose_log)
argv_array_push(&cp->args, "-V");
if (suite->trace)
argv_array_push(&cp->args, "-x");
if (suite->write_junit_xml)
argv_array_push(&cp->args, "--write-junit-xml");
strbuf_addf(err, "Output of '%s':\n", test);
*task_cb = (void *)test;
return 1;
}
static int test_finished(int result, struct strbuf *err, void *cb,
void *task_cb)
{
struct testsuite *suite = cb;
const char *name = (const char *)task_cb;
if (result)
string_list_append(&suite->failed, name);
strbuf_addf(err, "%s: '%s'\n", result ? "FAIL" : "SUCCESS", name);
return 0;
}
static int test_failed(struct strbuf *out, void *cb, void *task_cb)
{
struct testsuite *suite = cb;
const char *name = (const char *)task_cb;
string_list_append(&suite->failed, name);
strbuf_addf(out, "FAILED TO START: '%s'\n", name);
return 0;
}
static const char * const testsuite_usage[] = {
"test-run-command testsuite [<options>] [<pattern>...]",
NULL
};
static int testsuite(int argc, const char **argv)
{
struct testsuite suite = TESTSUITE_INIT;
int max_jobs = 1, i, ret;
DIR *dir;
struct dirent *d;
struct option options[] = {
OPT_BOOL('i', "immediate", &suite.immediate,
"stop at first failed test case(s)"),
OPT_INTEGER('j', "jobs", &max_jobs, "run <N> jobs in parallel"),
OPT_BOOL('q', "quiet", &suite.quiet, "be terse"),
OPT_BOOL('v', "verbose", &suite.verbose, "be verbose"),
OPT_BOOL('V', "verbose-log", &suite.verbose_log,
"be verbose, redirected to a file"),
OPT_BOOL('x', "trace", &suite.trace, "trace shell commands"),
OPT_BOOL(0, "write-junit-xml", &suite.write_junit_xml,
"write JUnit-style XML files"),
OPT_END()
};
memset(&suite, 0, sizeof(suite));
suite.tests.strdup_strings = suite.failed.strdup_strings = 1;
argc = parse_options(argc, argv, NULL, options,
testsuite_usage, PARSE_OPT_STOP_AT_NON_OPTION);
if (max_jobs <= 0)
max_jobs = online_cpus();
dir = opendir(".");
if (!dir)
die("Could not open the current directory");
while ((d = readdir(dir))) {
const char *p = d->d_name;
if (*p != 't' || !isdigit(p[1]) || !isdigit(p[2]) ||
!isdigit(p[3]) || !isdigit(p[4]) || p[5] != '-' ||
!ends_with(p, ".sh"))
continue;
/* No pattern: match all */
if (!argc) {
string_list_append(&suite.tests, p);
continue;
}
for (i = 0; i < argc; i++)
if (!wildmatch(argv[i], p, 0)) {
string_list_append(&suite.tests, p);
break;
}
}
closedir(dir);
if (!suite.tests.nr)
die("No tests match!");
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);
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);
for (i = 0; i < suite.failed.nr; i++)
fprintf(stderr, "\t%s\n", suite.failed.items[i].string);
}
string_list_clear(&suite.tests, 0);
string_list_clear(&suite.failed, 0);
return !!ret;
}
static uint64_t my_random_next = 1234;
static uint64_t my_random(void)
{
uint64_t res = my_random_next;
my_random_next = my_random_next * 1103515245 + 12345;
return res;
}
static int quote_stress_test(int argc, const char **argv)
{
/*
* We are running a quote-stress test.
* spawn a subprocess that runs quote-stress with a
* special option that echoes back the arguments that
* were passed in.
*/
char special[] = ".?*\\^_\"'`{}()[]<>@~&+:;$%"; // \t\r\n\a";
int i, j, k, trials = 100, skip = 0, msys2 = 0;
struct strbuf out = STRBUF_INIT;
struct argv_array args = ARGV_ARRAY_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_END()
};
const char * const usage[] = {
"test-tool run-command quote-stress-test <options>",
NULL
};
argc = parse_options(argc, argv, NULL, options, usage, 0);
setenv("MSYS_NO_PATHCONV", "1", 0);
for (i = 0; i < trials; i++) {
struct child_process cp = CHILD_PROCESS_INIT;
size_t arg_count, arg_offset;
int ret = 0;
argv_array_clear(&args);
if (msys2)
argv_array_pushl(&args, "sh", "-c",
"printf %s\\\\0 \"$@\"", "skip", NULL);
else
argv_array_pushl(&args, "test-tool", "run-command",
"quote-echo", NULL);
arg_offset = args.argc;
if (argc > 0) {
trials = 1;
arg_count = argc;
for (j = 0; j < arg_count; j++)
argv_array_push(&args, argv[j]);
} else {
arg_count = 1 + (my_random() % 5);
for (j = 0; j < arg_count; j++) {
char buf[20];
size_t min_len = 1;
size_t arg_len = min_len +
(my_random() % (ARRAY_SIZE(buf) - min_len));
for (k = 0; k < arg_len; k++)
buf[k] = special[my_random() %
ARRAY_SIZE(special)];
buf[arg_len] = '\0';
argv_array_push(&args, buf);
}
}
if (i < skip)
continue;
cp.argv = args.argv;
strbuf_reset(&out);
if (pipe_command(&cp, NULL, 0, &out, 0, NULL, 0) < 0)
return error("Failed to spawn child process");
for (j = 0, k = 0; j < arg_count; j++) {
const char *arg = args.argv[j + arg_offset];
if (strcmp(arg, out.buf + k))
ret = error("incorrectly quoted arg: '%s', "
"echoed back as '%s'",
arg, out.buf + k);
k += strlen(out.buf + k) + 1;
}
if (k != out.len)
ret = error("got %d bytes, but consumed only %d",
(int)out.len, (int)k);
if (ret) {
fprintf(stderr, "Trial #%d failed. Arguments:\n", i);
for (j = 0; j < arg_count; j++)
fprintf(stderr, "arg #%d: '%s'\n",
(int)j, args.argv[j + arg_offset]);
strbuf_release(&out);
argv_array_clear(&args);
return ret;
}
if (i && (i % 100) == 0)
fprintf(stderr, "Trials completed: %d\n", (int)i);
}
strbuf_release(&out);
argv_array_clear(&args);
return 0;
}
static int quote_echo(int argc, const char **argv)
{
while (argc > 1) {
fwrite(argv[1], strlen(argv[1]), 1, stdout);
fputc('\0', stdout);
argv++;
argc--;
}
return 0;
}
static int inherit_handle(const char *argv0)
{
struct child_process cp = CHILD_PROCESS_INIT;
char path[PATH_MAX];
int tmp;
/* First, open an inheritable handle */
xsnprintf(path, sizeof(path), "out-XXXXXX");
tmp = xmkstemp(path);
argv_array_pushl(&cp.args,
"test-tool", argv0, "inherited-handle-child", NULL);
cp.in = -1;
cp.no_stdout = cp.no_stderr = 1;
if (start_command(&cp) < 0)
die("Could not start child process");
/* Then close it, and try to delete it. */
close(tmp);
if (unlink(path))
die("Could not delete '%s'", path);
if (close(cp.in) < 0 || finish_command(&cp) < 0)
die("Child did not finish");
return 0;
}
static int inherit_handle_child(void)
{
struct strbuf buf = STRBUF_INIT;
if (strbuf_read(&buf, 0, 0) < 0)
die("Could not read stdin");
printf("Received %s\n", buf.buf);
strbuf_release(&buf);
return 0;
}
int cmd__run_command(int argc, const char **argv)
{
struct child_process proc = CHILD_PROCESS_INIT;
int jobs;
if (argc > 1 && !strcmp(argv[1], "testsuite"))
exit(testsuite(argc - 1, argv + 1));
if (!strcmp(argv[1], "inherited-handle"))
exit(inherit_handle(argv[0]));
if (!strcmp(argv[1], "inherited-handle-child"))
exit(inherit_handle_child());
if (argc >= 2 && !strcmp(argv[1], "quote-stress-test"))
return !!quote_stress_test(argc - 1, argv + 1);
if (argc >= 2 && !strcmp(argv[1], "quote-echo"))
return !!quote_echo(argc - 1, argv + 1);
if (argc < 3)
return 1;
while (!strcmp(argv[1], "env")) {

View file

@ -39,14 +39,11 @@ static struct test_cmd cmds[] = {
{ "oidmap", cmd__oidmap },
{ "online-cpus", cmd__online_cpus },
{ "parse-options", cmd__parse_options },
{ "parse-pathspec-file", cmd__parse_pathspec_file },
{ "path-utils", cmd__path_utils },
{ "pkt-line", cmd__pkt_line },
{ "prio-queue", cmd__prio_queue },
{ "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 },
{ "regex", cmd__regex },

View file

@ -29,14 +29,11 @@ int cmd__mktemp(int argc, const char **argv);
int cmd__oidmap(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__parse_pathspec_file(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__progress(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_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__regex(int argc, const char **argv);

View file

@ -19,7 +19,7 @@ int cmd__windows_named_pipe(int argc, const char **argv)
if (argc < 2)
goto print_usage;
filename = argv[1];
if (strpbrk(filename, "/\\"))
if (strchr(filename, '/') || strchr(filename, '\\'))
goto print_usage;
strbuf_addf(&pathname, "//./pipe/%s", filename);