diff options
| author | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2025-09-16 20:38:59 +0300 | 
|---|---|---|
| committer | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2025-09-16 20:38:59 +0300 | 
| commit | 5556ee3afa4dc015a73bff7bcddd65d14c6a57c6 (patch) | |
| tree | 0bad83a6eeeb621059e5506774e677953d19031c | |
| parent | 9e7132fff6d905e43955803892046e0a0b1dd8fb (diff) | |
| download | c-wares-5556ee3afa4dc015a73bff7bcddd65d14c6a57c6.tar.gz c-wares-5556ee3afa4dc015a73bff7bcddd65d14c6a57c6.zip  | |
cli: make long and ulong options more strict
Also add unit tests for them.
| -rw-r--r-- | cli/cli-test.c | 51 | ||||
| -rw-r--r-- | cli/cli.h | 10 | 
2 files changed, 57 insertions, 4 deletions
diff --git a/cli/cli-test.c b/cli/cli-test.c index c1d7591..0a52782 100644 --- a/cli/cli-test.c +++ b/cli/cli-test.c @@ -76,6 +76,55 @@ TEST_BEGIN(test_cli_opt_data_size_set)  }  TEST_END +TEST_BEGIN(test_cli_opt_long_set) +{ +	CLI_OPT_LONG(opt, 0, NULL, NULL); +	struct tcase { +		const char *input; +		long        expected_val; +		enum cli_rc expected_rc; +	} cases[] = { +		{"420", 420, CLI_RC_OK}, +		{"4K", 0, CLI_RC_BAD_ARGS}, +		{"-6", -6, CLI_RC_OK}, +		{"0.2", 0, CLI_RC_BAD_ARGS}, +	}; +	for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { +		opt.value = 0; +		int rc    = opt.opt.set(&opt.opt, cases[i].input); +		asserteq(rc, cases[i].expected_rc); +		if (rc == CLI_RC_OK) +			asserteq(opt.value, cases[i].expected_val); +	} +	TEST_OUT +} +TEST_END + +TEST_BEGIN(test_cli_opt_ulong_set) +{ +	CLI_OPT_ULONG(opt, 0, NULL, NULL); +	struct tcase { +		const char   *input; +		unsigned long expected_val; +		enum cli_rc   expected_rc; +	} cases[] = { +		{"420", 420, CLI_RC_OK}, +		{"4K", 0, CLI_RC_BAD_ARGS}, +		{"-6", -6, CLI_RC_OK},  // C typing discipline really is this bad +		{"0.2", 0, CLI_RC_BAD_ARGS}, +		{"0xB00B5", 0xB00B5, CLI_RC_OK}, +	}; +	for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { +		opt.value = 0; +		int rc    = opt.opt.set(&opt.opt, cases[i].input); +		asserteq(rc, cases[i].expected_rc); +		if (rc == CLI_RC_OK) +			asserteq(opt.value, cases[i].expected_val); +	} +	TEST_OUT +} +TEST_END +  TEST_BEGIN(test_parse_long)  {  	struct tcase { @@ -470,6 +519,8 @@ TEST_BEGIN(test_parse_options)  TEST_END  RUN_TESTS(test_cli_opt_data_size_set, +          test_cli_opt_long_set, +          test_cli_opt_ulong_set,            test_parse_long,            test_parse_short,            test_parse_options) @@ -104,8 +104,9 @@ int cli_opt_long_set(struct cli_opt *self, const char *val)  	struct cli_opt_long *opt = container_of(self, struct cli_opt_long, opt);  	errno      = 0; -	opt->value = strtol(val, NULL, 0); -	if (errno != 0) +	char *endptr; +	opt->value = strtol(val, &endptr, 0); +	if (errno != 0 || *endptr != '\0')  		return CLI_RC_BAD_ARGS;  	return CLI_RC_OK; @@ -133,8 +134,9 @@ int cli_opt_ulong_set(struct cli_opt *self, const char *val)  	struct cli_opt_ulong *opt = container_of(self, struct cli_opt_ulong, opt);  	errno      = 0; -	opt->value = strtoul(val, NULL, 0); -	if (errno != 0) +	char *endptr; +	opt->value = strtoul(val, &endptr, 0); +	if (errno != 0 || *endptr != '\0')  		return CLI_RC_BAD_ARGS;  	return CLI_RC_OK;  | 
