1 From abf2e09ee55a3ac3f227ea343fc9065b5d4e7288 Mon Sep 17 00:00:00 2001
2 From: Garima Singh <garima.singh@microsoft.com>
3 Date: Wed, 18 Sep 2019 16:03:59 -0400
4 Subject: tests: add a helper to stress test argument quoting
6 On Windows, we have to do all the command-line argument quoting
7 ourselves. Worse: we have to have two versions of said quoting, one for
8 MSYS2 programs (which have their own dequoting rules) and the rest.
10 We care mostly about the rest, and to make sure that that works, let's
11 have a stress test that comes up with all kinds of awkward arguments,
12 verifying that a spawned sub-process receives those unharmed.
14 Signed-off-by: Garima Singh <garima.singh@microsoft.com>
15 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
16 (cherry picked from commit ad1559252945179e28fba7d693494051352810c5)
17 Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
19 t/helper/test-run-command.c | 118 +++++++++++++++++++++++++++++++++++-
20 1 file changed, 116 insertions(+), 2 deletions(-)
22 diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
23 index ead6dc611a..8aad4fbd42 100644
24 --- a/t/helper/test-run-command.c
25 +++ b/t/helper/test-run-command.c
27 #include "string-list.h"
28 #include "thread-utils.h"
29 #include "wildmatch.h"
33 +#include "parse-options.h"
35 static int number_callbacks;
36 static int parallel_next(struct child_process *cp,
37 @@ -200,6 +200,114 @@ static int testsuite(int argc, const char **argv)
41 +static uint64_t my_random_next = 1234;
43 +static uint64_t my_random(void)
45 + uint64_t res = my_random_next;
46 + my_random_next = my_random_next * 1103515245 + 12345;
50 +static int quote_stress_test(int argc, const char **argv)
53 + * We are running a quote-stress test.
54 + * spawn a subprocess that runs quote-stress with a
55 + * special option that echoes back the arguments that
58 + char special[] = ".?*\\^_\"'`{}()[]<>@~&+:;$%"; // \t\r\n\a";
59 + int i, j, k, trials = 100;
60 + struct strbuf out = STRBUF_INIT;
61 + struct argv_array args = ARGV_ARRAY_INIT;
62 + struct option options[] = {
63 + OPT_INTEGER('n', "trials", &trials, "Number of trials"),
66 + const char * const usage[] = {
67 + "test-tool run-command quote-stress-test <options>",
71 + argc = parse_options(argc, argv, NULL, options, usage, 0);
73 + for (i = 0; i < trials; i++) {
74 + struct child_process cp = CHILD_PROCESS_INIT;
75 + size_t arg_count = 1 + (my_random() % 5), arg_offset;
78 + argv_array_clear(&args);
79 + argv_array_pushl(&args, "test-tool", "run-command",
80 + "quote-echo", NULL);
81 + arg_offset = args.argc;
82 + for (j = 0; j < arg_count; j++) {
85 + size_t arg_len = min_len +
86 + (my_random() % (ARRAY_SIZE(buf) - min_len));
88 + for (k = 0; k < arg_len; k++)
89 + buf[k] = special[my_random() %
90 + ARRAY_SIZE(special)];
91 + buf[arg_len] = '\0';
93 + argv_array_push(&args, buf);
96 + cp.argv = args.argv;
98 + if (pipe_command(&cp, NULL, 0, &out, 0, NULL, 0) < 0)
99 + return error("Failed to spawn child process");
101 + for (j = 0, k = 0; j < arg_count; j++) {
102 + const char *arg = args.argv[j + arg_offset];
104 + if (strcmp(arg, out.buf + k))
105 + ret = error("incorrectly quoted arg: '%s', "
106 + "echoed back as '%s'",
108 + k += strlen(out.buf + k) + 1;
112 + ret = error("got %d bytes, but consumed only %d",
113 + (int)out.len, (int)k);
116 + fprintf(stderr, "Trial #%d failed. Arguments:\n", i);
117 + for (j = 0; j < arg_count; j++)
118 + fprintf(stderr, "arg #%d: '%s'\n",
119 + (int)j, args.argv[j + arg_offset]);
121 + strbuf_release(&out);
122 + argv_array_clear(&args);
127 + if (i && (i % 100) == 0)
128 + fprintf(stderr, "Trials completed: %d\n", (int)i);
131 + strbuf_release(&out);
132 + argv_array_clear(&args);
137 +static int quote_echo(int argc, const char **argv)
140 + fwrite(argv[1], strlen(argv[1]), 1, stdout);
141 + fputc('\0', stdout);
149 int cmd__run_command(int argc, const char **argv)
151 struct child_process proc = CHILD_PROCESS_INIT;
152 @@ -208,6 +316,12 @@ int cmd__run_command(int argc, const char **argv)
153 if (argc > 1 && !strcmp(argv[1], "testsuite"))
154 exit(testsuite(argc - 1, argv + 1));
156 + if (argc >= 2 && !strcmp(argv[1], "quote-stress-test"))
157 + return !!quote_stress_test(argc - 1, argv + 1);
159 + if (argc >= 2 && !strcmp(argv[1], "quote-echo"))
160 + return !!quote_echo(argc - 1, argv + 1);
164 while (!strcmp(argv[1], "env")) {
166 2.24.0.393.g34dc348eaf