From 9d73ed08657b4e613bab16bb29cee9ff22e9c846 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Thu, 26 Jan 2017 04:23:55 +0300 Subject: [PATCH] Allow Lua scripts to declare supported options. Lua scripts can now declare their supported options, in which case sysbench validates command line arguments and display usage information. This is a prerequisite for fixing #15 and #79. --- .gitignore | 3 + configure.ac | 1 + sysbench/Makefile.am | 2 +- sysbench/lua/internal/Makefile.am | 4 +- sysbench/lua/internal/sysbench.cmdline.lua | 139 ++++++++++++++++ sysbench/sb_lua.c | 183 ++++++++++++++++++--- sysbench/sb_options.c | 15 +- sysbench/sb_options.h | 8 +- sysbench/sb_rand.c | 31 ++-- sysbench/sysbench.c | 12 +- sysbench/tests/fileio/sb_fileio.c | 4 +- tests/t/api_basic.t | 2 +- tests/t/cmdline.t | 122 +++++++++++++- 13 files changed, 470 insertions(+), 56 deletions(-) create mode 100644 sysbench/lua/internal/sysbench.cmdline.lua diff --git a/.gitignore b/.gitignore index 701b149..1448ee2 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,6 @@ third_party/luajit/tmp/ sysbench/lua/internal/sysbench.lua.h sysbench/lua/internal/sysbench.sql.lua.h /sysbench/lua/internal/sysbench.rand.lua.h +/sysbench/lua/internal/sysbench.opt.lua.h +tests/t/*.err +/sysbench/lua/internal/sysbench.cmdline.lua.h diff --git a/configure.ac b/configure.ac index 1474610..edff54a 100644 --- a/configure.ac +++ b/configure.ac @@ -301,6 +301,7 @@ sys/shm.h \ thread.h \ unistd.h \ limits.h \ +libgen.h \ ]) diff --git a/sysbench/Makefile.am b/sysbench/Makefile.am index d8afe5d..1d8b5e9 100644 --- a/sysbench/Makefile.am +++ b/sysbench/Makefile.am @@ -49,7 +49,7 @@ sb_options.c sb_options.h sb_logger.c sb_logger.h sb_list.h db_driver.h \ db_driver.c sb_histogram.c sb_histogram.h sb_rand.c sb_rand.h \ sb_thread.c sb_thread.h sb_barrier.c sb_barrier.h sb_lua.c \ sb_lua.h lua/internal/sysbench.lua.h lua/internal/sysbench.sql.lua.h \ -lua/internal/sysbench.rand.lua.h sb_util.h \ +lua/internal/sysbench.rand.lua.h lua/internal/sysbench.cmdline.lua.h sb_util.h \ xoroshiro128plus.h sb_util.c sysbench_LDADD = tests/fileio/libsbfileio.a tests/threads/libsbthreads.a \ diff --git a/sysbench/lua/internal/Makefile.am b/sysbench/lua/internal/Makefile.am index 6976c1b..3a55509 100644 --- a/sysbench/lua/internal/Makefile.am +++ b/sysbench/lua/internal/Makefile.am @@ -14,7 +14,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -BUILT_SOURCES = sysbench.lua.h sysbench.rand.lua.h sysbench.sql.lua.h +BUILT_SOURCES = sysbench.lua.h sysbench.rand.lua.h sysbench.sql.lua.h \ + sysbench.cmdline.lua.h + CLEARFILES = $(BUILT_SOURCES) EXTRA_DIST = $(BUILT_SOURCES:.h=) diff --git a/sysbench/lua/internal/sysbench.cmdline.lua b/sysbench/lua/internal/sysbench.cmdline.lua new file mode 100644 index 0000000..9b01ad0 --- /dev/null +++ b/sysbench/lua/internal/sysbench.cmdline.lua @@ -0,0 +1,139 @@ +-- Copyright (C) 2017 Alexey Kopytov + +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. + +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +-- ---------------------------------------------------------------------- +-- Command line option handling +-- ---------------------------------------------------------------------- + +ffi = require("ffi") + +sysbench.cmdline = {} + +ffi.cdef[[ +/* The following has been copied from sb_option.h */ + +typedef enum +{ + SB_ARG_TYPE_NULL, + SB_ARG_TYPE_BOOL, + SB_ARG_TYPE_INT, + SB_ARG_TYPE_SIZE, + SB_ARG_TYPE_DOUBLE, + SB_ARG_TYPE_STRING, + SB_ARG_TYPE_LIST, + SB_ARG_TYPE_FILE, + SB_ARG_TYPE_MAX +} sb_arg_type_t; + +/* Option validation function */ +typedef bool sb_arg_validate_t(const char *, const char *); + +/* Test option definition */ +typedef struct +{ + const char *name; + const char *desc; + const char *value; + sb_arg_type_t type; + sb_arg_validate_t *validate; +} sb_arg_t; + +int sb_lua_set_test_args(sb_arg_t *args, size_t len); +]] + +sysbench.cmdline.ARG_NULL = ffi.C.SB_ARG_TYPE_NULL +sysbench.cmdline.ARG_BOOL = ffi.C.SB_ARG_TYPE_BOOL +sysbench.cmdline.ARG_INT = ffi.C.SB_ARG_TYPE_INT +sysbench.cmdline.ARG_SIZE = ffi.C.SB_ARG_TYPE_SIZE +sysbench.cmdline.ARG_DOUBLE = ffi.C.SB_ARG_TYPE_DOUBLE +sysbench.cmdline.ARG_STRING = ffi.C.SB_ARG_TYPE_STRING +sysbench.cmdline.ARG_LIST = ffi.C.SB_ARG_TYPE_LIST +sysbench.cmdline.ARG_FILE = ffi.C.SB_ARG_TYPE_FILE +sysbench.cmdline.ARG_MAX = ffi.C.SB_ARG_TYPE_MAX + +local arg_types = { + boolean = sysbench.cmdline.ARG_BOOL, + string = sysbench.cmdline.ARG_STRING, + number = sysbench.cmdline.ARG_DOUBLE, + table = sysbench.cmdline.ARG_LIST +} + +-- Parse command line options definitions, if present in the script as a a +-- 'sysbench.option_defs' table. If no such table exists, or if there a parsing +-- error, return false. Return true on success. +function sysbench.cmdline.read_option_defs() + if sysbench.option_defs == nil then + return true + end + + local t = type(sysbench.option_defs) + assert(t == "table", "wrong type for sysbench.option_defs: " .. t) + + local i = 0 + for name, def in pairs(sysbench.option_defs) do + i = i+1 + end + + local args = ffi.new('sb_arg_t[?]', i) + i = 0 + + for name, def in pairs(sysbench.option_defs) do + -- name + assert(type(name) == "string", "wrong table structure in " .. + "sysbench.option_defs") + args[i].name = name + + -- description + assert(def[1] ~= nil, "nil description for option " .. name) + args[i].desc = def[1] + + if type(def[2]) == "table" then + assert(type(def[3]) == "nil" or + type(def[3]) == sysbench.cmdline.ARG_LIST, + "wrong type for list option " .. name) + args[i].value = table.concat(def[2], ',') + else + if type(def[2]) == "boolean" then + args[i].value = def[2] and 'on' or 'off' + elseif type(def[2]) == "number" then + args[i].value = tostring(def[2]) + else + args[i].value = def[2] + end + end + + -- type + local t = def[3] + if t == nil then + if def[2] ~= nil then + -- Try to determine the type by the default value + t = arg_types[type(def[2])] + else + t = sysbench.cmdline.ARG_STRING + end + end + + assert(t ~= nil, "cannot determine type for option " .. name) + args[i].type = t + + -- validation function + args[i].validate = def[4] + + i = i + 1 + end + + return ffi.C.sb_lua_set_test_args(args, i) == 0 +end diff --git a/sysbench/sb_lua.c b/sysbench/sb_lua.c index 7f5169f..bac0367 100644 --- a/sysbench/sb_lua.c +++ b/sysbench/sb_lua.c @@ -20,6 +20,10 @@ # include "config.h" #endif +#ifdef HAVE_LIBGEN_H +# include +#endif + #include "sb_lua.h" #include "lua.h" #include "lualib.h" @@ -33,9 +37,10 @@ /* Auto-generated headers for internal scripts. If you add a new header here, - make sure it is also added to the internal_sources array below. + make sure it is also added to the internal_scripts array below. */ #include "lua/internal/sysbench.lua.h" +#include "lua/internal/sysbench.cmdline.lua.h" #include "lua/internal/sysbench.rand.lua.h" #include "lua/internal/sysbench.sql.lua.h" @@ -92,6 +97,7 @@ typedef enum { } sb_lua_error_t; bool sb_lua_more_events(int); +int sb_lua_set_test_args(sb_arg_t *args, size_t len); /* Lua interpreter states */ @@ -99,8 +105,6 @@ static lua_State **states CK_CC_CACHELINE; static sb_test_t sbtest CK_CC_CACHELINE; -static const char *sb_lua_script_path CK_CC_CACHELINE; - static TLS sb_lua_ctxt_t *tls_lua_ctxt CK_CC_CACHELINE; /* Database driver */ @@ -110,6 +114,7 @@ static TLS db_driver_t *db_driver; static internal_script_t internal_scripts[] = { {"sysbench.rand.lua", sysbench_rand_lua, &sysbench_rand_lua_len}, {"sysbench.lua", sysbench_lua, &sysbench_lua_len}, + {"sysbench.cmdline.lua", sysbench_cmdline_lua, &sysbench_cmdline_lua_len}, {"sysbench.sql.lua", sysbench_sql_lua, &sysbench_sql_lua_len}, {NULL, NULL, 0} }; @@ -159,6 +164,8 @@ static int sb_lua_db_free_results(lua_State *); static unsigned int sb_lua_table_size(lua_State *, int); +static int read_option_defs(lua_State *L); + static void call_error(lua_State *L, const char *name) { const char * const err = lua_tostring(L, -1); @@ -182,17 +189,36 @@ static bool func_available(lua_State *L, const char *func) return rc; } +static void xfree(const void *ptr) +{ + if (ptr != NULL) + free((void *) ptr); +} + /* Load a specified Lua script */ sb_test_t *sb_load_lua(const char *testname) { - sb_lua_script_path = testname; + if (testname != NULL) + { + char *tmp = strdup(testname); + sbtest.sname = strdup(basename(tmp)); + sbtest.lname = tmp; + } + else + { + sbtest.sname = strdup(""); + sbtest.lname = NULL; + } /* Initialize global interpreter state */ gstate = sb_lua_new_state(-1); if (gstate == NULL) goto error; + if (read_option_defs(gstate)) + goto error; + /* Test commands */ if (func_available(gstate, PREPARE_FUNC)) sbtest.cmds.prepare = &sb_lua_cmd_prepare; @@ -225,8 +251,10 @@ sb_test_t *sb_load_lua(const char *testname) error: sb_lua_close_state(gstate); - if (states != NULL) - free(states); + xfree(states); + + xfree(sbtest.sname); + xfree(sbtest.lname); return NULL; } @@ -248,7 +276,7 @@ int sb_lua_op_init(void) if (!func_available(gstate, EVENT_FUNC)) { log_text(LOG_FATAL, "cannot find the event() function in %s", - sb_lua_script_path); + sbtest.sname); return 1; } @@ -325,8 +353,7 @@ void sb_lua_op_print_stats(sb_stat_t type) int sb_lua_op_done(void) { - if (states != NULL) - free(states); + xfree(states); lua_getglobal(gstate, DONE_FUNC); if (!lua_isnil(gstate, -1)) @@ -338,6 +365,23 @@ int sb_lua_op_done(void) } } + sb_lua_close_state(gstate); + + if (sbtest.args != NULL) + { + for (size_t i = 0; sbtest.args[i].name != NULL; i++) + { + xfree(sbtest.args[i].name); + xfree(sbtest.args[i].desc); + xfree(sbtest.args[i].value); + } + + free(sbtest.args); + } + + xfree(sbtest.sname); + xfree(sbtest.lname); + return 0; } @@ -450,12 +494,24 @@ static void sb_lua_set_paths(lua_State *L) } /* Export command line options */ + static int export_options(lua_State *L) { sb_list_item_t *pos; option_t *opt; char *tmp; + /* + Export options to the 'sysbench.opt' table, if the script declares supported + options with sysbench.option_defs, or to the global namespace otherwise + */ + if (sbtest.args != NULL) + { + lua_getglobal(L, "sysbench"); + lua_pushliteral(L, "opt"); + lua_newtable(L); + } + pos = sb_options_enum_start(); while ((pos = sb_options_enum_next(pos, &opt)) != NULL) { @@ -465,13 +521,20 @@ static int export_options(lua_State *L) which case name collisions with user-defined functions and variables might occur. For example, the --help option might redefine the help() function. */ - lua_getglobal(L, opt->name); - if (!lua_isnil(L, -1)) + if (sbtest.args == NULL) { + lua_getglobal(L, opt->name); + if (!lua_isnil(L, -1)) + { + lua_pop(L, 1); + continue; + } lua_pop(L, 1); - continue; } - lua_pop(L, 1); + else + { + lua_pushstring(L, opt->name); + } switch (opt->type) { @@ -481,8 +544,8 @@ static int export_options(lua_State *L) case SB_ARG_TYPE_INT: lua_pushnumber(L, sb_opt_to_int(opt)); break; - case SB_ARG_TYPE_FLOAT: - lua_pushnumber(L, sb_opt_to_float(opt)); + case SB_ARG_TYPE_DOUBLE: + lua_pushnumber(L, sb_opt_to_double(opt)); break; case SB_ARG_TYPE_SIZE: lua_pushnumber(L, sb_opt_to_size(opt)); @@ -492,11 +555,20 @@ static int export_options(lua_State *L) lua_pushstring(L, tmp ? tmp : ""); break; case SB_ARG_TYPE_LIST: - /*FIXME: should be exported as tables */ - lua_pushnil(L); + lua_newtable(L); + + sb_list_item_t *val; + int count = 1; + + SB_LIST_FOR_EACH(val, sb_opt_to_list(opt)) + { + lua_pushstring(L, SB_LIST_ENTRY(val, value_t, listitem)->data); + lua_rawseti(L, -2, count++); + } + break; case SB_ARG_TYPE_FILE: - /* FIXME: no need to export anything */ + /* no need to export anything */ lua_pushnil(L); break; default: @@ -506,15 +578,78 @@ static int export_options(lua_State *L) break; } - lua_setglobal(L, opt->name); + /* set var = value */ + if (sbtest.args != NULL) + lua_settable(L, -3); + else + lua_setglobal(L, opt->name); } + if (sbtest.args != NULL) + lua_settable(L, -3); /* set sysbench.opt */ + return 0; } +/* Create a deep copy of the 'args' array and set it to sbtest.args */ + +int sb_lua_set_test_args(sb_arg_t *args, size_t len) +{ + sbtest.args = malloc((len + 1) * sizeof(sb_arg_t)); + + for (size_t i = 0; i < len; i++) + { + sbtest.args[i].name = strdup(args[i].name); + sbtest.args[i].desc = strdup(args[i].desc); + sbtest.args[i].type = args[i].type; + + sbtest.args[i].value = args[i].value != NULL ? strdup(args[i].value) : NULL; + sbtest.args[i].validate = args[i].validate; + } + + sbtest.args[len] = (sb_arg_t) {.name = NULL}; + + return 0; +} + +/* + Parse command line options definitions, if present in the script as a + 'sysbench.option_defs' table. If there was a parsing error, return 1. Return 0 + on success. +*/ + +static int read_option_defs(lua_State *L) +{ + lua_getglobal(L, "sysbench"); + lua_getfield(L, -1, "cmdline"); + lua_getfield(L, -1, "read_option_defs"); + + if (!lua_isfunction(L, -1)) + { + log_text(LOG_WARNING, + "Cannot find the sysbench.cmdline.read_option_defs() function"); + lua_pop(L, 2); + + return 1; + } + + if (lua_pcall(L, 0, 1, 0) != 0) + { + call_error(L, "sysbench.cmdline.read_option_defs"); + lua_pop(L, 3); + return 1; + } + + int rc = lua_toboolean(L, -1) == 0; + + lua_pop(L, 4); + + return rc; +} + /* Allocate and initialize new interpreter state */ -lua_State *sb_lua_new_state(int thread_id) +static lua_State *sb_lua_new_state(int thread_id) { lua_State *L; @@ -577,7 +712,7 @@ lua_State *sb_lua_new_state(int thread_id) lua_pushliteral(L, "test"); lua_newtable(L); - sb_lua_var_string(L, "path", sb_lua_script_path); + sb_lua_var_string(L, "path", sbtest.lname); lua_settable(L, -3); /* sysbench.test */ @@ -591,7 +726,7 @@ lua_State *sb_lua_new_state(int thread_id) int rc; - if ((rc = luaL_loadfile(L, sb_lua_script_path))) + if ((rc = luaL_loadfile(L, sbtest.lname))) { lua_error(L); return NULL; @@ -642,6 +777,8 @@ static int execute_command(const char *cmd) return 1; } + lua_pop(gstate, 1); + return 0; } @@ -707,7 +844,7 @@ static void throw_restart_event(lua_State *L) { log_text(LOG_DEBUG, "Ignored error encountered, restarting transaction"); - lua_newtable(L); + lua_createtable(L, 0, 1); lua_pushliteral(L, "errcode"); lua_pushnumber(L, SB_LUA_ERROR_RESTART_EVENT); lua_settable(L, -3); diff --git a/sysbench/sb_options.c b/sysbench/sb_options.c index e0e0f2d..333f33e 100644 --- a/sysbench/sb_options.c +++ b/sysbench/sb_options.c @@ -66,7 +66,7 @@ static char *opt_formats[] = { "[=on|off]", /* SB_ARG_TYPE_FLAG */ "=N", /* SB_ARG_TYPE_INT */ "=SIZE", /* SB_ARG_TYPE_SIZE */ - "=N", /* SB_ARG_TYPE_FLOAT */ + "=N", /* SB_ARG_TYPE_DOUBLE */ "=STRING", /* SB_ARG_TYPE_STRING */ "=[LIST,...]", /* SB_ARG_TYPE_LIST */ "=FILENAME" /* SB_ARG_TYPE_FILE */ @@ -144,7 +144,7 @@ int set_option(const char *name, const char *value, sb_arg_type_t type) break; case SB_ARG_TYPE_INT: case SB_ARG_TYPE_SIZE: - case SB_ARG_TYPE_FLOAT: + case SB_ARG_TYPE_DOUBLE: case SB_ARG_TYPE_STRING: add_value(&opt->values, value); break; @@ -326,24 +326,23 @@ unsigned long long sb_get_value_size(const char *name) } -float sb_opt_to_float(option_t *opt) +double sb_opt_to_double(option_t *opt) { value_t *val; sb_list_item_t *pos; - float res; + double res; SB_LIST_FOR_EACH(pos, &opt->values) { val = SB_LIST_ENTRY(pos, value_t, listitem); - if (sscanf(val->data, "%f", &res) < 1) - res = 0; + res = strtod(val->data, NULL); } return res; } -float sb_get_value_float(const char *name) +double sb_get_value_double(const char *name) { option_t *opt; @@ -351,7 +350,7 @@ float sb_get_value_float(const char *name) if (opt == NULL) return 0; - return sb_opt_to_float(opt); + return sb_opt_to_double(opt); } diff --git a/sysbench/sb_options.h b/sysbench/sb_options.h index 76fafa9..0bd8be0 100644 --- a/sysbench/sb_options.h +++ b/sysbench/sb_options.h @@ -41,7 +41,7 @@ typedef enum SB_ARG_TYPE_BOOL, SB_ARG_TYPE_INT, SB_ARG_TYPE_SIZE, - SB_ARG_TYPE_FLOAT, + SB_ARG_TYPE_DOUBLE, SB_ARG_TYPE_STRING, SB_ARG_TYPE_LIST, SB_ARG_TYPE_FILE, @@ -56,8 +56,8 @@ typedef struct { const char *name; const char *desc; - sb_arg_type_t type; const char *value; + sb_arg_type_t type; sb_arg_validate_t *validate; } sb_arg_t; @@ -103,7 +103,7 @@ int sb_get_value_int(const char *name); unsigned long long sb_get_value_size(const char *name); -float sb_get_value_float(const char *name); +double sb_get_value_double(const char *name); char *sb_get_value_string(const char *name); @@ -117,7 +117,7 @@ int sb_opt_to_int(option_t *); unsigned long long sb_opt_to_size(option_t *); -float sb_opt_to_float(option_t *); +double sb_opt_to_double(option_t *); char *sb_opt_to_string(option_t *); diff --git a/sysbench/sb_rand.c b/sysbench/sb_rand.c index 2e6f071..d455c80 100644 --- a/sysbench/sb_rand.c +++ b/sysbench/sb_rand.c @@ -46,18 +46,23 @@ int sb_rand_seed; /* optional seed set on the command line */ static sb_arg_t rand_args[] = { - {"rand-type", "random numbers distribution {uniform,gaussian,special,pareto}", - SB_ARG_TYPE_STRING, "special"}, - {"rand-spec-iter", "number of iterations used for numbers generation", SB_ARG_TYPE_INT, "12"}, - {"rand-spec-pct", "percentage of values to be treated as 'special' (for special distribution)", - SB_ARG_TYPE_INT, "1"}, - {"rand-spec-res", "percentage of 'special' values to use (for special distribution)", - SB_ARG_TYPE_INT, "75"}, - {"rand-seed", "seed for random number generator. When 0, the current time is " - "used as a RNG seed.", SB_ARG_TYPE_INT, "0"}, - {"rand-pareto-h", "parameter h for pareto distibution", SB_ARG_TYPE_FLOAT, - "0.2"}, - {NULL, NULL, SB_ARG_TYPE_NULL, NULL} + SB_OPT("rand-type", + "random numbers distribution {uniform,gaussian,special,pareto}", + "special", STRING), + SB_OPT("rand-spec-iter", + "number of iterations used for numbers generation", "12", INT), + SB_OPT("rand-spec-pct", + "percentage of values to be treated as 'special' " + "(for special distribution)", "1", INT), + SB_OPT("rand-spec-res", + "percentage of 'special' values to use " + "(for special distribution)", "75", INT), + SB_OPT("rand-seed", + "seed for random number generator. When 0, the current time is " + "used as a RNG seed.", "0", INT), + SB_OPT("rand-pareto-h", "parameter h for pareto distibution", "0.2", DOUBLE), + + SB_OPT_END }; static rand_dist_t rand_type; @@ -143,7 +148,7 @@ int sb_rand_init(void) rand_res = sb_get_value_int("rand-spec-res"); rand_res_mult = 100.0 / (100.0 - rand_res); - pareto_h = sb_get_value_float("rand-pareto-h"); + pareto_h = sb_get_value_double("rand-pareto-h"); pareto_power = log(pareto_h) / log(1.0-pareto_h); /* Seed PRNG for the main thread. Worker thread do their own seeding */ diff --git a/sysbench/sysbench.c b/sysbench/sysbench.c index a58e382..f36932b 100644 --- a/sysbench/sysbench.c +++ b/sysbench/sysbench.c @@ -373,7 +373,10 @@ static int parse_test_arguments(sb_test_t *test, int argc, char *argv[]) latter case we just export all unrecognized options as strings. */ if (parse_option(argv[i]+2, test->args == NULL)) - return 1; + { + fprintf(stderr, "invalid option: %s\n", argv[i]); + return 1; + } argv[i] = NULL; } @@ -1250,7 +1253,12 @@ int main(int argc, char *argv[]) strerror(errno)); return EXIT_FAILURE; } - test = sb_load_lua(sb_globals.testname); + + if ((test = sb_load_lua(sb_globals.testname)) == NULL) + { + fprintf(stderr, "Script execution failed"); + return EXIT_FAILURE; + } if (sb_globals.cmdname == NULL) { diff --git a/sysbench/tests/fileio/sb_fileio.c b/sysbench/tests/fileio/sb_fileio.c index d2b47b9..0e06798 100644 --- a/sysbench/tests/fileio/sb_fileio.c +++ b/sysbench/tests/fileio/sb_fileio.c @@ -233,7 +233,7 @@ static sb_arg_t fileio_args[] = { "fsync", STRING), SB_OPT("file-merged-requests", "merge at most this number of IO requests " "if possible (0 - don't merge)", "0", INT), - SB_OPT("file-rw-ratio", "reads/writes ratio for combined test", "1.5", FLOAT), + SB_OPT("file-rw-ratio", "reads/writes ratio for combined test", "1.5", DOUBLE), SB_OPT_END }; @@ -1907,7 +1907,7 @@ int parse_arguments(void) return 1; } - file_rw_ratio = sb_get_value_float("file-rw-ratio"); + file_rw_ratio = sb_get_value_double("file-rw-ratio"); if (file_rw_ratio < 0) { log_text(LOG_FATAL, "Invalid value for --file-rw-ratio: %f.", file_rw_ratio); diff --git a/tests/t/api_basic.t b/tests/t/api_basic.t index 2c9c23b..aeec0cc 100644 --- a/tests/t/api_basic.t +++ b/tests/t/api_basic.t @@ -101,5 +101,5 @@ Error handling > end > EOF $ sysbench $SB_ARGS run - FATAL: cannot find the event() function in */api_basic.lua (glob) + FATAL: cannot find the event() function in *api_basic.lua (glob) [1] diff --git a/tests/t/cmdline.t b/tests/t/cmdline.t index 2298e51..4d62637 100644 --- a/tests/t/cmdline.t +++ b/tests/t/cmdline.t @@ -86,4 +86,124 @@ Threads fairness: events (avg/stddev): 1.0000/0.00 execution time (avg/stddev): 0.0000/0.00 - \ No newline at end of file + +######################################################################## +Command line options tests +######################################################################## + + $ cat >cmdline.lua < sysbench.option_defs = { + > str_opt1 = {"str_opt1 description"}, + > str_opt2 = {"str_opt2 description", "opt2"}, + > str_opt3 = {"str_opt3 description", "opt3", sysbench.cmdline.ARG_STRING}, + > bool_opt1 = {"bool_opt1 description", false}, + > bool_opt2 = {"bool_opt2 description", true}, + > bool_opt3 = {"bool_opt3 description", nil, sysbench.cmdline.ARG_BOOL}, + > int_opt1 = {"int_opt1 description", 10}, + > int_opt2 = {"int_opt2 description", nil, sysbench.cmdline.ARG_INT}, + > int_opt3 = {"int_opt3 description", 20, sysbench.cmdline.ARG_INT}, + > float_opt1 = {"float_opt1 description", 3.14, sysbench.cmdline.ARG_DOUBLE}, + > float_opt2 = {"float_opt2 description", 0.2}, + > list_opt1 = {"list_opt1 description", {"foo", "bar"}}, + > list_opt2 = {"list_opt2 description", nil, sysbench.cmdline.ARG_LIST}, + > ["dash-opt"] = {"dash-opt desc", "dash-opt val"} + > } + > + > function help() + > local o = sysbench.opt + > print(o.str_opt1) + > print(o.str_opt2) + > print(o.str_opt3) + > print(o.bool_opt1) + > print(o.bool_opt2) + > print(o.bool_opt3) + > print(o.int_opt1) + > print(o.int_opt2) + > print(o.float_opt1) + > print(o.float_opt2) + > print(o.list_opt1) + > print(o.list_opt2) + > print(o.dash_opt) + > end + > EOF + + $ sysbench cmdline.lua + sysbench * (glob) + + $ sysbench cmdline.lua help + sysbench * (glob) + + cmdline.lua options: + --dash-opt=STRING dash-opt desc [dash-opt val] + --str_opt1=STRING str_opt1 description + --bool_opt3[=on|off] bool_opt3 description + --int_opt2=N int_opt2 description + --list_opt2=[LIST,...] list_opt2 description + --float_opt2=N float_opt2 description [0.2] + --str_opt2=STRING str_opt2 description [opt2] + --list_opt1=[LIST,...] list_opt1 description [foo,bar] + --str_opt3=STRING str_opt3 description [opt3] + --int_opt3=N int_opt3 description [20] + --bool_opt1[=on|off] bool_opt1 description [off] + --float_opt1=N float_opt1 description [3.14] + --bool_opt2[=on|off] bool_opt2 description [on] + --int_opt1=N int_opt1 description [10] + + + opt2 + opt3 + false + true + true + 10 + 0 + 3.14 + 0.2 + table: 0x* (glob) + table: 0x* (glob) + dash-opt val + + $ sysbench cmdline.lua prepare + sysbench * (glob) + + 'cmdline.lua' test does not have the 'prepare' command. + [1] + + $ sysbench --non-existing-option=3 cmdline.lua prepare + sysbench * (glob) + + invalid option: --non-existing-option=3 + [1] + + $ sysbench cmdline.lua run + sysbench * (glob) + + FATAL: cannot find the event() function in cmdline.lua + [1] + + $ sysbench cmdline.lua cleanup + sysbench * (glob) + + 'cmdline.lua' test does not have the 'cleanup' command. + [1] + + $ cat >cmdline.lua < sysbench.option_defs = { + > {}, + > } + > + > function help() + > end + > EOF + $ sysbench cmdline.lua help + sysbench * (glob) + + FATAL: `sysbench.cmdline.read_option_defs' function failed: [string "sysbench.cmdline.lua"]:95: wrong table structure in sysbench.option_defs + Script execution failed (no-eol) + [1] + + $ sysbench fileio --invalid-option prepare + sysbench * (glob) + + invalid option: --invalid-option + [1]