From: Martin Mares Date: Tue, 3 Sep 2013 13:31:19 +0000 (+0200) Subject: Opt: Tests split off to a separate file X-Git-Tag: v5.99~25^2~41 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=9d24e18d51c569cd2cdfb61270d98af13ccfb21c;p=libucw.git Opt: Tests split off to a separate file --- diff --git a/ucw/Makefile b/ucw/Makefile index 11aabfa9..ece9b9a8 100644 --- a/ucw/Makefile +++ b/ucw/Makefile @@ -115,6 +115,7 @@ $(o)/ucw/kmp-test: $(LIBCHARSET) endif $(o)/ucw/ipaccess-test: $(o)/ucw/ipaccess-test.o $(LIBUCW) $(o)/ucw/trie-test: $(o)/ucw/trie-test.o $(LIBUCW) +$(o)/ucw/opt-test: $(o)/ucw/opt-test.o $(LIBUCW) TESTS+=$(addprefix $(o)/ucw/,regex.test unicode.test hash-test.test mempool.test stkstring.test \ slists.test bbuf.test kmp-test.test getopt.test ff-unicode.test eltpool.test \ @@ -152,7 +153,7 @@ $(o)/ucw/time.test: $(o)/ucw/time-conf-t $(o)/ucw/crc.test: $(o)/ucw/crc-t $(o)/ucw/signames.test: $(o)/ucw/signames-t $(o)/ucw/md5.test: $(o)/ucw/md5-t -$(o)/ucw/opt.test: $(o)/ucw/opt-t +$(o)/ucw/opt.test: $(o)/ucw/opt-test ifdef CONFIG_UCW_THREADS TESTS+=$(addprefix $(o)/ucw/,asio.test) diff --git a/ucw/opt-test.c b/ucw/opt-test.c new file mode 100644 index 00000000..7de4767c --- /dev/null +++ b/ucw/opt-test.c @@ -0,0 +1,185 @@ +/* + * UCW Library -- Parsing of command line options + * + * (c) 2013 Jan Moskyto Matejka + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. + */ + +#include +#include +#include +#include + +static void show_version(struct opt_item * opt UNUSED, const char * value UNUSED, void * data UNUSED) { + printf("This is a simple tea boiling console v0.1.\n"); + exit(EXIT_SUCCESS); +} + +struct teapot_temperature { + enum { + TEMP_CELSIUS = 0, + TEMP_FAHRENHEIT, + TEMP_KELVIN, + TEMP_REAUMUR, + TEMP_RANKINE + } scale; + int value; +} temperature; + +static char * temp_scale_str[] = { "C", "F", "K", "Re", "R" }; + +static enum TEAPOT_TYPE { + TEAPOT_STANDARD = 0, + TEAPOT_EXCLUSIVE, + TEAPOT_GLASS, + TEAPOT_HANDS, + TEAPOT_UNDEFINED = -1 +} set = TEAPOT_UNDEFINED; + +static char * teapot_type_str[] = { "standard", "exclusive", "glass", "hands" }; + +static int show_hooks = 0; +static int english = 0; +static int sugar = 0; +static int verbose = 1; +static int with_gas = 0; +static clist black_magic; +static int pray = 0; +static int water_amount = 0; +static char * first_tea = NULL; + +#define MAX_TEA_COUNT 30 +static char * tea_list[MAX_TEA_COUNT]; +static int tea_num = 0; +static void add_tea(struct opt_item * opt UNUSED, const char * name, void * data) { + char ** tea_list = data; + if (tea_num >= MAX_TEA_COUNT) { + fprintf(stderr, "Cannot boil more than %d teas.\n", MAX_TEA_COUNT); + exit(OPT_EXIT_BAD_ARGS); + } + tea_list[tea_num++] = xstrdup(name); +} + +static const char * teapot_temperature_parser(char * in, void * ptr) { + struct teapot_temperature * temp = ptr; + const char * next; + const char * err = str_to_int(&temp->value, in, &next, 10); + if (err) + return err; + if (!strcmp("C", next)) + temp->scale = TEMP_CELSIUS; + else if (!strcmp("F", next)) + temp->scale = TEMP_FAHRENHEIT; + else if (!strcmp("K", next)) + temp->scale = TEMP_KELVIN; + else if (!strcmp("R", next)) + temp->scale = TEMP_RANKINE; + else if (!strcmp("Re", next)) + temp->scale = TEMP_REAUMUR; + else { + fprintf(stderr, "Unknown scale: %s\n", next); + exit(OPT_EXIT_BAD_ARGS); + } + return NULL; +} + +static void teapot_temperature_dumper(struct fastbuf * fb, void * ptr) { + struct teapot_temperature * temp = ptr; + bprintf(fb, "%d%s", temp->value, temp_scale_str[temp->scale]); +} + +static struct cf_user_type teapot_temperature_t = { + .size = sizeof(struct teapot_temperature), + .name = "teapot_temperature_t", + .parser = (cf_parser1*) teapot_temperature_parser, + .dumper = (cf_dumper1*) teapot_temperature_dumper +}; + +static void opt_test_hook(struct opt_item * opt, const char * value, void * data) { + if (!show_hooks) + return; + if (opt) + printf("[HOOK-%s:%c/%s=%s] ", (char *) data, opt->letter, opt->name, value); + else + printf("[HOOK-%s] ", (char *) data); +} + +static struct opt_section water_options = { + OPT_ITEMS { + OPT_INT('w', "water", water_amount, OPT_REQUIRED | OPT_REQUIRED_VALUE, "\tAmount of water (in mls; required)"), + OPT_BOOL('G', "with-gas", with_gas, OPT_NO_VALUE, "\tUse water with gas"), + OPT_END + } +}; + +static struct opt_section help = { + OPT_ITEMS { + OPT_HELP("A simple tea boiling console."), + OPT_HELP("Usage: teapot [options] name-of-the-tea"), + OPT_HELP("Black, green or white tea supported as well as fruit or herbal tea."), + OPT_HELP("You may specify more kinds of tea, all of them will be boiled for you, in the given order."), + OPT_HELP("At least one kind of tea must be specified."), + OPT_HELP(""), + OPT_HELP("Options:"), + OPT_HELP_OPTION, + OPT_CALL('V', "version", show_version, NULL, OPT_NO_VALUE, "\tShow the version"), + OPT_HELP(""), + OPT_BOOL('e', "english-style", english, 0, "\tEnglish style (with milk)"), + OPT_INT('s', "sugar", sugar, OPT_REQUIRED_VALUE, "\tAmount of sugar (in teaspoons)"), + OPT_SWITCH(0, "standard-set", set, TEAPOT_STANDARD, 0, "\tStandard teapot"), + OPT_SWITCH('x', "exclusive-set", set, TEAPOT_EXCLUSIVE, 0, "\tExclusive teapot"), + OPT_SWITCH('g', "glass-set", set, TEAPOT_GLASS, 0, "\tTransparent glass teapot"), + OPT_SWITCH('h', "hands", set, TEAPOT_HANDS, 0, "\tUse user's hands as a teapot (a bit dangerous)"), + OPT_USER('t', "temperature", temperature, teapot_temperature_t, OPT_REQUIRED_VALUE | OPT_REQUIRED, + "\tWanted final temperature of the tea to be served (required)\n" + "\t\tSupported scales: Celsius [60C], Fahrenheit [140F],\n" + "\t\t Kelvin [350K], Rankine [600R] and Reaumur [50Re]\n" + "\t\tOnly integer values allowed."), + OPT_INC('v', "verbose", verbose, 0, "\tVerbose (the more -v, the more verbose)"), + OPT_INC('q', "quiet", verbose, OPT_NEGATIVE, "\tQuiet (the more -q, the more quiet)"), + OPT_INT('b', "black-magic", black_magic, OPT_MULTIPLE, "\tUse black magic to make the tea extraordinary delicious.\n\t\tMay be specified more than once to describe the amounts of black magic to be invoked in each step of tea boiling."), + OPT_BOOL('p', "pray", pray, OPT_SINGLE, "\tPray before boiling"), + OPT_STRING(OPT_POSITIONAL(1), NULL, first_tea, OPT_REQUIRED | OPT_NO_HELP, ""), + OPT_CALL(OPT_POSITIONAL_TAIL, NULL, add_tea, &tea_list, OPT_NO_HELP, ""), + OPT_HELP(""), + OPT_HELP("Water options:"), + OPT_SECTION(water_options), + OPT_HOOK(opt_test_hook, "prearg", OPT_HOOK_BEFORE_ARG), + OPT_HOOK(opt_test_hook, "preval", OPT_HOOK_BEFORE_VALUE), + OPT_HOOK(opt_test_hook, "postval", OPT_HOOK_AFTER_VALUE), + OPT_BOOL('H', "show-hooks", show_hooks, 0, "Demonstrate the hooks."), + OPT_CONF_OPTIONS, + OPT_END + } +}; + +struct intnode { + cnode n; + int x; +}; + +int main(int argc UNUSED, char ** argv) +{ + clist_init(&black_magic); + opt_parse(&help, argv+1); + + printf("English style: %s|", english ? "yes" : "no"); + if (sugar) + printf("Sugar: %d teaspoons|", sugar); + if (set != -1) + printf("Chosen teapot: %s|", teapot_type_str[set]); + printf("Temperature: %d%s|", temperature.value, temp_scale_str[temperature.scale]); + printf("Verbosity: %d|", verbose); + CLIST_FOR_EACH(struct intnode *, n, black_magic) + printf("Black magic: %d|", n->x); + printf("Prayer: %s|", pray ? "yes" : "no"); + printf("Water amount: %d|", water_amount); + printf("Gas: %s|", with_gas ? "yes" : "no"); + printf("First tea: %s|", first_tea); + for (int i=0; i - -static void show_version(struct opt_item * opt UNUSED, const char * value UNUSED, void * data UNUSED) { - printf("This is a simple tea boiling console v0.1.\n"); - exit(EXIT_SUCCESS); -} - -struct teapot_temperature { - enum { - TEMP_CELSIUS = 0, - TEMP_FAHRENHEIT, - TEMP_KELVIN, - TEMP_REAUMUR, - TEMP_RANKINE - } scale; - int value; -} temperature; - -static char * temp_scale_str[] = { "C", "F", "K", "Re", "R" }; - -static enum TEAPOT_TYPE { - TEAPOT_STANDARD = 0, - TEAPOT_EXCLUSIVE, - TEAPOT_GLASS, - TEAPOT_HANDS, - TEAPOT_UNDEFINED = -1 -} set = TEAPOT_UNDEFINED; - -static char * teapot_type_str[] = { "standard", "exclusive", "glass", "hands" }; - -static int show_hooks = 0; -static int english = 0; -static int sugar = 0; -static int verbose = 1; -static int with_gas = 0; -static clist black_magic; -static int pray = 0; -static int water_amount = 0; -static char * first_tea = NULL; - -#define MAX_TEA_COUNT 30 -static char * tea_list[MAX_TEA_COUNT]; -static int tea_num = 0; -static void add_tea(struct opt_item * opt UNUSED, const char * name, void * data) { - char ** tea_list = data; - if (tea_num >= MAX_TEA_COUNT) { - fprintf(stderr, "Cannot boil more than %d teas.\n", MAX_TEA_COUNT); - exit(OPT_EXIT_BAD_ARGS); - } - tea_list[tea_num++] = xstrdup(name); -} - -static const char * teapot_temperature_parser(char * in, void * ptr) { - struct teapot_temperature * temp = ptr; - const char * next; - const char * err = str_to_int(&temp->value, in, &next, 10); - if (err) - return err; - if (!strcmp("C", next)) - temp->scale = TEMP_CELSIUS; - else if (!strcmp("F", next)) - temp->scale = TEMP_FAHRENHEIT; - else if (!strcmp("K", next)) - temp->scale = TEMP_KELVIN; - else if (!strcmp("R", next)) - temp->scale = TEMP_RANKINE; - else if (!strcmp("Re", next)) - temp->scale = TEMP_REAUMUR; - else { - fprintf(stderr, "Unknown scale: %s\n", next); - exit(OPT_EXIT_BAD_ARGS); - } - return NULL; -} - -static void teapot_temperature_dumper(struct fastbuf * fb, void * ptr) { - struct teapot_temperature * temp = ptr; - bprintf(fb, "%d%s", temp->value, temp_scale_str[temp->scale]); -} - -static struct cf_user_type teapot_temperature_t = { - .size = sizeof(struct teapot_temperature), - .name = "teapot_temperature_t", - .parser = (cf_parser1*) teapot_temperature_parser, - .dumper = (cf_dumper1*) teapot_temperature_dumper -}; - -static void opt_test_hook(struct opt_item * opt, const char * value, void * data) { - if (!show_hooks) - return; - if (opt) - printf("[HOOK-%s:%c/%s=%s] ", (char *) data, opt->letter, opt->name, value); - else - printf("[HOOK-%s] ", (char *) data); -} - -static struct opt_section water_options = { - OPT_ITEMS { - OPT_INT('w', "water", water_amount, OPT_REQUIRED | OPT_REQUIRED_VALUE, "\tAmount of water (in mls; required)"), - OPT_BOOL('G', "with-gas", with_gas, OPT_NO_VALUE, "\tUse water with gas"), - OPT_END - } -}; - -static struct opt_section help = { - OPT_ITEMS { - OPT_HELP("A simple tea boiling console."), - OPT_HELP("Usage: teapot [options] name-of-the-tea"), - OPT_HELP("Black, green or white tea supported as well as fruit or herbal tea."), - OPT_HELP("You may specify more kinds of tea, all of them will be boiled for you, in the given order."), - OPT_HELP("At least one kind of tea must be specified."), - OPT_HELP(""), - OPT_HELP("Options:"), - OPT_HELP_OPTION, - OPT_CALL('V', "version", show_version, NULL, OPT_NO_VALUE, "\tShow the version"), - OPT_HELP(""), - OPT_BOOL('e', "english-style", english, 0, "\tEnglish style (with milk)"), - OPT_INT('s', "sugar", sugar, OPT_REQUIRED_VALUE, "\tAmount of sugar (in teaspoons)"), - OPT_SWITCH(0, "standard-set", set, TEAPOT_STANDARD, 0, "\tStandard teapot"), - OPT_SWITCH('x', "exclusive-set", set, TEAPOT_EXCLUSIVE, 0, "\tExclusive teapot"), - OPT_SWITCH('g', "glass-set", set, TEAPOT_GLASS, 0, "\tTransparent glass teapot"), - OPT_SWITCH('h', "hands", set, TEAPOT_HANDS, 0, "\tUse user's hands as a teapot (a bit dangerous)"), - OPT_USER('t', "temperature", temperature, teapot_temperature_t, OPT_REQUIRED_VALUE | OPT_REQUIRED, - "\tWanted final temperature of the tea to be served (required)\n" - "\t\tSupported scales: Celsius [60C], Fahrenheit [140F],\n" - "\t\t Kelvin [350K], Rankine [600R] and Reaumur [50Re]\n" - "\t\tOnly integer values allowed."), - OPT_INC('v', "verbose", verbose, 0, "\tVerbose (the more -v, the more verbose)"), - OPT_INC('q', "quiet", verbose, OPT_NEGATIVE, "\tQuiet (the more -q, the more quiet)"), - OPT_INT('b', "black-magic", black_magic, OPT_MULTIPLE, "\tUse black magic to make the tea extraordinary delicious.\n\t\tMay be specified more than once to describe the amounts of black magic to be invoked in each step of tea boiling."), - OPT_BOOL('p', "pray", pray, OPT_SINGLE, "\tPray before boiling"), - OPT_STRING(OPT_POSITIONAL(1), NULL, first_tea, OPT_REQUIRED | OPT_NO_HELP, ""), - OPT_CALL(OPT_POSITIONAL_TAIL, NULL, add_tea, &tea_list, OPT_NO_HELP, ""), - OPT_HELP(""), - OPT_HELP("Water options:"), - OPT_SECTION(water_options), - OPT_HOOK(opt_test_hook, "prearg", OPT_HOOK_BEFORE_ARG), - OPT_HOOK(opt_test_hook, "preval", OPT_HOOK_BEFORE_VALUE), - OPT_HOOK(opt_test_hook, "postval", OPT_HOOK_AFTER_VALUE), - OPT_BOOL('H', "show-hooks", show_hooks, 0, "Demonstrate the hooks."), - OPT_CONF_OPTIONS, - OPT_END - } -}; - -struct intnode { - cnode n; - int x; -}; - -int main(int argc UNUSED, char ** argv) -{ - clist_init(&black_magic); - opt_parse(&help, argv+1); - - printf("English style: %s|", english ? "yes" : "no"); - if (sugar) - printf("Sugar: %d teaspoons|", sugar); - if (set != -1) - printf("Chosen teapot: %s|", teapot_type_str[set]); - printf("Temperature: %d%s|", temperature.value, temp_scale_str[temperature.scale]); - printf("Verbosity: %d|", verbose); - CLIST_FOR_EACH(struct intnode *, n, black_magic) - printf("Black magic: %d|", n->x); - printf("Prayer: %s|", pray ? "yes" : "no"); - printf("Water amount: %d|", water_amount); - printf("Gas: %s|", with_gas ? "yes" : "no"); - printf("First tea: %s|", first_tea); - for (int i=0; i&1 1>/dev/null || [ $? -eq "2" ] ) | tr -d '\n' +Run: ( ../obj/ucw/opt-test 2>&1 1>/dev/null || [ $? -eq "2" ] ) | tr -d '\n' Out: Required option -t not found.Run with argument --help for more information. Name: Opt-2 -Run: ../obj/ucw/opt-t -t95C -w640 -gG darjeeling +Run: ../obj/ucw/opt-test -t95C -w640 -gG darjeeling Out: English style: no|Chosen teapot: glass|Temperature: 95C|Verbosity: 1|Prayer: no|Water amount: 640|Gas: yes|First tea: darjeeling|Everything OK. Bye. Name: Opt-3 -Run: ../obj/ucw/opt-t -vvqvqvhpe -t120F -w4 darjeeling +Run: ../obj/ucw/opt-test -vvqvqvhpe -t120F -w4 darjeeling Out: English style: yes|Chosen teapot: hands|Temperature: 120F|Verbosity: 3|Prayer: yes|Water amount: 4|Gas: no|First tea: darjeeling|Everything OK. Bye. Name: Opt-4 -Run: ../obj/ucw/opt-t -t120F -w4 puerh darjeeling earl-gray +Run: ../obj/ucw/opt-test -t120F -w4 puerh darjeeling earl-gray Out: English style: no|Temperature: 120F|Verbosity: 1|Prayer: no|Water amount: 4|Gas: no|First tea: puerh|Boiling a tea: darjeeling|Boiling a tea: earl-gray|Everything OK. Bye. Name: Opt-5 -Run: ( ../obj/ucw/opt-t -ghx 2>&1 1>/dev/null || [ $? -eq "2" ] ) | tr -d '\n' +Run: ( ../obj/ucw/opt-test -ghx 2>&1 1>/dev/null || [ $? -eq "2" ] ) | tr -d '\n' Out: Multiple switches: -hRun with argument --help for more information. Name: Opt-6 -Run: ../obj/ucw/opt-t -t120F -w4 -b15 -he -- --puerh darjeeling earl-gray +Run: ../obj/ucw/opt-test -t120F -w4 -b15 -he -- --puerh darjeeling earl-gray Out: English style: yes|Chosen teapot: hands|Temperature: 120F|Verbosity: 1|Black magic: 15|Prayer: no|Water amount: 4|Gas: no|First tea: --puerh|Boiling a tea: darjeeling|Boiling a tea: earl-gray|Everything OK. Bye. Name: Opt-7 -Run: ../obj/ucw/opt-t -t120F -w4 -b15 -b54 -he -- --puerh darjeeling earl-gray +Run: ../obj/ucw/opt-test -t120F -w4 -b15 -b54 -he -- --puerh darjeeling earl-gray Out: English style: yes|Chosen teapot: hands|Temperature: 120F|Verbosity: 1|Black magic: 15|Black magic: 54|Prayer: no|Water amount: 4|Gas: no|First tea: --puerh|Boiling a tea: darjeeling|Boiling a tea: earl-gray|Everything OK. Bye. Name: Opt-Conf-1 -Run: ( ../obj/ucw/opt-t -h --dumpconfig 2>&1 1>/dev/null || [ $? -eq "2" ] ) | tr -d '\n' +Run: ( ../obj/ucw/opt-test -h --dumpconfig 2>&1 1>/dev/null || [ $? -eq "2" ] ) | tr -d '\n' Out: Config options (-C, -S) must stand before other options.Run with argument --help for more information. Name: Opt-Hook-1 -Run: ../obj/ucw/opt-t -Ht 95C -w640 -gG darjeeling +Run: ../obj/ucw/opt-test -Ht 95C -w640 -gG darjeeling Out: [HOOK-postval:H/show-hooks=(null)] [HOOK-preval:t/temperature=95C] [HOOK-postval:t/temperature=95C] [HOOK-prearg] [HOOK-preval:w/water=640] [HOOK-postval:w/water=640] [HOOK-prearg] [HOOK-preval:g/glass-set=(null)] [HOOK-postval:g/glass-set=(null)] [HOOK-preval:G/with-gas=(null)] [HOOK-postval:G/with-gas=(null)] [HOOK-prearg] [HOOK-preval:/(null)=darjeeling] [HOOK-postval:/(null)=darjeeling] English style: no|Chosen teapot: glass|Temperature: 95C|Verbosity: 1|Prayer: no|Water amount: 640|Gas: yes|First tea: darjeeling|Everything OK. Bye.