diff options
author | Clarisse Cheah <clarisse.cheah@mongodb.com> | 2022-10-16 23:44:05 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-10-17 00:18:57 +0000 |
commit | 66d5774b8394dc5385e9dff11971bde66a6c8445 (patch) | |
tree | 6c320412b13b3f79469915aa20e9ae9c39132313 | |
parent | c799404a8968a3cc2e794c1389ea058611ae1b09 (diff) | |
download | mongo-66d5774b8394dc5385e9dff11971bde66a6c8445.tar.gz |
Import wiredtiger: 91d645f95bf454168c6d15d0940f18a328e1c7bf from branch mongodb-master
ref: 3098d774bc..91d645f95b
for: 6.2.0-rc0
WT-9937 Added testutil_parse_opt to allow extended argument parsing. (#8320)
-rw-r--r-- | src/third_party/wiredtiger/dist/s_string.ok | 11 | ||||
-rw-r--r-- | src/third_party/wiredtiger/import.data | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/csuite/wt2447_join_main_table/main.c | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/csuite/wt9937_parse_opts/main.c | 365 | ||||
-rwxr-xr-x | src/third_party/wiredtiger/test/evergreen.yml | 10 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/utility/misc.c | 9 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/utility/parse_opts.c | 296 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/utility/test_util.h | 19 |
8 files changed, 553 insertions, 161 deletions
diff --git a/src/third_party/wiredtiger/dist/s_string.ok b/src/third_party/wiredtiger/dist/s_string.ok index d564365e0c8..c65436830d8 100644 --- a/src/third_party/wiredtiger/dist/s_string.ok +++ b/src/third_party/wiredtiger/dist/s_string.ok @@ -357,6 +357,7 @@ PackOutputStream Pandis Phong PlatformSDK +Pomy Posix PostgreSQL Postrun @@ -592,6 +593,7 @@ batchSize bb bba bbb +bbuilddir bcr beginthreadex bigram @@ -610,6 +612,7 @@ bm bnd bool boolean +boption br breakpoint bs @@ -831,6 +834,7 @@ dsync dumpcmp dumpfile dup +dv eee eg egrep @@ -854,6 +858,8 @@ errhandler errno errx esc +ev +evd eventv evictable evictserver @@ -1263,6 +1269,7 @@ other's oversized ovfl ownp +pR packv pagedump pageref @@ -1555,6 +1562,7 @@ unhandled unicode uninstantiated unistd +unittest unlink unlinked unmap @@ -1593,6 +1601,8 @@ util utils uu vN +vPomy +vW va valgrind validator @@ -1601,6 +1611,7 @@ valuev vanishingly variable's variadic +vd vdata vec vectorized diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index b5f05daf23b..1a38e364e89 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -2,5 +2,5 @@ "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", "branch": "mongodb-master", - "commit": "3098d774bca59302b7f9ac672b839343f5795821" + "commit": "91d645f95bf454168c6d15d0940f18a328e1c7bf" } diff --git a/src/third_party/wiredtiger/test/csuite/wt2447_join_main_table/main.c b/src/third_party/wiredtiger/test/csuite/wt2447_join_main_table/main.c index 48f10203edb..a80dc7c8ad4 100644 --- a/src/third_party/wiredtiger/test/csuite/wt2447_join_main_table/main.c +++ b/src/third_party/wiredtiger/test/csuite/wt2447_join_main_table/main.c @@ -112,6 +112,8 @@ main(int argc, char *argv[]) break; case TABLE_FIX: testutil_die(ENOTSUP, "Fixed-length column store not supported"); + case TABLE_NOT_SET: + testutil_die(ENOTSUP, "Unknown table type (%d)\n", (int)opts->table_type); case TABLE_ROW: printf("Table type: rows\n"); break; diff --git a/src/third_party/wiredtiger/test/csuite/wt9937_parse_opts/main.c b/src/third_party/wiredtiger/test/csuite/wt9937_parse_opts/main.c new file mode 100644 index 00000000000..bae6f601266 --- /dev/null +++ b/src/third_party/wiredtiger/test/csuite/wt9937_parse_opts/main.c @@ -0,0 +1,365 @@ +/*- + * Public Domain 2014-present MongoDB, Inc. + * Public Domain 2008-2014 WiredTiger, Inc. + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "test_util.h" + +/* + * This is a unit test for the testutil_parse_opts and testutil_parse_single_opt functions. + * + * In one part of the test, we do a straightforward test of the testutil_parse_opts function. This + * function is used by test programs to parse a fixed set of commonly used options, for example + * ".... -h home_dir -T 3 -v" sets the home directory as indicated, the thread count to 3 and turns + * on verbose. Options are parsed and a TEST_OPTS structure is modified accordingly. To test this, + * we have a set of simulated command lines and our expected contents of the TEST_OPTS structure. + * These command lines and expected TEST_OPTS appear as the first entries in the driver array below. + * + * In the second part of the test, we want to parse additional options. Many test programs need some + * options from the fixed set provided by the testutil_parse_opts function, but perhaps need + * additional options. We have in mind a fictional test program that wants to use the standard + * testutil parsing for options 'b', 'P', 'T', and 'v', and has added its own options: 'c', 'd', + * 'e', and 'f', which it stores in a struct below called FICTIONAL_OPTS. Note that its 'd' option + * overrides the standard 'd' option. To do this sort of "extended" parsing, we need to use a + * particular idiom that uses testutil_parse_begin_opt, getopt, testutil_parse_single_opt, and + * testutil_parse_end_opt, as seen in the check function. + */ + +extern char *__wt_optarg; /* option argument */ +extern int __wt_optind; /* argv position, needed to reset __wt_getopt parser */ +extern int __wt_optreset; /* needed to reset the parser internal state */ + +/* + * This structure aids in testing testutil_parse_single_opt. The options here only have meaning to + * our fictional test program. + */ +typedef struct { + char *checkpoint_name; /* -c option, takes a string argument */ + bool delete_flag; /* -d option */ + bool energize_flag; /* -e option, it's fictional! */ + int fuzziness_option; /* -f option, takes an int argument */ +} FICTIONAL_OPTS; + +/* + * This drives the testing. For each given command_line, there is a matching expected TEST_OPTS + * structure. When argv[0] is "parse_opts", we are driving testutil_parse_opts. If argv[0] is + * "parse_single_opt", then we are parsing some of our "own" options, put into an FICTIONAL_OPTS + * struct, and using testutil_parse_single_opt to parse any we don't recognize, those are put into + * TEST_OPTS. + */ +typedef struct { + const char *command_line[10]; + TEST_OPTS expected; + FICTIONAL_OPTS fiction_expected; +} TEST_DRIVER; + +/* + * We've chosen tests to cover: + * - string options both appearing as "-b option" and "-boption" + * - int options also appearing both as "-T 21" and "-T21" + * - tiered storage multiple character options starting with "-P", like "-PT" and "-Po name". + * - flag options like "-v". + * - our set of "fictional" arguments. + * + */ +#define UNUSED_OPTS 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +static TEST_DRIVER driver[] = { + {{"parse_opts", "-b", "builddir", "-T", "21", NULL}, + {NULL, NULL, {0}, NULL, (char *)"builddir", NULL, 0, NULL, NULL, false, false, false, false, 0, + 0, 21, UNUSED_OPTS}, + {NULL, 0, 0, 0}}, + + {{"parse_opts", "-bbuilddir", "-T21", NULL}, + {NULL, NULL, {0}, NULL, (char *)"builddir", NULL, 0, NULL, NULL, false, false, false, false, 0, + 0, 21, UNUSED_OPTS}, + {NULL, 0, 0, 0}}, + + /* If -PT is used, the tiered_storage source is set to dir_store, even if -Po is not used. */ + {{"parse_opts", "-v", "-PT", NULL}, + {NULL, NULL, {0}, NULL, NULL, (char *)"dir_store", 0, NULL, NULL, false, false, true, true, 0, + 0, 0, UNUSED_OPTS}, + {NULL, 0, 0, 0}}, + + {{"parse_opts", "-v", "-Po", "my_store", "-PT", NULL}, + {NULL, NULL, {0}, NULL, NULL, (char *)"my_store", 0, NULL, NULL, false, false, true, true, 0, 0, + 0, UNUSED_OPTS}, + {NULL, 0, 0, 0}}, + + {{"parse_opts", "-vPomy_store", "-PT", NULL}, + {NULL, NULL, {0}, NULL, NULL, (char *)"my_store", 0, NULL, NULL, false, false, true, true, 0, 0, + 0, UNUSED_OPTS}, + {NULL, 0, 0, 0}}, + + /* + * From here on, we are using some "extended" options, see previous comment. We set the argv[0] to + * "parse_single_opt" to indicate to use the extended parsing idiom. + */ + {{"parse_single_opt", "-vd", "-Pomy_store", "-c", "string_opt", "-PT", NULL}, + {NULL, NULL, {0}, NULL, NULL, (char *)"my_store", 0, NULL, NULL, false, false, true, true, 0, 0, + 0, UNUSED_OPTS}, + {(char *)"string_opt", true, false, 0}}, + + {{"parse_single_opt", "-dv", "-Pomy_store", "-cstring_opt", "-PT", NULL}, + {NULL, NULL, {0}, NULL, NULL, (char *)"my_store", 0, NULL, NULL, false, false, true, true, 0, 0, + 0, UNUSED_OPTS}, + {(char *)"string_opt", true, false, 0}}, + + {{"parse_single_opt", "-ev", "-cstring_opt", "-Pomy_store", "-PT", "-f", "22", NULL}, + {NULL, NULL, {0}, NULL, NULL, (char *)"my_store", 0, NULL, NULL, false, false, true, true, 0, 0, + 0, UNUSED_OPTS}, + {(char *)"string_opt", false, true, 22}}, + + {{"parse_single_opt", "-evd", "-Pomy_store", "-PT", "-f22", NULL}, + {NULL, NULL, {0}, NULL, NULL, (char *)"my_store", 0, NULL, NULL, false, false, true, true, 0, 0, + 0, UNUSED_OPTS}, + {NULL, true, true, 22}}, + + {{"parse_single_opt", "-v", "-Pomy_store", "-PT", NULL}, + {NULL, NULL, {0}, NULL, NULL, (char *)"my_store", 0, NULL, NULL, false, false, true, true, 0, 0, + 0, UNUSED_OPTS}, + {NULL, false, false, 0}}, +}; + +/* + * report -- + * Show any changed fields in the options. + */ +static void +report(const TEST_OPTS *opts, FICTIONAL_OPTS *fiction_opts) +{ +#define REPORT_INT(o, field) \ + do { \ + if (o->field != 0) \ + printf(#field ": %" PRIu64 "\n", (uint64_t)o->field); \ + } while (0) +#define REPORT_STR(o, field) \ + do { \ + if (o->field != NULL) \ + printf(#field ": %s\n", o->field); \ + } while (0) + + REPORT_STR(opts, home); + REPORT_STR(opts, build_dir); + REPORT_STR(opts, tiered_storage_source); + REPORT_INT(opts, table_type); + REPORT_INT(opts, do_data_ops); + REPORT_INT(opts, preserve); + REPORT_INT(opts, tiered_storage); + REPORT_INT(opts, verbose); + REPORT_INT(opts, nrecords); + REPORT_INT(opts, nops); + REPORT_INT(opts, nthreads); + REPORT_INT(opts, n_append_threads); + REPORT_INT(opts, n_read_threads); + REPORT_INT(opts, n_write_threads); + REPORT_STR(fiction_opts, checkpoint_name); + REPORT_INT(fiction_opts, delete_flag); + REPORT_INT(fiction_opts, energize_flag); + REPORT_INT(fiction_opts, fuzziness_option); +} + +/* + * check -- + * Call testutil_parse_opts or use extended parsing with testutil_parse_single_opt and return + * options. + */ +static void +check(int argc, char *const *argv, TEST_OPTS *opts, FICTIONAL_OPTS *fiction_opts) +{ + int ch; + const char *fiction_usage = " [-c string] [-d] [-e] [-f int]"; + const char *prog; + + memset(opts, 0, sizeof(*opts)); + memset(fiction_opts, 0, sizeof(*fiction_opts)); + + /* This may be called multiple times, so reset the __wt_getopt parser. */ + __wt_optind = 1; + __wt_optreset = 1; + + prog = argv[0]; + if (strchr(prog, '/') != NULL) + prog = strchr(prog, '/') + 1; + + if (strcmp(prog, "parse_opts") == 0) { + /* Regular test of testutil_parse_opts, using only the options that it provides. */ + + testutil_check(testutil_parse_opts(argc, argv, opts)); + } else { + /* + * Test of extended parsing, in which we'll parse some options that we know about and rely + * on testutil_parse_single_opt to cover the options it knows about. + */ + testutil_assert(strcmp(prog, "parse_single_opt") == 0); + + /* + * For this part of the testing, we're parsing options for a fictional test program. This + * test program wants to have the standard testutil parsing for options 'b', 'P', 'T', and + * 'v', and has added its own options: 'c', 'd', 'e', and 'f'. We use the following idiom to + * accomplish this. + */ + + /* "b:P:T:v" are the only options we want testutil to handle. */ + testutil_parse_begin_opt(argc, argv, "b:P:T:v", opts); + + /* We list the entire set of options we want to support when we call getopt. */ + while ((ch = __wt_getopt(opts->progname, argc, argv, "b:c:def:P:T:v")) != EOF) + switch (ch) { + case 'c': + fiction_opts->checkpoint_name = __wt_optarg; + break; + case 'd': + fiction_opts->delete_flag = true; + break; + case 'e': + fiction_opts->energize_flag = true; + break; + case 'f': + fiction_opts->fuzziness_option = atoi(__wt_optarg); + break; + default: + /* The option is either one that we're asking testutil to support, or illegal. */ + if (testutil_parse_single_opt(opts, ch) != 0) { + (void)fprintf( + stderr, "usage: %s%s%s\n", opts->progname, fiction_usage, opts->usage); + testutil_assert(false); + } + } + /* + * We are finished parsing, so ask testutil to finish any extra processing of the options. + */ + testutil_parse_end_opt(opts); + } +} + +/* + * verify_expect -- + * Verify the returned options against the expected options. + */ +static void +verify_expect( + TEST_OPTS *opts, FICTIONAL_OPTS *fiction_opts, TEST_OPTS *expect, FICTIONAL_OPTS *fiction_expect) +{ +#define VERIFY_INT(o, e, field) \ + do { \ + if (o->field != 0 || e->field != 0) \ + testutil_assert(o->field == e->field); \ + } while (0) +#define VERIFY_STR(o, e, field) \ + do { \ + if (o->field != NULL || e->field != NULL) { \ + testutil_assert(o->field != NULL); \ + testutil_assert(e->field != NULL); \ + testutil_assert(strcmp(o->field, e->field) == 0); \ + } \ + } while (0) + + /* + * opts->home is always set, even without -h on the command line, so don't check it here. + */ + VERIFY_STR(opts, expect, build_dir); + VERIFY_STR(opts, expect, tiered_storage_source); + VERIFY_INT(opts, expect, table_type); + VERIFY_INT(opts, expect, do_data_ops); + VERIFY_INT(opts, expect, preserve); + VERIFY_INT(opts, expect, tiered_storage); + VERIFY_INT(opts, expect, verbose); + VERIFY_INT(opts, expect, nrecords); + VERIFY_INT(opts, expect, nops); + VERIFY_INT(opts, expect, nthreads); + VERIFY_INT(opts, expect, n_append_threads); + VERIFY_INT(opts, expect, n_read_threads); + VERIFY_INT(opts, expect, n_write_threads); + + VERIFY_STR(fiction_opts, fiction_expect, checkpoint_name); + VERIFY_INT(fiction_opts, fiction_expect, delete_flag); + VERIFY_INT(fiction_opts, fiction_expect, energize_flag); + VERIFY_INT(fiction_opts, fiction_expect, fuzziness_option); +} + +/* + * cleanup -- + * Clean up allocated resources. + */ +static void +cleanup(TEST_OPTS *opts, FICTIONAL_OPTS *fiction_opts) +{ + (void)fiction_opts; /* Nothing to clean up here. */ + + testutil_cleanup(opts); +} + +/* + * main -- + * Unit test for test utility functions. + */ +int +main(int argc, char *argv[]) +{ + TEST_OPTS *expect, opts; + FICTIONAL_OPTS *fiction_expect, fiction_opts; + size_t i; + int nargs; + char *const *cmd; + + if (argc > 1) { + /* + * The first arg must be --parse_opt or --parse_single_opt, we'll make argv[0] point to + * "parse_opts" or "parse_single_opt" so our "check" parser knows what kind of parsing to be + * done. This path is not used by test scripts, but can be useful for manual testing. + */ + if (strcmp(argv[1], "--parse_opts") != 0 && strcmp(argv[1], "--parse_single_opt") != 0) { + fprintf(stderr, + "Error: test_wt9937_parse_opts first argument must be --parse_opts or " + "--parse_single_opt, remaining options will be parsed accordingly\n"); + exit(EXIT_FAILURE); + } + + argc--; + argv++; + argv[0] += 2; /* skip past -- */ + + check(argc, argv, &opts, &fiction_opts); + report(&opts, &fiction_opts); + cleanup(&opts, &fiction_opts); + } else { + /* + * For normal testing, we run the whole test, parsing each command line from the driver + * array. + */ + for (i = 0; i < WT_ELEMENTS(driver); i++) { + cmd = (char *const *)driver[i].command_line; + for (nargs = 0; cmd[nargs] != NULL; nargs++) + ; + expect = &driver[i].expected; + fiction_expect = &driver[i].fiction_expected; + check(nargs, cmd, &opts, &fiction_opts); + verify_expect(&opts, &fiction_opts, expect, fiction_expect); + cleanup(&opts, &fiction_opts); + } + } + + exit(0); +} diff --git a/src/third_party/wiredtiger/test/evergreen.yml b/src/third_party/wiredtiger/test/evergreen.yml index bd2857251cc..be6cafe21e4 100755 --- a/src/third_party/wiredtiger/test/evergreen.yml +++ b/src/third_party/wiredtiger/test/evergreen.yml @@ -1846,6 +1846,16 @@ tasks: vars: test_name: wt8963_insert_stress + - name: csuite-wt9937-parse-opts-test + tags: ["pull_request"] + depends_on: + - name: compile + commands: + - func: "fetch artifacts" + - func: "csuite test" + vars: + test_name: wt9937_parse_opts + # End of csuite test tasks # Start of Python unit test tasks diff --git a/src/third_party/wiredtiger/test/utility/misc.c b/src/third_party/wiredtiger/test/utility/misc.c index d9702d94e89..90d50ffd453 100644 --- a/src/third_party/wiredtiger/test/utility/misc.c +++ b/src/third_party/wiredtiger/test/utility/misc.c @@ -207,7 +207,6 @@ testutil_progress(TEST_OPTS *opts, const char *message) void testutil_cleanup(TEST_OPTS *opts) { - int i; if (opts->conn != NULL) testutil_check(opts->conn->close(opts->conn, NULL)); @@ -221,13 +220,7 @@ testutil_cleanup(TEST_OPTS *opts) free(opts->progress_file_name); free(opts->home); free(opts->build_dir); - if (opts->tiered_storage) { - for (i = 0; i <= opts->nargc; ++i) - free(opts->nargv[i]); - free(opts->nargv); - } - if (opts->tiered_storage_source != NULL) - free(opts->tiered_storage_source); + free(opts->tiered_storage_source); } /* diff --git a/src/third_party/wiredtiger/test/utility/parse_opts.c b/src/third_party/wiredtiger/test/utility/parse_opts.c index d87b89c7666..50e300cc3e3 100644 --- a/src/third_party/wiredtiger/test/utility/parse_opts.c +++ b/src/third_party/wiredtiger/test/utility/parse_opts.c @@ -29,88 +29,52 @@ #define DIR_STORE "dir_store" extern char *__wt_optarg; /* argument associated with option */ +extern int __wt_optind; +extern int __wt_optopt; +extern int __wt_optreset; /* - * parse_tiered_opts -- - * Parse command line options for the tiered storage configurations. + * This is called when parsing a sub-option like the 'o' in -Po, which expects an argument. We need + * to update the option argument to point to that argument. + */ +#define EXPECT_OPTIONAL_ARG_IN_SUB_PARSE(opts) \ + do { \ + if (*__wt_optarg == '\0') { \ + /* If we change option indicator, we need to reset getopt. */ \ + __wt_optarg = opts->argv[__wt_optind++]; \ + __wt_optreset = 1; \ + } \ + } while (0) + +/* + * parse_tiered_opt -- + * Parse a command line option for the tiered storage configurations. */ static inline void -parse_tiered_opts(int argc, char *const *argv, TEST_OPTS *opts) +parse_tiered_opt(TEST_OPTS *opts) { - int index, i; - int number_of_tiered_options; - - number_of_tiered_options = 0; - index = 0; - opts->tiered_storage = false; - opts->tiered_storage_source = NULL; - - for (i = 1; i < argc; i++) { - /* Tiered storage command line options starts with -P. */ - if (strstr(argv[i], "-P")) { - /* Many more options to come here. */ - if (argv[i][2] == 'o') { - if (argv[i + 1] == NULL) - testutil_die( - EINVAL, "%s option requires an argument %s", opts->progname, argv[i]); - number_of_tiered_options += 2; - } else if (argv[i][2] == 'T') { - /* This parsing is different because -PT does not accept any arguments. */ - ++number_of_tiered_options; - opts->tiered_storage = true; - } - } + switch (*__wt_optarg++) { + case 'o': + EXPECT_OPTIONAL_ARG_IN_SUB_PARSE(opts); + if (__wt_optarg == NULL || *__wt_optarg == '\0') + testutil_die(EINVAL, "-Po option requires an argument"); + opts->tiered_storage_source = dstrdup(__wt_optarg); + break; + case 'T': + opts->tiered_storage = true; + break; } - - /* Return from here if tiered arguments are not passed. */ - if (!opts->tiered_storage) { - if (number_of_tiered_options == 0) - return; - else - testutil_die( - EINVAL, "Error - Tiered storage command line arguments are passed without -PT."); - } - - opts->nargc = argc - number_of_tiered_options; - - /* Allocate the memory for the new argv without tiered options. */ - opts->nargv = dmalloc(((size_t)opts->nargc + 1) * sizeof(char *)); - - /* Copy other command line arguments except tiered. */ - for (i = 0; i < argc; ++i) { - if (strcmp(argv[i], "-Po") == 0) { - opts->tiered_storage_source = dstrdup(argv[i + 1]); - /* Move the index because this option has an argument. */ - i++; - } else if (strcmp(argv[i], "-PT") == 0) - continue; - else - opts->nargv[index++] = dstrdup(argv[i]); - } - - testutil_assert(index == opts->nargc); - /* - * Allocating an extra empty space at the end of the new argv just to replicate the system argv - * implementation. - */ - opts->nargv[index++] = dstrdup(""); - - if (opts->tiered_storage_source == NULL) - opts->tiered_storage_source = dstrdup(DIR_STORE); } /* - * testutil_parse_opts -- - * Parse command line options for a test case. + * testutil_parse_begin_opt -- + * Start a set of calls to parse single command line options. */ -int -testutil_parse_opts(int argc, char *const *argv, TEST_OPTS *opts) +void +testutil_parse_begin_opt(int argc, char *const *argv, const char *getopts_string, TEST_OPTS *opts) { - size_t len; - int ch; - - opts->nargc = 0; - opts->nargv = NULL; + opts->argc = 0; + opts->argv = NULL; opts->do_data_ops = false; opts->preserve = false; opts->running = true; @@ -118,87 +82,33 @@ testutil_parse_opts(int argc, char *const *argv, TEST_OPTS *opts) opts->argv0 = argv[0]; opts->progname = testutil_set_progname(argv); + opts->getopts_string = getopts_string; testutil_print_command_line(argc, argv); - parse_tiered_opts(argc, argv, opts); + opts->argv = (char **)argv; + opts->argc = argc; - if (!opts->tiered_storage) { - opts->nargv = (char **)argv; - opts->nargc = argc; - } +#define USAGE_STR(ch, usage) ((strchr(getopts_string, (ch)) == NULL) ? "" : (usage)) - while ( - (ch = __wt_getopt(opts->progname, opts->nargc, opts->nargv, "A:b:dh:n:o:pR:T:t:vW:")) != EOF) - switch (ch) { - case 'A': /* Number of append threads */ - opts->n_append_threads = (uint64_t)atoll(__wt_optarg); - break; - case 'b': /* Build directory */ - opts->build_dir = dstrdup(__wt_optarg); - break; - case 'd': /* Use data in multi-threaded test programs */ - opts->do_data_ops = true; - break; - case 'h': /* Home directory */ - opts->home = dstrdup(__wt_optarg); - break; - case 'n': /* Number of records */ - opts->nrecords = (uint64_t)atoll(__wt_optarg); - break; - case 'o': /* Number of operations */ - opts->nops = (uint64_t)atoll(__wt_optarg); - break; - case 'p': /* Preserve directory contents */ - opts->preserve = true; - break; - case 'R': /* Number of reader threads */ - opts->n_read_threads = (uint64_t)atoll(__wt_optarg); - break; - case 'T': /* Number of threads */ - opts->nthreads = (uint64_t)atoll(__wt_optarg); - break; - case 't': /* Table type */ - switch (__wt_optarg[0]) { - case 'C': - case 'c': - opts->table_type = TABLE_COL; - break; - case 'F': - case 'f': - opts->table_type = TABLE_FIX; - break; - case 'R': - case 'r': - opts->table_type = TABLE_ROW; - break; - } - break; - case 'v': - opts->verbose = true; - break; - case 'W': /* Number of writer threads */ - opts->n_write_threads = (uint64_t)atoll(__wt_optarg); - break; - case '?': - default: - (void)fprintf(stderr, - "usage: %s " - "[-A append thread count] " - "[-b build directory] " - "[-d add data] " - "[-h home] " - "[-n record count] " - "[-o op count] " - "[-p] " - "[-R read thread count] " - "[-T thread count] " - "[-t c|f|r table type] " - "[-v] " - "[-W write thread count] ", - opts->progname); - return (1); - } + testutil_check(__wt_snprintf(opts->usage, sizeof(opts->usage), "%s%s%s%s%s%s%s%s%s%s%s%s%s", + USAGE_STR('A', " [-A append thread count]"), USAGE_STR('b', " [-b build directory]"), + USAGE_STR('d', " [-d add data]"), USAGE_STR('h', " [-h home]"), + USAGE_STR('n', " [-n record count]"), USAGE_STR('o', " [-o op count]"), + USAGE_STR('P', " [-PT] [-Po storage source]"), USAGE_STR('p', " [-p]"), + USAGE_STR('R', " [-R read thread count]"), USAGE_STR('T', " [-T thread count]"), + USAGE_STR('t', " [-t c|f|r table type]"), USAGE_STR('v', " [-v]"), + USAGE_STR('W', " [-W write thread count]"))); +} + +/* + * testutil_parse_end_opt -- + * Finish a set of calls to parse single command line options. + */ +void +testutil_parse_end_opt(TEST_OPTS *opts) +{ + size_t len; /* * Setup the home directory if not explicitly specified. It needs to be unique for every test or @@ -222,5 +132,97 @@ testutil_parse_opts(int argc, char *const *argv, TEST_OPTS *opts) opts->uri = dmalloc(len); testutil_check(__wt_snprintf(opts->uri, len, "table:%s", opts->progname)); + if (opts->tiered_storage && opts->tiered_storage_source == NULL) + opts->tiered_storage_source = dstrdup(DIR_STORE); +} + +/* + * testutil_parse_single_opt -- + * Parse a single command line option for a test case. + */ +int +testutil_parse_single_opt(TEST_OPTS *opts, int ch) +{ + if (ch == '?' || strchr(opts->getopts_string, ch) == NULL) + return (1); + + switch (ch) { + case 'A': /* Number of append threads */ + opts->n_append_threads = (uint64_t)atoll(__wt_optarg); + break; + case 'b': /* Build directory */ + opts->build_dir = dstrdup(__wt_optarg); + break; + case 'd': /* Use data in multi-threaded test programs */ + opts->do_data_ops = true; + break; + case 'h': /* Home directory */ + opts->home = dstrdup(__wt_optarg); + break; + case 'n': /* Number of records */ + opts->nrecords = (uint64_t)atoll(__wt_optarg); + break; + case 'o': /* Number of operations */ + opts->nops = (uint64_t)atoll(__wt_optarg); + break; + case 'P': /* Tiered storage options follow */ + parse_tiered_opt(opts); + break; + case 'p': /* Preserve directory contents */ + opts->preserve = true; + break; + case 'R': /* Number of reader threads */ + opts->n_read_threads = (uint64_t)atoll(__wt_optarg); + break; + case 'T': /* Number of threads */ + opts->nthreads = (uint64_t)atoll(__wt_optarg); + break; + case 't': /* Table type */ + switch (__wt_optarg[0]) { + case 'C': + case 'c': + opts->table_type = TABLE_COL; + break; + case 'F': + case 'f': + opts->table_type = TABLE_FIX; + break; + case 'R': + case 'r': + opts->table_type = TABLE_ROW; + break; + } + break; + case 'v': + opts->verbose = true; + break; + case 'W': /* Number of writer threads */ + opts->n_write_threads = (uint64_t)atoll(__wt_optarg); + break; + case '?': + default: + return (1); + } + return (0); +} + +/* + * testutil_parse_opts -- + * Parse command line options for a test case. + */ +int +testutil_parse_opts(int argc, char *const *argv, TEST_OPTS *opts) +{ + int ch; + static const char *getopt_args = "A:b:dh:n:o:P:pR:T:t:vW:"; + + testutil_parse_begin_opt(argc, argv, getopt_args, opts); + while ((ch = __wt_getopt(opts->progname, opts->argc, opts->argv, getopt_args)) != EOF) + if (testutil_parse_single_opt(opts, ch) != 0) { + (void)fprintf(stderr, "usage: %s%s\n", opts->progname, opts->usage); + return (1); + } + + testutil_parse_end_opt(opts); return (0); } diff --git a/src/third_party/wiredtiger/test/utility/test_util.h b/src/third_party/wiredtiger/test/utility/test_util.h index 40fc123fbe3..a7af77dd7d7 100644 --- a/src/third_party/wiredtiger/test/utility/test_util.h +++ b/src/third_party/wiredtiger/test/utility/test_util.h @@ -53,17 +53,17 @@ typedef struct { char *home; const char *argv0; /* Exec name */ - char **nargv; /* New argument vector */ - int nargc; /* New argument count */ + char usage[256]; /* Usage string for this parser */ const char *progname; /* Truncated program name */ char *build_dir; /* Build directory path */ char *tiered_storage_source; /* Tiered storage source */ enum { - TABLE_COL = 1, /* Fixed-length column store */ - TABLE_FIX = 2, /* Variable-length column store */ - TABLE_ROW = 3 /* Row-store */ + TABLE_NOT_SET = 0, /* Not explicitly set */ + TABLE_COL = 1, /* Fixed-length column store */ + TABLE_FIX = 2, /* Variable-length column store */ + TABLE_ROW = 3 /* Row-store */ } table_type; FILE *progress_fp; /* Progress tracking file */ @@ -91,6 +91,12 @@ typedef struct { volatile uint64_t next_threadid; uint64_t unique_id; uint64_t max_inserted_id; + + /* Fields used internally by testutil library. */ + char **argv; /* Saved argument vector */ + int argc; /* Saved argument count */ + const char *getopts_string; + } TEST_OPTS; /* @@ -370,6 +376,9 @@ void testutil_copy_if_exists(WT_SESSION *, const char *); void testutil_create_backup_directory(const char *); void testutil_make_work_dir(const char *); void testutil_modify_apply(WT_ITEM *, WT_ITEM *, WT_MODIFY *, int, uint8_t); +void testutil_parse_begin_opt(int, char *const *, const char *, TEST_OPTS *); +void testutil_parse_end_opt(TEST_OPTS *); +int testutil_parse_single_opt(TEST_OPTS *, int); int testutil_parse_opts(int, char *const *, TEST_OPTS *); void testutil_print_command_line(int argc, char *const *argv); void testutil_progress(TEST_OPTS *, const char *); |