summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClarisse Cheah <clarisse.cheah@mongodb.com>2022-10-16 23:44:05 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-17 00:18:57 +0000
commit66d5774b8394dc5385e9dff11971bde66a6c8445 (patch)
tree6c320412b13b3f79469915aa20e9ae9c39132313
parentc799404a8968a3cc2e794c1389ea058611ae1b09 (diff)
downloadmongo-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.ok11
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt2447_join_main_table/main.c2
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt9937_parse_opts/main.c365
-rwxr-xr-xsrc/third_party/wiredtiger/test/evergreen.yml10
-rw-r--r--src/third_party/wiredtiger/test/utility/misc.c9
-rw-r--r--src/third_party/wiredtiger/test/utility/parse_opts.c296
-rw-r--r--src/third_party/wiredtiger/test/utility/test_util.h19
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 *);