2020-12-01 14:55:16 -05:00
|
|
|
#include <kernaux/cmdline.h>
|
|
|
|
|
2020-12-01 15:22:38 -05:00
|
|
|
#include <assert.h>
|
2020-12-01 16:40:41 -05:00
|
|
|
#include <stdbool.h>
|
2020-12-01 15:29:45 -05:00
|
|
|
#include <string.h>
|
2020-12-01 15:22:38 -05:00
|
|
|
|
2020-12-01 16:34:46 -05:00
|
|
|
static const unsigned int ARGV_COUNT_MAX = 100;
|
2020-12-01 15:22:38 -05:00
|
|
|
static const unsigned int ARG_SIZE_MAX = 4096;
|
|
|
|
|
2020-12-01 16:34:46 -05:00
|
|
|
static void test(
|
|
|
|
const char *cmdline,
|
|
|
|
unsigned int argv_count_max,
|
|
|
|
unsigned int arg_size_max,
|
2020-12-01 15:22:38 -05:00
|
|
|
|
2020-12-01 16:40:41 -05:00
|
|
|
bool expected_result,
|
2020-12-01 16:34:46 -05:00
|
|
|
const char *expected_error_msg,
|
|
|
|
unsigned int expected_argc,
|
|
|
|
const char *const *const expected_argv
|
|
|
|
);
|
2020-12-01 15:32:35 -05:00
|
|
|
|
2020-12-01 16:34:46 -05:00
|
|
|
static const char *const argv0[] = {};
|
2020-12-01 15:22:38 -05:00
|
|
|
|
2020-12-01 16:34:46 -05:00
|
|
|
static const char *const argv_foo[] = {"foo"};
|
2020-12-01 15:29:45 -05:00
|
|
|
|
2020-12-01 16:34:46 -05:00
|
|
|
static const char *const argv_foo_bar[] = {"foo", "bar"};
|
2020-12-01 15:32:35 -05:00
|
|
|
|
2020-12-01 16:34:46 -05:00
|
|
|
static const char *const argv_foo_bar_car[] = {"foo", "bar", "car"};
|
2020-12-01 15:32:35 -05:00
|
|
|
|
2020-12-05 17:31:15 -05:00
|
|
|
static const char *const argv_space[] = {" "};
|
|
|
|
|
|
|
|
static const char *const argv_backslash[] = {"\\"};
|
|
|
|
|
|
|
|
static const char *const argv_foospace[] = {"foo "};
|
|
|
|
|
|
|
|
static const char *const argv_foobackslash[] = {"foo\\"};
|
|
|
|
|
|
|
|
static const char *const argv_spacefoo[] = {" foo"};
|
|
|
|
|
|
|
|
static const char *const argv_backslashfoo[] = {"\\foo"};
|
|
|
|
|
|
|
|
static const char *const argv_spacefoospace[] = {" foo "};
|
|
|
|
|
|
|
|
static const char *const argv_backslashfoobackslash[] = {"\\foo\\"};
|
|
|
|
|
|
|
|
static const char *const argv_foospacebar[] = {"foo bar"};
|
|
|
|
|
|
|
|
static const char *const argv_foobackslashbar[] = {"foo\\bar"};
|
|
|
|
|
|
|
|
static const char *const argv_spaceX3_X3[] = {" ", " ", " "};
|
|
|
|
|
|
|
|
static const char *const argv_backslashX3_X3[] = {"\\\\\\", "\\\\\\", "\\\\\\"};
|
|
|
|
|
|
|
|
static const char *const argv_spacefoo_bar[] = {" foo", "bar"};
|
|
|
|
|
|
|
|
static const char *const argv_backslashfoo_bar[] = {"\\foo", "bar"};
|
|
|
|
|
|
|
|
static const char *const argv_foospace_bar[] = {"foo ", "bar"};
|
|
|
|
|
|
|
|
static const char *const argv_foobackslash_bar[] = {"foo\\", "bar"};
|
|
|
|
|
|
|
|
static const char *const argv_spacefoospace_bar[] = {" foo ", "bar"};
|
|
|
|
|
|
|
|
static const char *const argv_backslashfoobackslash_bar[] = {"\\foo\\", "bar"};
|
|
|
|
|
|
|
|
static const char *const argv_foo_spacebar[] = {"foo", " bar"};
|
|
|
|
|
|
|
|
static const char *const argv_foo_backslashbar[] = {"foo", "\\bar"};
|
|
|
|
|
|
|
|
static const char *const argv_foo_barspace[] = {"foo", "bar "};
|
|
|
|
|
|
|
|
static const char *const argv_foo_barbackslash[] = {"foo", "bar\\"};
|
|
|
|
|
|
|
|
static const char *const argv_foo_spacebarspace[] = {"foo", " bar "};
|
|
|
|
|
|
|
|
static const char *const argv_foo_backslashbarbackslash[] = {"foo", "\\bar\\"};
|
|
|
|
|
2020-12-01 16:34:46 -05:00
|
|
|
int main()
|
|
|
|
{
|
2020-12-05 17:41:22 -05:00
|
|
|
test("", 0, 0, true, "", 0, argv0);
|
|
|
|
test(" ", 0, 0, true, "", 0, argv0);
|
|
|
|
test("foo", 0, 0, true, "", 1, argv_foo);
|
|
|
|
test("foo bar", 0, 0, true, "", 2, argv_foo_bar);
|
|
|
|
test(" foo bar", 0, 0, true, "", 2, argv_foo_bar);
|
|
|
|
test("foo bar ", 0, 0, true, "", 2, argv_foo_bar);
|
|
|
|
test(" foo bar ", 0, 0, true, "", 2, argv_foo_bar);
|
|
|
|
test("foo bar", 0, 0, true, "", 2, argv_foo_bar);
|
|
|
|
test(" foo bar", 0, 0, true, "", 2, argv_foo_bar);
|
|
|
|
test("foo bar ", 0, 0, true, "", 2, argv_foo_bar);
|
2020-12-01 16:40:41 -05:00
|
|
|
test(" foo bar ", 0, 0, true, "", 2, argv_foo_bar);
|
2020-12-05 17:41:22 -05:00
|
|
|
test("foo bar car", 0, 0, true, "", 3, argv_foo_bar_car);
|
2020-12-01 16:34:46 -05:00
|
|
|
|
2020-12-05 16:50:36 -05:00
|
|
|
test("foo bar car", 3, 0, true, "", 3, argv_foo_bar_car);
|
|
|
|
test("foo bar car", 0, 4, true, "", 3, argv_foo_bar_car);
|
2020-12-01 16:56:30 -05:00
|
|
|
test("foo bar car", 3, 4, true, "", 3, argv_foo_bar_car);
|
|
|
|
|
2020-12-01 16:54:18 -05:00
|
|
|
test("foo bar car", 2, 0, false, "too many args", 0, argv0);
|
2020-12-01 16:56:30 -05:00
|
|
|
test("foo bar car", 0, 3, false, "arg too long", 0, argv0);
|
2020-12-05 16:50:36 -05:00
|
|
|
test("foo bar car", 2, 3, false, "arg too long", 0, argv0);
|
2020-12-01 16:54:18 -05:00
|
|
|
|
2020-12-05 17:31:15 -05:00
|
|
|
test("\\ ", 0, 0, true, "", 1, argv_space);
|
|
|
|
test("\\\\", 0, 0, true, "", 1, argv_backslash);
|
|
|
|
test("foo\\ ", 0, 0, true, "", 1, argv_foospace);
|
|
|
|
test("foo\\\\", 0, 0, true, "", 1, argv_foobackslash);
|
|
|
|
test("\\ foo", 0, 0, true, "", 1, argv_spacefoo);
|
|
|
|
test("\\\\foo", 0, 0, true, "", 1, argv_backslashfoo);
|
|
|
|
test("\\ foo\\ ", 0, 0, true, "", 1, argv_spacefoospace);
|
|
|
|
test("\\\\foo\\\\", 0, 0, true, "", 1, argv_backslashfoobackslash);
|
|
|
|
test("foo\\ bar", 0, 0, true, "", 1, argv_foospacebar);
|
|
|
|
test("foo\\\\bar", 0, 0, true, "", 1, argv_foobackslashbar);
|
|
|
|
test("\\ foo bar", 0, 0, true, "", 2, argv_spacefoo_bar);
|
|
|
|
test("\\\\foo bar", 0, 0, true, "", 2, argv_backslashfoo_bar);
|
|
|
|
test("foo\\ bar", 0, 0, true, "", 2, argv_foospace_bar);
|
|
|
|
test("foo\\\\ bar", 0, 0, true, "", 2, argv_foobackslash_bar);
|
|
|
|
test("\\ foo\\ bar", 0, 0, true, "", 2, argv_spacefoospace_bar);
|
|
|
|
test("\\\\foo\\\\ bar", 0, 0, true, "", 2, argv_backslashfoobackslash_bar);
|
|
|
|
test("foo \\ bar", 0, 0, true, "", 2, argv_foo_spacebar);
|
|
|
|
test("foo \\\\bar", 0, 0, true, "", 2, argv_foo_backslashbar);
|
|
|
|
test("foo bar\\ ", 0, 0, true, "", 2, argv_foo_barspace);
|
|
|
|
test("foo bar\\\\", 0, 0, true, "", 2, argv_foo_barbackslash);
|
|
|
|
test("foo \\ bar\\ ", 0, 0, true, "", 2, argv_foo_spacebarspace);
|
|
|
|
test("foo \\\\bar\\\\", 0, 0, true, "", 2, argv_foo_backslashbarbackslash);
|
|
|
|
|
|
|
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 3, 0, true, "", 3, argv_spaceX3_X3);
|
|
|
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 3, 0, true, "", 3, argv_backslashX3_X3);
|
|
|
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 0, 4, true, "", 3, argv_spaceX3_X3);
|
|
|
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 0, 4, true, "", 3, argv_backslashX3_X3);
|
|
|
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 3, 4, true, "", 3, argv_spaceX3_X3);
|
|
|
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 3, 4, true, "", 3, argv_backslashX3_X3);
|
|
|
|
|
|
|
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 2, 0, false, "too many args", 0, argv0);
|
|
|
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 2, 0, false, "too many args", 0, argv0);
|
|
|
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 0, 3, false, "arg too long", 0, argv0);
|
|
|
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 0, 3, false, "arg too long", 0, argv0);
|
|
|
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 2, 3, false, "arg too long", 0, argv0);
|
|
|
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 2, 3, false, "arg too long", 0, argv0);
|
|
|
|
|
2020-12-05 17:34:57 -05:00
|
|
|
test("\\", 0, 0, false, "EOL after backslash", 0, argv0);
|
|
|
|
test(" \\", 0, 0, false, "EOL after backslash", 0, argv0);
|
|
|
|
test("\\ \\", 0, 0, false, "EOL after backslash", 0, argv0);
|
|
|
|
test("\\\\\\", 0, 0, false, "EOL after backslash", 0, argv0);
|
|
|
|
test("foo\\", 0, 0, false, "EOL after backslash", 0, argv0);
|
|
|
|
|
2020-12-01 16:34:46 -05:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void test(
|
|
|
|
const char *const cmdline,
|
2020-12-01 16:36:46 -05:00
|
|
|
unsigned int argv_count_max,
|
|
|
|
unsigned int arg_size_max,
|
2020-12-01 16:34:46 -05:00
|
|
|
|
2020-12-01 16:40:41 -05:00
|
|
|
const bool expected_result,
|
2020-12-01 16:34:46 -05:00
|
|
|
const char *const expected_error_msg,
|
|
|
|
unsigned int expected_argc,
|
|
|
|
const char *const *const expected_argv
|
|
|
|
) {
|
2020-12-01 16:36:46 -05:00
|
|
|
if (argv_count_max == 0) {
|
|
|
|
argv_count_max = ARGV_COUNT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (arg_size_max == 0) {
|
|
|
|
arg_size_max = ARG_SIZE_MAX;
|
|
|
|
}
|
|
|
|
|
2020-12-01 16:34:46 -05:00
|
|
|
char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX];
|
|
|
|
unsigned int argc = 1234;
|
|
|
|
char *argv[argv_count_max];
|
|
|
|
char buffer[argv_count_max * arg_size_max];
|
|
|
|
|
|
|
|
assert(
|
|
|
|
kernaux_cmdline_parse(
|
|
|
|
cmdline,
|
|
|
|
error_msg,
|
|
|
|
&argc,
|
|
|
|
argv,
|
|
|
|
buffer,
|
|
|
|
argv_count_max,
|
|
|
|
arg_size_max
|
|
|
|
) == !!expected_result
|
|
|
|
);
|
|
|
|
|
|
|
|
assert(strcmp(error_msg, expected_error_msg) == 0);
|
|
|
|
assert(argc == expected_argc);
|
|
|
|
|
|
|
|
for (unsigned int index = 0; index < argc; ++index) {
|
|
|
|
assert(strcmp(argv[index], expected_argv[index]) == 0);
|
|
|
|
}
|
2020-12-01 15:59:53 -05:00
|
|
|
|
2020-12-01 16:54:18 -05:00
|
|
|
for (unsigned int index = argc; index < argv_count_max; ++index) {
|
2020-12-01 15:59:53 -05:00
|
|
|
assert(argv[index] == KERNAUX_NULL);
|
|
|
|
}
|
2020-12-01 14:55:16 -05:00
|
|
|
}
|