From dacdfede2bdfc3c46df54ac45ae462a7c23699f4 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Mon, 27 Jun 2022 19:30:47 +0300 Subject: [PATCH] Improve cmdline file API (#103) --- ChangeLog | 1 + bindings/mruby/src/cmdline.c | 6 +- bindings/mruby/test/cmdline.rb | 4 +- bindings/ruby/ext/default/cmdline.c | 6 +- .../ruby/spec/lib/kernaux/cmdline_spec.rb | 4 +- bindings/rust/kernaux-sys/src/cmdline.rs | 10 +- common/cmdline.yml | 16 +-- examples/cmdline.c | 6 +- examples/cmdline_file.c | 46 +++++- include/kernaux/cmdline.h | 6 +- src/cmdline.c | 91 +++++++----- tests/Makefile.am | 8 +- tests/cmdline_gen.jinja | 107 +------------- tests/cmdline_test.c | 134 ++++++++++++++++++ tests/cmdline_test.h | 26 ++++ tests/test_cmdline.c | 105 +------------- 16 files changed, 298 insertions(+), 278 deletions(-) create mode 100644 tests/cmdline_test.c create mode 100644 tests/cmdline_test.h diff --git a/ChangeLog b/ChangeLog index 90eb8fb9..fb19bc6c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 2022-06-27 Alex Kotov * include/kernaux/memory_file.h: Added + * include/kernaux/cmdline: Added function "kernaux_cmdline_file" 2022-06-25 Alex Kotov diff --git a/bindings/mruby/src/cmdline.c b/bindings/mruby/src/cmdline.c index 56d949ea..78266758 100644 --- a/bindings/mruby/src/cmdline.c +++ b/bindings/mruby/src/cmdline.c @@ -8,7 +8,7 @@ #include #include -#define ARGV_COUNT_MAX 256 +#define ARG_COUNT_MAX 256 #define BUFFER_SIZE 4096 #ifdef KERNAUX_VERSION_WITH_CMDLINE @@ -34,7 +34,7 @@ mrb_value rb_KernAux_cmdline(mrb_state *const mrb, mrb_value self) mrb_get_args(mrb, "z", &str); size_t argc; char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX]; - char **const argv = malloc(sizeof(char*) * ARGV_COUNT_MAX); + char **const argv = malloc(sizeof(char*) * ARG_COUNT_MAX); char *const buffer = malloc(BUFFER_SIZE); const bool status = kernaux_cmdline( @@ -43,7 +43,7 @@ mrb_value rb_KernAux_cmdline(mrb_state *const mrb, mrb_value self) &argc, argv, buffer, - ARGV_COUNT_MAX, + ARG_COUNT_MAX, BUFFER_SIZE ); diff --git a/bindings/mruby/test/cmdline.rb b/bindings/mruby/test/cmdline.rb index 98ff730a..1a305f15 100644 --- a/bindings/mruby/test/cmdline.rb +++ b/bindings/mruby/test/cmdline.rb @@ -79,11 +79,11 @@ if KernAux::Version.with_cmdline? end cmdline = escape_str.call test['cmdline'] - argv_count_max = test['argv_count_max'] + arg_count_max = test['arg_count_max'] buffer_size = test['buffer_size'] result = test['result']&.map(&escape_str) - next unless argv_count_max.nil? && buffer_size.nil? && !result.nil? + next unless arg_count_max.nil? && buffer_size.nil? && !result.nil? assert "transforms #{cmdline.inspect} to #{result.inspect}" do assert_equal KernAux.cmdline(cmdline), result diff --git a/bindings/ruby/ext/default/cmdline.c b/bindings/ruby/ext/default/cmdline.c index 80749c6d..ca30b23b 100644 --- a/bindings/ruby/ext/default/cmdline.c +++ b/bindings/ruby/ext/default/cmdline.c @@ -2,12 +2,12 @@ #ifdef KERNAUX_VERSION_WITH_CMDLINE -#define ARGV_COUNT_MAX 256 +#define ARG_COUNT_MAX 256 #define BUFFER_SIZE 4096 struct Data { char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX]; - char *argv[ARGV_COUNT_MAX]; + char *argv[ARG_COUNT_MAX]; char buffer[BUFFER_SIZE]; }; @@ -64,7 +64,7 @@ VALUE rb_KernAux_cmdline(const VALUE self_rb, VALUE cmdline_rb) &argc, data->argv, data->buffer, - ARGV_COUNT_MAX, + ARG_COUNT_MAX, BUFFER_SIZE ); diff --git a/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb b/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb index 38b984ff..b5d427b5 100644 --- a/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb @@ -100,11 +100,11 @@ KernAux::Version.with_cmdline? and RSpec.describe KernAux, '.cmdline' do end cmdline = escape_str.call test['cmdline'] - argv_count_max = test['argv_count_max'] + arg_count_max = test['arg_count_max'] buffer_size = test['buffer_size'] result = test['result']&.map(&escape_str) - next unless argv_count_max.nil? && buffer_size.nil? && !result.nil? + next unless arg_count_max.nil? && buffer_size.nil? && !result.nil? it "transforms #{cmdline.inspect} to #{result.inspect}" do expect(described_class.cmdline(cmdline)).to eq result diff --git a/bindings/rust/kernaux-sys/src/cmdline.rs b/bindings/rust/kernaux-sys/src/cmdline.rs index c8ffb448..79b6ec19 100644 --- a/bindings/rust/kernaux-sys/src/cmdline.rs +++ b/bindings/rust/kernaux-sys/src/cmdline.rs @@ -13,7 +13,7 @@ extern "C" { argc: *mut size_t, argv: *mut *mut c_char, buffer: *mut c_char, - argv_count_max: size_t, + arg_count_max: size_t, buffer_size: size_t, ) -> bool; } @@ -24,7 +24,7 @@ mod tests { use std::ffi::{CStr, CString}; - const ARGV_COUNT_MAX: usize = 100; + const ARG_COUNT_MAX: usize = 100; const BUFFER_SIZE: usize = 4096; #[test] @@ -34,8 +34,8 @@ mod tests { let mut error_msg: [c_char; ERROR_MSG_SIZE_MAX] = [0; ERROR_MSG_SIZE_MAX]; let mut argc: size_t = 0; - let mut argv: [*mut c_char; ARGV_COUNT_MAX] = - [0 as *mut c_char; ARGV_COUNT_MAX]; + let mut argv: [*mut c_char; ARG_COUNT_MAX] = + [0 as *mut c_char; ARG_COUNT_MAX]; let mut buffer: [c_char; BUFFER_SIZE] = [0; BUFFER_SIZE]; unsafe { @@ -45,7 +45,7 @@ mod tests { &mut argc, argv.as_mut_ptr(), buffer.as_mut_ptr(), - ARGV_COUNT_MAX, + ARG_COUNT_MAX, BUFFER_SIZE, )); } diff --git a/common/cmdline.yml b/common/cmdline.yml index c371aacf..1ebef83e 100644 --- a/common/cmdline.yml +++ b/common/cmdline.yml @@ -51,46 +51,46 @@ result: ['foo', 'bar', 'car'] - cmdline: 'foo bar car' - argv_count_max: 3 + arg_count_max: 3 result: ['foo', 'bar', 'car'] - cmdline: 'foo bar car' buffer_size: 12 result: ['foo', 'bar', 'car'] - cmdline: 'foo bar car' - argv_count_max: 3 + arg_count_max: 3 buffer_size: 12 result: ['foo', 'bar', 'car'] - cmdline: 'foo bar car' - argv_count_max: 2 + arg_count_max: 2 error: 'too many args' - cmdline: 'foo bar car' buffer_size: 11 error: 'EOF or buffer overflow' - cmdline: 'foo bar car' - argv_count_max: 2 + arg_count_max: 2 buffer_size: 11 error: 'too many args' - cmdline: '\"foo\" \"bar\" \"car\"' - argv_count_max: 3 + arg_count_max: 3 result: ['foo', 'bar', 'car'] - cmdline: '\"foo\" \"bar\" \"car\"' buffer_size: 12 result: ['foo', 'bar', 'car'] - cmdline: '\"foo\" \"bar\" \"car\"' - argv_count_max: 3 + arg_count_max: 3 buffer_size: 12 result: ['foo', 'bar', 'car'] - cmdline: '\"foo\" \"bar\" \"car\"' - argv_count_max: 2 + arg_count_max: 2 error: 'too many args' - cmdline: '\"foo\" \"bar\" \"car\"' buffer_size: 11 error: 'EOF or buffer overflow' - cmdline: '\"foo\" \"bar\" \"car\"' - argv_count_max: 2 + arg_count_max: 2 buffer_size: 11 error: 'too many args' diff --git a/examples/cmdline.c b/examples/cmdline.c index 4c968542..83732d70 100644 --- a/examples/cmdline.c +++ b/examples/cmdline.c @@ -4,7 +4,7 @@ #include #include -#define ARGV_COUNT_MAX 100 +#define ARG_COUNT_MAX 100 #define BUFFER_SIZE 4096 static const char *const cmdline = "foo bar\\ baz \"car cdr\""; @@ -13,7 +13,7 @@ void example_main() { char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX]; size_t argc; - char *argv[ARGV_COUNT_MAX]; + char *argv[ARG_COUNT_MAX]; char buffer[BUFFER_SIZE]; assert(kernaux_cmdline( @@ -22,7 +22,7 @@ void example_main() &argc, argv, buffer, - ARGV_COUNT_MAX, + ARG_COUNT_MAX, BUFFER_SIZE )); diff --git a/examples/cmdline_file.c b/examples/cmdline_file.c index b90ecadd..ee9b6fb4 100644 --- a/examples/cmdline_file.c +++ b/examples/cmdline_file.c @@ -5,22 +5,62 @@ #include #include +#define ARG_COUNT_MAX 100 +#define BUFFER_SIZE 4096 + static const char *const cmdline = "foo bar\\ baz \"car cdr\""; -static char buffer[4096]; +static void with_args_indices_array(); +static void without_args_indices_array(); void example_main() +{ + with_args_indices_array(); + without_args_indices_array(); +} + +void with_args_indices_array() { char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX]; size_t argc; + size_t argv[ARG_COUNT_MAX]; + char buffer[BUFFER_SIZE]; + struct KernAux_MemoryFile memory_file = - KernAux_MemoryFile_create(buffer, sizeof(buffer), NULL); + KernAux_MemoryFile_create(buffer, BUFFER_SIZE, NULL); assert(kernaux_cmdline_file( cmdline, error_msg, &argc, - &memory_file.file + &memory_file.file, + argv, + ARG_COUNT_MAX + )); + + assert(strcmp(error_msg, "") == 0); + assert(argc == 3); + assert(strcmp(&buffer[argv[0]], "foo") == 0); + assert(strcmp(&buffer[argv[1]], "bar baz") == 0); + assert(strcmp(&buffer[argv[2]], "car cdr") == 0); +} + +void without_args_indices_array() +{ + char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX]; + size_t argc; + char buffer[BUFFER_SIZE]; + + struct KernAux_MemoryFile memory_file = + KernAux_MemoryFile_create(buffer, BUFFER_SIZE, NULL); + + assert(kernaux_cmdline_file( + cmdline, + error_msg, + &argc, + &memory_file.file, + NULL, + 0 )); assert(strcmp(error_msg, "") == 0); diff --git a/include/kernaux/cmdline.h b/include/kernaux/cmdline.h index 266e0aa8..84735125 100644 --- a/include/kernaux/cmdline.h +++ b/include/kernaux/cmdline.h @@ -20,7 +20,7 @@ bool kernaux_cmdline( size_t *argc, char **argv, char *buffer, - size_t argv_count_max, + size_t arg_count_max, size_t buffer_size ); @@ -28,7 +28,9 @@ bool kernaux_cmdline_file( const char *cmdline, char *error_msg, size_t *argc, - KernAux_File file + KernAux_File file, + size_t *arg_idxs, + size_t arg_count_max ); #ifdef __cplusplus diff --git a/src/cmdline.c b/src/cmdline.c index 7ac93311..48de810b 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -25,9 +25,10 @@ static bool kernaux_cmdline_common( char arg_terminator, char **argv, char *buffer, - size_t argv_count_max, - size_t buffer_size, - KernAux_File file + KernAux_File file, + size_t *arg_idxs, + size_t arg_count_max, + size_t buffer_size ); /***************************** @@ -40,14 +41,14 @@ bool kernaux_cmdline( size_t *const argc, char **const argv, char *const buffer, - const size_t argv_count_max, + const size_t arg_count_max, const size_t buffer_size ) { KERNAUX_ASSERT(cmdline); KERNAUX_ASSERT(error_msg); KERNAUX_ASSERT(argc); KERNAUX_ASSERT(argv); - KERNAUX_ASSERT(argv_count_max > 0); + KERNAUX_ASSERT(arg_count_max > 0); KERNAUX_ASSERT(buffer_size > 0); return kernaux_cmdline_common( @@ -57,9 +58,10 @@ bool kernaux_cmdline( '\0', // arg_terminator argv, buffer, - argv_count_max, - buffer_size, - NULL + NULL, + NULL, + arg_count_max, + buffer_size ); } @@ -67,12 +69,15 @@ bool kernaux_cmdline_file( const char *const cmdline, char *const error_msg, size_t *const argc, - const KernAux_File file + const KernAux_File file, + size_t *arg_idxs, + size_t arg_count_max ) { KERNAUX_ASSERT(cmdline); KERNAUX_ASSERT(error_msg); KERNAUX_ASSERT(argc); KERNAUX_ASSERT(file); + KERNAUX_ASSERT(arg_idxs == NULL || arg_count_max > 0); return kernaux_cmdline_common( cmdline, @@ -81,9 +86,10 @@ bool kernaux_cmdline_file( '\0', // arg_terminator NULL, NULL, - 0, - 0, - file + file, + arg_idxs, + arg_count_max, + 0 ); } @@ -91,52 +97,67 @@ bool kernaux_cmdline_file( * Implementation: main internal function * ******************************************/ +#define CLEAR do { \ + *argc = 0; \ + if (argv) memset(argv, 0, sizeof(char*) * arg_count_max); \ + if (buffer) memset(buffer, '\0', buffer_size); \ + if (arg_idxs) memset(arg_idxs, 0, sizeof(size_t) * arg_count_max); \ +} while (0) + #define FAIL(msg) do { \ strcpy(error_msg, msg); \ goto fail; \ } while (0) #define PUT_CHAR(char) do { \ - if (buffer_size && buffer_pos >= buffer_size) { \ + if (buffer_size && buffer_or_file_pos >= buffer_size) { \ FAIL("EOF or buffer overflow"); \ } \ if (buffer) { \ - buffer[buffer_pos++] = char; \ + buffer[buffer_or_file_pos] = char; \ } \ if (file) { \ if (KernAux_File_putc(file, char) == KERNAUX_EOF) { \ FAIL("EOF or buffer overflow"); \ } \ } \ + ++buffer_or_file_pos; \ } while (0) -#define PUT_ARG do { \ - if (argv_count_max && *argc >= argv_count_max) { \ - FAIL("too many args"); \ - } \ - if (argv && buffer) { \ - argv[*argc] = &buffer[buffer_pos]; \ - } \ - ++(*argc); \ +#define PUT_ARG do { \ + if (arg_count_max && *argc >= arg_count_max) { \ + FAIL("too many args"); \ + } \ + if (argv && buffer) { \ + argv[*argc] = &buffer[buffer_or_file_pos]; \ + } \ + if (arg_idxs) { \ + arg_idxs[*argc] = buffer_or_file_pos; \ + } \ + ++(*argc); \ } while (0) #define PUT_ARG_AND_CHAR(char) do { \ - if (argv_count_max && *argc >= argv_count_max) { \ + if (arg_count_max && *argc >= arg_count_max) { \ FAIL("too many args"); \ } \ - if (buffer_size && buffer_pos >= buffer_size) { \ + if (buffer_size && buffer_or_file_pos >= buffer_size) { \ FAIL("EOF or buffer overflow"); \ } \ if (argv && buffer) { \ - argv[*argc] = &buffer[buffer_pos]; \ - buffer[buffer_pos++] = char; \ + argv[*argc] = &buffer[buffer_or_file_pos]; \ + buffer[buffer_or_file_pos] = char; \ } \ if (file) { \ if (KernAux_File_putc(file, char) == KERNAUX_EOF) { \ FAIL("EOF or buffer overflow"); \ } \ } \ + if (arg_idxs) { \ + arg_idxs[*argc] = buffer_or_file_pos; \ + } \ ++(*argc); \ + ++buffer_or_file_pos; \ } while (0) bool kernaux_cmdline_common( @@ -146,23 +167,23 @@ bool kernaux_cmdline_common( char arg_terminator, char **const argv, char *const buffer, - const size_t argv_count_max, - const size_t buffer_size, - const KernAux_File file + const KernAux_File file, + size_t *const arg_idxs, + const size_t arg_count_max, + const size_t buffer_size ) { KERNAUX_ASSERT(cmdline); KERNAUX_ASSERT(error_msg); KERNAUX_ASSERT(argc); + (void)arg_idxs; memset(error_msg, '\0', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); - *argc = 0; - if (argv) memset(argv, 0, sizeof(char*) * argv_count_max); - if (buffer) memset(buffer, '\0', buffer_size); + CLEAR; if (cmdline[0] == '\0') return true; enum State state = INITIAL; - size_t buffer_pos = 0; + size_t buffer_or_file_pos = 0; for (size_t index = 0; ; ++index) { const char cur = cmdline[index]; @@ -259,8 +280,6 @@ bool kernaux_cmdline_common( return true; fail: - *argc = 0; - if (argv) memset(argv, 0, sizeof(char*) * argv_count_max); - if (buffer) memset(buffer, '\0', buffer_size); + CLEAR; return false; } diff --git a/tests/Makefile.am b/tests/Makefile.am index e0a1c822..8049c443 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -65,7 +65,9 @@ TESTS += test_cmdline test_cmdline_LDADD = $(top_builddir)/libkernaux.la test_cmdline_SOURCES = \ main.c \ - test_cmdline.c + test_cmdline.c \ + cmdline_test.h \ + cmdline_test.c endif #################### @@ -81,7 +83,9 @@ test_cmdline_gen_SOURCES = \ test_cmdline_gen.c \ cmdline_gen.py \ cmdline_gen.jinja \ - $(top_srcdir)/common/cmdline.yml + $(top_srcdir)/common/cmdline.yml \ + cmdline_test.h \ + cmdline_test.c endif endif diff --git a/tests/cmdline_gen.jinja b/tests/cmdline_gen.jinja index 99be76eb..1148616a 100644 --- a/tests/cmdline_gen.jinja +++ b/tests/cmdline_gen.jinja @@ -2,29 +2,13 @@ #include "config.h" #endif -#include -#include +#include "cmdline_test.h" -#include #include #include #include #include -#define ARGV_COUNT_MAX 100 -#define BUFFER_SIZE 4096 - -static void test( - const char *cmdline, - size_t argv_count_max, - size_t buffer_size, - - bool expected_result, - const char *expected_error_msg, - size_t expected_argc, - const char *const *const expected_argv -); - void test_main() { {% for case in cases %} @@ -39,7 +23,7 @@ void test_main() test( {{ escape_str(case.cmdline) }}, - {{ escape_int(case.argv_count_max or 0) }}, + {{ escape_int(case.arg_count_max or 0) }}, {{ escape_int(case.buffer_size or 0) }}, {% if not case.error %} true, @@ -60,90 +44,3 @@ void test_main() } {% endfor %} } - -void test( - const char *const cmdline, - size_t argv_count_max, - size_t buffer_size, - - const bool expected_result, - const char *const expected_error_msg, - size_t expected_argc, - const char *const *const expected_argv -) { - if (argv_count_max == 0) argv_count_max = ARGV_COUNT_MAX; - if (buffer_size == 0) buffer_size = BUFFER_SIZE; - - char *error_msg = malloc(KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); - size_t argc = 1234; - char **const argv = malloc(sizeof(char*) * argv_count_max); - char *const buffer = malloc(buffer_size); - - assert(error_msg); - assert(argv); - assert(buffer); - - { - memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); - memset(argv, 'x', sizeof(char*) * argv_count_max); - memset(buffer, 'x', buffer_size); - - assert( - kernaux_cmdline( - cmdline, - error_msg, - &argc, - argv, - buffer, - argv_count_max, - buffer_size - ) == !!expected_result - ); - - assert(strcmp(error_msg, expected_error_msg) == 0); - assert(argc == expected_argc); - - if (expected_argv) { - for (size_t index = 0; index < argc; ++index) { - assert(strcmp(argv[index], expected_argv[index]) == 0); - } - } - - for (size_t index = argc; index < argv_count_max; ++index) { - assert(argv[index] == NULL); - } - } - - if (strcmp(expected_error_msg, "too many args") != 0) { - memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); - memset(argv, 'x', sizeof(char*) * argv_count_max); - memset(buffer, 'x', buffer_size); - - struct KernAux_MemoryFile memory_file = - KernAux_MemoryFile_create(buffer, buffer_size, NULL); - - assert( - kernaux_cmdline_file( - cmdline, - error_msg, - &argc, - &memory_file.file - ) == !!expected_result - ); - - assert(strcmp(error_msg, expected_error_msg) == 0); - assert(argc == expected_argc); - - if (expected_argv) { - const char *arg = buffer; - for (size_t index = 0; index < argc; ++index) { - assert(strcmp(expected_argv[index], arg) == 0); - arg += strlen(arg) + 1; - } - } - } - - free(error_msg); - free(argv); - free(buffer); -} diff --git a/tests/cmdline_test.c b/tests/cmdline_test.c new file mode 100644 index 00000000..654cae75 --- /dev/null +++ b/tests/cmdline_test.c @@ -0,0 +1,134 @@ +#include "cmdline_test.h" + +#include +#include + +#include +#include +#include + +#define ARG_COUNT_MAX 100 +#define BUFFER_SIZE 4096 + +void test( + const char *const cmdline, + size_t arg_count_max, + size_t buffer_size, + + const bool expected_result, + const char *const expected_error_msg, + size_t expected_argc, + const char *const *const expected_argv +) { + if (arg_count_max == 0) arg_count_max = ARG_COUNT_MAX; + if (buffer_size == 0) buffer_size = BUFFER_SIZE; + + char *error_msg = malloc(KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); + size_t argc = 1234; + char **const argv = malloc(sizeof(char*) * arg_count_max); + size_t *arg_idxs = malloc(sizeof(size_t) * arg_count_max); + char *const buffer = malloc(buffer_size); + + assert(error_msg); + assert(argv); + assert(buffer); + + { + memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); + memset(argv, 0, sizeof(char*) * arg_count_max); + memset(arg_idxs, 0, sizeof(size_t) * arg_count_max); + memset(buffer, 'x', buffer_size); + + assert( + kernaux_cmdline( + cmdline, + error_msg, + &argc, + argv, + buffer, + arg_count_max, + buffer_size + ) == !!expected_result + ); + + assert(strcmp(error_msg, expected_error_msg) == 0); + assert(argc == expected_argc); + + if (expected_argv) { + for (size_t index = 0; index < argc; ++index) { + assert(strcmp(argv[index], expected_argv[index]) == 0); + } + } + + for (size_t index = argc; index < arg_count_max; ++index) { + assert(argv[index] == NULL); + } + } + + { + memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); + memset(argv, 0, sizeof(char*) * arg_count_max); + memset(arg_idxs, 0, sizeof(size_t) * arg_count_max); + memset(buffer, 'x', buffer_size); + + struct KernAux_MemoryFile memory_file = + KernAux_MemoryFile_create(buffer, buffer_size, NULL); + + assert( + kernaux_cmdline_file( + cmdline, + error_msg, + &argc, + &memory_file.file, + arg_idxs, + arg_count_max + ) == !!expected_result + ); + + assert(strcmp(error_msg, expected_error_msg) == 0); + assert(argc == expected_argc); + + if (expected_argv) { + for (size_t index = 0; index < argc; ++index) { + assert(strcmp(&buffer[arg_idxs[index]], expected_argv[index]) == 0); + } + } + } + + if (strcmp(expected_error_msg, "too many args") != 0) { + memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); + memset(argv, 0, sizeof(char*) * arg_count_max); + memset(arg_idxs, 0, sizeof(size_t) * arg_count_max); + memset(buffer, 'x', buffer_size); + + struct KernAux_MemoryFile memory_file = + KernAux_MemoryFile_create(buffer, buffer_size, NULL); + + assert( + kernaux_cmdline_file( + cmdline, + error_msg, + &argc, + &memory_file.file, + NULL, + 0 + ) == !!expected_result + ); + + assert(strcmp(error_msg, expected_error_msg) == 0); + assert(argc == expected_argc); + + if (expected_argv) { + const char *arg = buffer; + for (size_t index = 0; index < argc; ++index) { + assert(strcmp(expected_argv[index], arg) == 0); + arg += strlen(arg) + 1; + } + } + } + + free(error_msg); + free(argv); + free(arg_idxs); + free(buffer); +} diff --git a/tests/cmdline_test.h b/tests/cmdline_test.h new file mode 100644 index 00000000..645e24f9 --- /dev/null +++ b/tests/cmdline_test.h @@ -0,0 +1,26 @@ +#ifndef KERNAUX_INCLUDED_TESTS_CMDLINE_TEST +#define KERNAUX_INCLUDED_TESTS_CMDLINE_TEST + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +void test( + const char *cmdline, + size_t arg_count_max, + size_t buffer_size, + + bool expected_result, + const char *expected_error_msg, + size_t expected_argc, + const char *const *const expected_argv +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/test_cmdline.c b/tests/test_cmdline.c index 996d7cf1..3aba50a2 100644 --- a/tests/test_cmdline.c +++ b/tests/test_cmdline.c @@ -2,29 +2,13 @@ #include "config.h" #endif -#include -#include +#include "cmdline_test.h" -#include #include #include #include #include -#define ARGV_COUNT_MAX 100 -#define BUFFER_SIZE 4096 - -static void test( - const char *cmdline, - size_t argv_count_max, - size_t buffer_size, - - bool expected_result, - const char *expected_error_msg, - size_t expected_argc, - const char *const *const expected_argv -); - static const char *const argv_spaceX3_X3[] = {" ", " ", " "}; static const char *const argv_backslashX3_X3[] = {"\\\\\\", "\\\\\\", "\\\\\\"}; static const char *const argv_quotmarkX3_X3[] = {"\"\"\"", "\"\"\"", "\"\"\""}; @@ -133,90 +117,3 @@ void test_main() free(buffer); } } - -void test( - const char *const cmdline, - size_t argv_count_max, - size_t buffer_size, - - const bool expected_result, - const char *const expected_error_msg, - size_t expected_argc, - const char *const *const expected_argv -) { - if (argv_count_max == 0) argv_count_max = ARGV_COUNT_MAX; - if (buffer_size == 0) buffer_size = BUFFER_SIZE; - - char *error_msg = malloc(KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); - size_t argc = 1234; - char **const argv = malloc(sizeof(char*) * argv_count_max); - char *const buffer = malloc(buffer_size); - - assert(error_msg); - assert(argv); - assert(buffer); - - { - memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); - memset(argv, 'x', sizeof(char*) * argv_count_max); - memset(buffer, 'x', buffer_size); - - assert( - kernaux_cmdline( - cmdline, - error_msg, - &argc, - argv, - buffer, - argv_count_max, - buffer_size - ) == !!expected_result - ); - - assert(strcmp(error_msg, expected_error_msg) == 0); - assert(argc == expected_argc); - - if (expected_argv) { - for (size_t index = 0; index < argc; ++index) { - assert(strcmp(argv[index], expected_argv[index]) == 0); - } - } - - for (size_t index = argc; index < argv_count_max; ++index) { - assert(argv[index] == NULL); - } - } - - if (strcmp(expected_error_msg, "too many args") != 0) { - memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX); - memset(argv, 'x', sizeof(char*) * argv_count_max); - memset(buffer, 'x', buffer_size); - - struct KernAux_MemoryFile memory_file = - KernAux_MemoryFile_create(buffer, buffer_size, NULL); - - assert( - kernaux_cmdline_file( - cmdline, - error_msg, - &argc, - &memory_file.file - ) == !!expected_result - ); - - assert(strcmp(error_msg, expected_error_msg) == 0); - assert(argc == expected_argc); - - if (expected_argv) { - const char *arg = buffer; - for (size_t index = 0; index < argc; ++index) { - assert(strcmp(expected_argv[index], arg) == 0); - arg += strlen(arg) + 1; - } - } - } - - free(error_msg); - free(argv); - free(buffer); -}