diff mbox series

[v3,23/34] t/helper/test-touch: add helper to touch a series of files

Message ID 3cf8f3cd7717dad69262ae884a89c1a6ca0ce5fc.1625150864.git.gitgitgadget@gmail.com (mailing list archive)
State New, archived
Headers show
Series Builtin FSMonitor Feature | expand

Commit Message

Jeff Hostetler July 1, 2021, 2:47 p.m. UTC
From: Jeff Hostetler <jeffhost@microsoft.com>

Create `test-tool touch` that can update a series of files
using either a pattern given on the command line or a list
of files read from stdin.

This will be used in a later commit to speed up p7519
which needs to generate/update many thousands of files.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
---
 Makefile              |   1 +
 t/helper/test-tool.c  |   1 +
 t/helper/test-tool.h  |   1 +
 t/helper/test-touch.c | 126 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 129 insertions(+)
 create mode 100644 t/helper/test-touch.c

Comments

Junio C Hamano July 1, 2021, 8 p.m. UTC | #1
"Jeff Hostetler via GitGitGadget" <gitgitgadget@gmail.com> writes:

> diff --git a/t/helper/test-touch.c b/t/helper/test-touch.c
> new file mode 100644
> index 00000000000..e9b3b754f1f
> --- /dev/null
> +++ b/t/helper/test-touch.c
> @@ -0,0 +1,126 @@
> +/*
> + * test-touch.c: variation on /usr/bin/touch to speed up tests
> + * with a large number of files (primarily on Windows where child
> + * process are very, very expensive).
> + */
> +
> +#include "test-tool.h"
> +#include "cache.h"
> +#include "parse-options.h"
> +
> +char *seq_pattern;
> +int seq_start = 1;
> +int seq_count = 1;

With this in, "make sparse" dies like this:

    SP t/helper/test-touch.c
t/helper/test-touch.c:11:6: error: symbol 'seq_pattern' was not declared. Should it be static?
t/helper/test-touch.c:12:5: error: symbol 'seq_start' was not declared. Should it be static?
t/helper/test-touch.c:13:5: error: symbol 'seq_count' was not declared. Should it be static?
Jeff Hostetler July 13, 2021, 4:45 p.m. UTC | #2
On 7/1/21 4:00 PM, Junio C Hamano wrote:
> "Jeff Hostetler via GitGitGadget" <gitgitgadget@gmail.com> writes:
> 
>> diff --git a/t/helper/test-touch.c b/t/helper/test-touch.c
>> new file mode 100644
>> index 00000000000..e9b3b754f1f
>> --- /dev/null
>> +++ b/t/helper/test-touch.c
>> @@ -0,0 +1,126 @@
>> +/*
>> + * test-touch.c: variation on /usr/bin/touch to speed up tests
>> + * with a large number of files (primarily on Windows where child
>> + * process are very, very expensive).
>> + */
>> +
>> +#include "test-tool.h"
>> +#include "cache.h"
>> +#include "parse-options.h"
>> +
>> +char *seq_pattern;
>> +int seq_start = 1;
>> +int seq_count = 1;
> 
> With this in, "make sparse" dies like this:
> 
>      SP t/helper/test-touch.c
> t/helper/test-touch.c:11:6: error: symbol 'seq_pattern' was not declared. Should it be static?
> t/helper/test-touch.c:12:5: error: symbol 'seq_start' was not declared. Should it be static?
> t/helper/test-touch.c:13:5: error: symbol 'seq_count' was not declared. Should it be static?
> 

I'll fix.  Thanks!
Jeff
diff mbox series

Patch

diff --git a/Makefile b/Makefile
index a2a6e1f20f6..c07cfb75532 100644
--- a/Makefile
+++ b/Makefile
@@ -757,6 +757,7 @@  TEST_BUILTINS_OBJS += test-string-list.o
 TEST_BUILTINS_OBJS += test-submodule-config.o
 TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
 TEST_BUILTINS_OBJS += test-subprocess.o
