1
0
Fork 0
mirror of https://github.com/tailix/libkernaux.git synced 2024-11-13 11:04:27 -05:00
libkernaux/tests/test_cmdline.c

278 lines
15 KiB
C
Raw Normal View History

2020-12-06 23:47:53 -05:00
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
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-06 05:16:15 -05:00
#include <stddef.h>
2020-12-01 15:29:45 -05:00
#include <string.h>
2020-12-01 15:22:38 -05:00
2022-01-21 16:42:54 -05:00
#define ARGV_COUNT_MAX 100
#define BUFFER_SIZE 4096
2020-12-01 15:22:38 -05:00
2020-12-01 16:34:46 -05:00
static void test(
const char *cmdline,
2021-12-16 10:26:16 -05:00
size_t argv_count_max,
2022-01-21 16:42:54 -05:00
size_t buffer_size,
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,
2021-12-16 10:26:16 -05:00
size_t expected_argc,
2020-12-01 16:34:46 -05:00
const char *const *const expected_argv
);
2020-12-01 15:32:35 -05:00
2021-12-12 10:39:17 -05:00
static const char *const argv_empty[] = {""};
static const char *const argv_empty_X2[] = {"", ""};
static const char *const argv_empty_X3[] = {"", "", ""};
2020-12-01 16:34:46 -05:00
static const char *const argv_foo[] = {"foo"};
static const char *const argv_foo_bar[] = {"foo", "bar"};
static const char *const argv_foo_bar_car[] = {"foo", "bar", "car"};
2021-12-12 10:39:17 -05:00
static const char *const argv_spaceX3_X3[] = {" ", " ", " "};
static const char *const argv_backslashX3_X3[] = {"\\\\\\", "\\\\\\", "\\\\\\"};
static const char *const argv_quotmarkX3_X3[] = {"\"\"\"", "\"\"\"", "\"\"\""};
static const char *const argv_foospacebar_car[] = {"foo bar", "car"};
static const char *const argv_foo_barspacecar[] = {"foo", "bar car"};
static const char *const argv_space[] = {" "};
static const char *const argv_backslash[] = {"\\"};
static const char *const argv_quotmark[] = {"\""};
static const char *const argv_foospace[] = {"foo "};
static const char *const argv_foobackslash[] = {"foo\\"};
static const char *const argv_fooquotmark[] = {"foo\""};
static const char *const argv_spacefoo[] = {" foo"};
static const char *const argv_backslashfoo[] = {"\\foo"};
static const char *const argv_quotmarkfoo[] = {"\"foo"};
static const char *const argv_spacefoospace[] = {" foo "};
static const char *const argv_backslashfoobackslash[] = {"\\foo\\"};
static const char *const argv_quotmarkfooquotmark[] = {"\"foo\""};
static const char *const argv_foospacebar[] = {"foo bar"};
static const char *const argv_foobackslashbar[] = {"foo\\bar"};
static const char *const argv_fooquotmarkbar[] = {"foo\"bar"};
static const char *const argv_spacefoo_bar[] = {" foo", "bar"};
static const char *const argv_backslashfoo_bar[] = {"\\foo", "bar"};
static const char *const argv_quotmarkfoo_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_fooquotmark_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_quotmarkfooquotmark_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_quotmarkbar[] = {"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_barquotmark[] = {"foo", "bar\""};
static const char *const argv_foo_spacebarspace[] = {"foo", " bar "};
static const char *const argv_foo_backslashbarbackslash[] = {"foo", "\\bar\\"};
static const char *const argv_foo_quotmarkbarquotmark[] = {"foo", "\"bar\""};
2020-12-01 16:34:46 -05:00
int main()
{
2021-12-13 15:51:49 -05:00
test("", 0, 0, true, "", 0, NULL);
test(" ", 0, 0, true, "", 0, NULL);
2020-12-05 17:41:22 -05:00
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
2021-12-12 10:39:17 -05:00
test("\"\"", 0, 0, true, "", 1, argv_empty);
test("\"\" \"\"", 0, 0, true, "", 2, argv_empty_X2);
test("\"\" \"\" \"\"", 0, 0, true, "", 3, argv_empty_X3);
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);
test(" \"foo\" \"bar\" ", 0, 0, true, "", 2, argv_foo_bar);
test("\"foo\" \"bar\" \"car\"", 0, 0, true, "", 3, argv_foo_bar_car);
2022-01-21 17:07:05 -05:00
test("foo bar car", 3, 0, true, "", 3, argv_foo_bar_car);
test("foo bar car", 0, 12, true, "", 3, argv_foo_bar_car);
test("foo bar car", 3, 12, true, "", 3, argv_foo_bar_car);
2020-12-01 16:56:30 -05:00
2022-01-21 17:07:05 -05:00
test("foo bar car", 2, 0, false, "too many args", 0, NULL);
test("foo bar car", 0, 11, false, "buffer overflow", 0, NULL);
test("foo bar car", 2, 11, false, "too many args", 0, NULL);
2020-12-01 16:54:18 -05:00
2022-01-21 17:07:05 -05:00
test("\"foo\" \"bar\" \"car\"", 3, 0, true, "", 3, argv_foo_bar_car);
test("\"foo\" \"bar\" \"car\"", 0, 12, true, "", 3, argv_foo_bar_car);
test("\"foo\" \"bar\" \"car\"", 3, 12, true, "", 3, argv_foo_bar_car);
2021-12-12 10:39:17 -05:00
2022-01-21 17:07:05 -05:00
test("\"foo\" \"bar\" \"car\"", 2, 0, false, "too many args", 0, NULL);
test("\"foo\" \"bar\" \"car\"", 0, 11, false, "buffer overflow", 0, NULL);
test("\"foo\" \"bar\" \"car\"", 2, 11, false, "too many args", 0, NULL);
2021-12-12 10:39:17 -05:00
test("\\ ", 0, 0, true, "", 1, argv_space);
test("\"\\ \"", 0, 0, true, "", 1, argv_space);
test("\\\\", 0, 0, true, "", 1, argv_backslash);
test("\"\\\\\"", 0, 0, true, "", 1, argv_backslash);
test("\\\"", 0, 0, true, "", 1, argv_quotmark);
test("\"\\\"\"", 0, 0, true, "", 1, argv_quotmark);
test("foo\\ ", 0, 0, true, "", 1, argv_foospace);
test("\"foo\\ \"", 0, 0, true, "", 1, argv_foospace);
test("foo\\\\", 0, 0, true, "", 1, argv_foobackslash);
test("\"foo\\\\\"", 0, 0, true, "", 1, argv_foobackslash);
test("foo\\\"", 0, 0, true, "", 1, argv_fooquotmark);
test("\"foo\\\"\"", 0, 0, true, "", 1, argv_fooquotmark);
test("\\ foo", 0, 0, true, "", 1, argv_spacefoo);
test("\"\\ foo\"", 0, 0, true, "", 1, argv_spacefoo);
test("\\\\foo", 0, 0, true, "", 1, argv_backslashfoo);
test("\"\\\\foo\"", 0, 0, true, "", 1, argv_backslashfoo);
test("\\\"foo", 0, 0, true, "", 1, argv_quotmarkfoo);
test("\"\\\"foo\"", 0, 0, true, "", 1, argv_quotmarkfoo);
test("\\ foo\\ ", 0, 0, true, "", 1, argv_spacefoospace);
test("\"\\ foo\\ \"", 0, 0, true, "", 1, argv_spacefoospace);
test("\\\\foo\\\\", 0, 0, true, "", 1, argv_backslashfoobackslash);
test("\"\\\\foo\\\\\"", 0, 0, true, "", 1, argv_backslashfoobackslash);
test("\\\"foo\\\"", 0, 0, true, "", 1, argv_quotmarkfooquotmark);
test("\"\\\"foo\\\"\"", 0, 0, true, "", 1, argv_quotmarkfooquotmark);
test("foo\\ bar", 0, 0, true, "", 1, argv_foospacebar);
test("\"foo\\ bar\"", 0, 0, true, "", 1, argv_foospacebar);
test("foo\\\\bar", 0, 0, true, "", 1, argv_foobackslashbar);
test("\"foo\\\\bar\"", 0, 0, true, "", 1, argv_foobackslashbar);
test("foo\\\"bar", 0, 0, true, "", 1, argv_fooquotmarkbar);
test("\"foo\\\"bar\"", 0, 0, true, "", 1, argv_fooquotmarkbar);
test("\\ foo bar", 0, 0, true, "", 2, argv_spacefoo_bar);
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_backslashfoo_bar);
test("\\\"foo bar", 0, 0, true, "", 2, argv_quotmarkfoo_bar);
test("\"\\\"foo\" bar", 0, 0, true, "", 2, argv_quotmarkfoo_bar);
test("foo\\ bar", 0, 0, true, "", 2, argv_foospace_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_foobackslash_bar);
test("foo\\\" bar", 0, 0, true, "", 2, argv_fooquotmark_bar);
test("\"foo\\\"\" bar", 0, 0, true, "", 2, argv_fooquotmark_bar);
test("\\ foo\\ bar", 0, 0, true, "", 2, argv_spacefoospace_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_backslashfoobackslash_bar);
test("\\\"foo\\\" bar", 0, 0, true, "", 2, argv_quotmarkfooquotmark_bar);
test("\"\\\"foo\\\"\" bar", 0, 0, true, "", 2, argv_quotmarkfooquotmark_bar);
test("foo \\ bar", 0, 0, true, "", 2, argv_foo_spacebar);
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_backslashbar);
test("foo \\\"bar", 0, 0, true, "", 2, argv_foo_quotmarkbar);
test("foo \"\\\"bar\"", 0, 0, true, "", 2, argv_foo_quotmarkbar);
test("foo bar\\ ", 0, 0, true, "", 2, argv_foo_barspace);
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_barbackslash);
test("foo bar\\\"", 0, 0, true, "", 2, argv_foo_barquotmark);
test("foo \"bar\\\"\"", 0, 0, true, "", 2, argv_foo_barquotmark);
test("foo \\ bar\\ ", 0, 0, true, "", 2, argv_foo_spacebarspace);
test("foo \"\\ bar\\ \"", 0, 0, true, "", 2, argv_foo_spacebarspace);
test("foo \\\\bar\\\\", 0, 0, true, "", 2, argv_foo_backslashbarbackslash);
test("foo \"\\\\bar\\\\\"", 0, 0, true, "", 2, argv_foo_backslashbarbackslash);
test("foo \\\"bar\\\"", 0, 0, true, "", 2, argv_foo_quotmarkbarquotmark);
test("foo \"\\\"bar\\\"\"", 0, 0, true, "", 2, argv_foo_quotmarkbarquotmark);
2021-12-12 10:39:17 -05:00
test("foo\\ bar car", 0, 0, true, "", 2, argv_foospacebar_car);
test("\"foo bar\" car", 0, 0, true, "", 2, argv_foospacebar_car);
test("\"foo bar\" \"car\"", 0, 0, true, "", 2, argv_foospacebar_car);
test("foo bar\\ car", 0, 0, true, "", 2, argv_foo_barspacecar);
test("foo \"bar car\"", 0, 0, true, "", 2, argv_foo_barspacecar);
test("\"foo\" \"bar car\"", 0, 0, true, "", 2, argv_foo_barspacecar);
2022-01-21 17:07:05 -05:00
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 3, 0, true, "", 3, argv_spaceX3_X3);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 3, 0, true, "", 3, argv_backslashX3_X3);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 3, 0, true, "", 3, argv_quotmarkX3_X3);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 0, 12, true, "", 3, argv_spaceX3_X3);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 0, 12, true, "", 3, argv_backslashX3_X3);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 0, 12, true, "", 3, argv_quotmarkX3_X3);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 3, 12, true, "", 3, argv_spaceX3_X3);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 3, 12, true, "", 3, argv_backslashX3_X3);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 3, 12, true, "", 3, argv_quotmarkX3_X3);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 2, 0, false, "too many args", 0, NULL);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 2, 0, false, "too many args", 0, NULL);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 2, 0, false, "too many args", 0, NULL);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 0, 11, false, "buffer overflow", 0, NULL);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 0, 11, false, "buffer overflow", 0, NULL);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 0, 11, false, "buffer overflow", 0, NULL);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 2, 11, false, "too many args", 0, NULL);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 2, 11, false, "too many args", 0, NULL);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 2, 11, false, "too many args", 0, NULL);
2021-12-13 15:51:49 -05:00
test("\\", 0, 0, false, "EOL after backslash", 0, NULL);
test(" \\", 0, 0, false, "EOL after backslash", 0, NULL);
test("\\ \\", 0, 0, false, "EOL after backslash", 0, NULL);
test("\\\\\\", 0, 0, false, "EOL after backslash", 0, NULL);
test("\\\"\\", 0, 0, false, "EOL after backslash", 0, NULL);
test("foo\\", 0, 0, false, "EOL after backslash", 0, NULL);
test("\"\\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("\" \\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("\"\\ \\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("\"\\\\\\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("\"\\\"\\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("\"foo\\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("foo\"", 0, 0, false, "unescaped quotation mark", 0, NULL);
test("foo\"bar", 0, 0, false, "unescaped quotation mark", 0, NULL);
test("\"", 0, 0, false, "EOL inside quote", 0, NULL);
test("\"foo", 0, 0, false, "EOL inside quote", 0, NULL);
2021-12-12 10:52:04 -05:00
2020-12-01 16:34:46 -05:00
return 0;
}
void test(
const char *const cmdline,
2021-12-16 10:26:16 -05:00
size_t argv_count_max,
2022-01-21 16:42:54 -05:00
size_t buffer_size,
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,
2021-12-16 10:26:16 -05:00
size_t expected_argc,
2020-12-01 16:34:46 -05:00
const char *const *const expected_argv
) {
2022-01-21 16:42:54 -05:00
if (argv_count_max == 0) argv_count_max = ARGV_COUNT_MAX;
if (buffer_size == 0) buffer_size = BUFFER_SIZE;
2020-12-01 16:36:46 -05:00
2020-12-01 16:34:46 -05:00
char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX];
2021-12-16 10:26:16 -05:00
size_t argc = 1234;
2020-12-01 16:34:46 -05:00
char *argv[argv_count_max];
2022-01-21 16:42:54 -05:00
char buffer[buffer_size];
2020-12-01 16:34:46 -05:00
assert(
kernaux_cmdline(
2020-12-01 16:34:46 -05:00
cmdline,
error_msg,
&argc,
argv,
buffer,
argv_count_max,
2022-01-21 16:42:54 -05:00
buffer_size
2020-12-01 16:34:46 -05:00
) == !!expected_result
);
assert(strcmp(error_msg, expected_error_msg) == 0);
assert(argc == expected_argc);
2021-12-16 10:26:16 -05:00
for (size_t index = 0; index < argc; ++index) {
2020-12-01 16:34:46 -05:00
assert(strcmp(argv[index], expected_argv[index]) == 0);
}
2020-12-01 15:59:53 -05:00
2021-12-16 10:26:16 -05:00
for (size_t index = argc; index < argv_count_max; ++index) {
2020-12-06 05:16:15 -05:00
assert(argv[index] == NULL);
2020-12-01 15:59:53 -05:00
}
2020-12-01 14:55:16 -05:00
}