test-mergesort: add generate subcommand

Add a subcommand for printing test data. It can be used to generate special test cases and feed them into the sort subcommand or sort(1) for performance measurements. It may also be useful to illustrate the effect of distributions, modes and their parameters. It generates n integers with the specified distribution and its distribution-specific parameter m. E.g. m is the maximum value for the plateau distribution and the length and height of individual teeth of the sawtooth distribution. The generated values are printed as zero-padded eight-digit hexadecimal numbers to make sure alphabetic and numeric order are the same. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Oct 1, 2021 at 11:14 UTC 0cecb75531e1ab525f42943be71f4a213d023412
1 file changed +59 -1
t/helper/test-mergesort.c
+59 -1
@@ -98,6 +98,16 @@ static struct dist {
98 DIST(shuffle),
99 };
100
101 +static const struct dist *get_dist_by_name(const char *name)
102 +{
103 + int i;
104 + for (i = 0; i < ARRAY_SIZE(dist); i++) {
105 + if (!strcmp(dist[i].name, name))
106 + return &dist[i];
107 + }
108 + return NULL;
109 +}
110 +
111 static void mode_copy(int *arr, int n)
112 {
113 /* nothing */
@@ -154,6 +164,41 @@ static struct mode {
164 MODE(dither),
165 };
166
167 +static const struct mode *get_mode_by_name(const char *name)
168 +{
169 + int i;
170 + for (i = 0; i < ARRAY_SIZE(mode); i++) {
171 + if (!strcmp(mode[i].name, name))
172 + return &mode[i];
173 + }
174 + return NULL;
175 +}
176 +
177 +static int generate(int argc, const char **argv)
178 +{
179 + const struct dist *dist = NULL;
180 + const struct mode *mode = NULL;
181 + int i, n, m, *arr;
182 +
183 + if (argc != 4)
184 + return 1;
185 +
186 + dist = get_dist_by_name(argv[0]);
187 + mode = get_mode_by_name(argv[1]);
188 + n = strtol(argv[2], NULL, 10);
189 + m = strtol(argv[3], NULL, 10);
190 + if (!dist || !mode)
191 + return 1;
192 +
193 + ALLOC_ARRAY(arr, n);
194 + dist->fn(arr, n, m);
195 + mode->fn(arr, n);
196 + for (i = 0; i < n; i++)
197 + printf("%08x\n", arr[i]);
198 + free(arr);
199 + return 0;
200 +}
201 +
202 static struct stats {
203 int get_next, set_next, compare;
204 } stats;
@@ -278,11 +323,24 @@ static int run_tests(int argc, const char **argv)
323
324 int cmd__mergesort(int argc, const char **argv)
325 {
326 + int i;
327 + const char *sep;
328 +
329 + if (argc == 6 && !strcmp(argv[1], "generate"))
330 + return generate(argc - 2, argv + 2);
331 if (argc == 2 && !strcmp(argv[1], "sort"))
332 return sort_stdin();
333 if (argc > 1 && !strcmp(argv[1], "test"))
334 return run_tests(argc - 2, argv + 2);
285 - fprintf(stderr, "usage: test-tool mergesort sort\n");
335 + fprintf(stderr, "usage: test-tool mergesort generate <distribution> <mode> <n> <m>\n");
336 + fprintf(stderr, " or: test-tool mergesort sort\n");
337 fprintf(stderr, " or: test-tool mergesort test [<n>...]\n");
338 + fprintf(stderr, "\n");
339 + for (i = 0, sep = "distributions: "; i < ARRAY_SIZE(dist); i++, sep = ", ")
340 + fprintf(stderr, "%s%s", sep, dist[i].name);
341 + fprintf(stderr, "\n");
342 + for (i = 0, sep = "modes: "; i < ARRAY_SIZE(mode); i++, sep = ", ")
343 + fprintf(stderr, "%s%s", sep, mode[i].name);
344 + fprintf(stderr, "\n");
345 return 129;
346 }