+TEST_BUILTINS_OBJS += test-touch.o
 TEST_BUILTINS_OBJS += test-trace2.o
 TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
 TEST_BUILTINS_OBJS += test-userdiff.o
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index af879e4a5d7..1ad8d5fbd82 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -73,6 +73,7 @@  static struct test_cmd cmds[] = {
 	{ "submodule-config", cmd__submodule_config },
 	{ "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
 	{ "subprocess", cmd__subprocess },
+	{ "touch", cmd__touch },
 	{ "trace2", cmd__trace2 },
 	{ "userdiff", cmd__userdiff },
 	{ "urlmatch-normalization", cmd__urlmatch_normalization },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index 6c5134b46d9..58fde0a62e5 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -63,6 +63,7 @@  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__touch(int argc, const char **argv);
 int cmd__trace2(int argc, const char **argv);
 int cmd__userdiff(int argc, const char **argv);
 int cmd__urlmatch_normalization(int argc, const char **argv);
diff --git a/t/helper/test-touch.c b/t/helper/test-touch.c
new file mode 100644
index 00000000000..e9b3b754f1f
--- /dev/null
+++ b/t/helper/test-touch.c
@@ -0,0 +1,126 @@ 
+/*
+ * test-touch.c: variation on /usr/bin/touch to speed up tests
+ * with a large number of files (primarily on Windows where child
+ * process are very, very expensive).
+ */
+
+#include "test-tool.h"
+#include "cache.h"
+#include "parse-options.h"
+
+char *seq_pattern;
+int seq_start = 1;
+int seq_count = 1;
+
+static int do_touch_one(const char *path)
+{
+	int fd;
+
+	if (!utime(path, NULL))
+		return 0;
+
+	if (errno != ENOENT) {
+		warning_errno("could not touch '%s'", path);
+		return 0;
+	}
+
+	fd = open(path, O_RDWR | O_CREAT, 0644);
+	if (fd == -1) {
+		warning_errno("could not create '%s'", path);
+		return 0;
+	}
+	close(fd);
+
+	return 0;
+}
+
+/*
+ * Touch a series of files.  We assume that any required subdirs
+ * already exist.  This function allows us to replace the following
+ * test script fragment:
+ *
+ *    for i in $(test_seq 1 10000); do touch 10000_files/$i; done &&
+ *
+ * with a single process:
+ *
+ *    test-tool touch sequence --pattern="10000_files/%d" --start=1 --count=10000
+ *
+ * which is much faster on Windows.
+ */
+static int do_sequence(void)
+{
+	struct strbuf buf = STRBUF_INIT;
+	int k;
+
+	for (k = seq_start; k < seq_start + seq_count; k++) {
+		strbuf_reset(&buf);
+		strbuf_addf(&buf, seq_pattern, k);
+
+		if (do_touch_one(buf.buf))
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Read a list of pathnames from stdin and touch them.  We assume that
+ * any required subdirs already exist.
+ */
+static int do_stdin(void)
+{
+	struct strbuf buf = STRBUF_INIT;
+
+	while (strbuf_getline(&buf, stdin) != EOF && buf.len)
+		if (do_touch_one(buf.buf))
+			return 1;
+
+	return 0;
+}
+
+int cmd__touch(int argc, const char **argv)
+{
+	const char *touch_usage[] = {
+		N_("test-tool touch sequence <pattern> <start> <count>"),
+		N_("test-tool touch stdin"),
+		NULL,
+	};
+
+	struct option touch_options[] = {
+		OPT_GROUP(N_("sequence")),
+		OPT_STRING(0, "pattern", &seq_pattern, N_("format"),
+			   N_("sequence pathname pattern")),
+		OPT_INTEGER(0, "start", &seq_start,
+			    N_("sequence starting value")),
+		OPT_INTEGER(0, "count", &seq_count,
+			    N_("sequence count")),
+		OPT_END()
+	};
+
+	const char *subcmd;
+
+	if (argc < 2)
+		usage_with_options(touch_usage, touch_options);
+	if (argc == 2 && !strcmp(argv[1], "-h"))
+		usage_with_options(touch_usage, touch_options);
+
+	subcmd = argv[1];
+	argv--;
+	argc++;
+
+	argc = parse_options(argc, argv, NULL, touch_options, touch_usage, 0);
+
+	if (!strcmp(subcmd, "sequence")) {
+		if (!seq_pattern || !strstr(seq_pattern, "%d"))
+			die("invalid sequence pattern");
+		if (seq_count < 1)
+			die("invalid sequence count: %d", seq_count);
+		return !!do_sequence();
+	}
+
+	if (!strcmp(subcmd, "stdin")) {
+		return !!do_stdin();
+	}
+
+	die("Unhandled subcommand: '%s'", subcmd);
+}