From: Pasi Kallinen Date: Wed, 10 Feb 2021 17:15:35 +0000 (+0200) Subject: Add lua tests for config file parsing X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc25f40d69ec54d6b18f155a027be563f57c5a04;p=nethack Add lua tests for config file parsing Bare-bones for now, more tests needed. --- diff --git a/doc/lua.adoc b/doc/lua.adoc index fe650d45a..a6d41a340 100644 --- a/doc/lua.adoc +++ b/doc/lua.adoc @@ -171,12 +171,23 @@ Example: === parse_config Parse string as if it was read from a config file. +Always call parse_config_errors afterwards to check for any parsing errors. Example: nh.parse_config("OPTIONS=color"); +=== parse_config_errors + +Returns any errors found when parsing a config file string with parse_config. + +Example: + + local errors = nh.parse_config("OPTIONS=color\nOPTIONS=!color"); + nh.pline("Line: " .. errors[1].line .. ", " .. errors[1].error); + + === pline Show the text in the message area. diff --git a/include/extern.h b/include/extern.h index 9fe5f369d..5a7f11447 100644 --- a/include/extern.h +++ b/include/extern.h @@ -743,6 +743,9 @@ extern void makerogueghost(void); /* ### files.c ### */ +#if !defined(CROSSCOMPILE) || defined(CROSSCOMPILE_TARGET) +extern int l_get_config_errors(lua_State *); +#endif extern char *fname_encode(const char *, char, char *, char *, int); extern char *fname_decode(char, char *, char *, int); extern const char *fqname(const char *, int, int); diff --git a/src/files.c b/src/files.c index d6db62293..c488ae93c 100644 --- a/src/files.c +++ b/src/files.c @@ -2798,6 +2798,12 @@ can_read_file(const char *filename) } #endif /* USER_SOUNDS */ +struct _config_error_errmsg { + int line_num; + char *errormsg; + struct _config_error_errmsg *next; +}; + struct _config_error_frame { int line_num; int num_errors; @@ -2810,6 +2816,7 @@ struct _config_error_frame { }; static struct _config_error_frame *config_error_data = 0; +static struct _config_error_errmsg *config_error_msg = 0; void config_error_init(boolean from_file, const char *sourcename, boolean secure) @@ -2856,6 +2863,32 @@ config_error_nextline(const char *line) return TRUE; } +int +l_get_config_errors(lua_State *L) +{ + struct _config_error_errmsg *dat = config_error_msg; + struct _config_error_errmsg *tmp; + int idx = 1; + + lua_newtable(L); + + while (dat) { + lua_pushinteger(L, idx++); + lua_newtable(L); + nhl_add_table_entry_int(L, "line", dat->line_num); + nhl_add_table_entry_str(L, "error", dat->errormsg); + lua_settable(L, -3); + tmp = dat->next; + free(dat->errormsg); + dat->errormsg = (char *) 0; + free(dat); + dat = tmp; + } + config_error_msg = (struct _config_error_errmsg *) 0; + + return 1; +} + /* varargs 'config_error_add()' moved to pline.c */ void config_erradd(const char *buf) @@ -2865,6 +2898,16 @@ config_erradd(const char *buf) if (!buf || !*buf) buf = "Unknown error"; + if (iflags.in_lua) { + struct _config_error_errmsg *dat = (struct _config_error_errmsg *) alloc(sizeof (struct _config_error_errmsg)); + + dat->next = config_error_msg; + dat->line_num = config_error_data->line_num; + dat->errormsg = dupstr(buf); + config_error_msg = dat; + return; + } + if (!config_error_data) { /* either very early, where pline() will use raw_print(), or player gave bad value when prompted by interactive 'O' command */ diff --git a/src/nhlua.c b/src/nhlua.c index e92aed64b..e89d9889e 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -830,6 +830,7 @@ static const struct luaL_Reg nhl_functions[] = { {"level_difficulty", nhl_level_difficulty}, {"parse_config", nhl_parse_config}, {"get_config", nhl_get_config}, + {"get_config_errors", l_get_config_errors}, {NULL, NULL} }; diff --git a/test/test_cnf.lua b/test/test_cnf.lua new file mode 100644 index 000000000..8efdf5553 --- /dev/null +++ b/test/test_cnf.lua @@ -0,0 +1,49 @@ + +local configtests = { + { test = "OPTIONS=color", -- config string to parse + result = { }, -- errors, result of parsing the config string + extra = function() return nh.get_config("color") == "true" end -- optional, function that returns boolean, and false means the test failed. + }, + { test = "OPTIONS=!color", + result = { }, + extra = function() return nh.get_config("color") == "false" end + }, + { test = "OPTIONS=!color\nOPTIONS=color", + result = { { line = 2, error = "boolean option specified multiple times: color" } } + }, +}; + + +function testtable(t1, t2) + if type(t1) ~= type(t2) then return false end + + for k1, v1 in pairs(t1) do + if type(v1) == "table" and type(t2[k1]) == "table" then + if not testtable(v1, t2[k1]) then return false end + else + if v1 ~= t2[k1] then return false end + end + end + + return true +end + + + +for k, v in pairs(configtests) do + local cnf = configtests[k].test; + local err = configtests[k].result; + nh.parse_config(cnf); + local res = nh.get_config_errors(); + + if not testtable(err, res) then + error("Config: Results don't match"); + end + + if (type(configtests[k].extra) == "function") then + if configtests[k].extra() == "false" then + error("Config: Failed extra test."); + end + end + +end