aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ls_args.h20
-rw-r--r--tests/ls_test.h36
-rw-r--r--tests/tests.c43
3 files changed, 88 insertions, 11 deletions
diff --git a/ls_args.h b/ls_args.h
index 38592fa..bd57e2a 100644
--- a/ls_args.h
+++ b/ls_args.h
@@ -103,6 +103,7 @@ typedef struct ls_args_arg {
ls_args_type type;
void* val_ptr;
ls_args_mode mode;
+ int found;
} ls_args_arg;
typedef struct ls_args {
@@ -325,6 +326,7 @@ end:
}
void _lsa_apply(ls_args_arg* arg, ls_args_arg** prev_arg) {
+ arg->found = 1;
switch (arg->type) {
case LS_ARGS_TYPE_BOOL:
*(int*)arg->val_ptr = 1;
@@ -403,6 +405,11 @@ int ls_args_parse(ls_args* a, int argc, char** argv) {
ls_args_arg* prev_arg = NULL;
assert(a != NULL);
assert(argv != NULL);
+ a->last_error = "Success";
+ /* set all args to not found in case this is called multiple times */
+ for (i = 0; i < (int)a->args_len; ++i) {
+ a->args[i].found = 0;
+ }
for (i = 1; i < argc; ++i) {
_lsa_parsed parsed = _lsa_parse(argv[i]);
if (prev_arg) {
@@ -462,6 +469,19 @@ int ls_args_parse(ls_args* a, int argc, char** argv) {
a->last_error = a->_allocated_error;
return 0;
}
+
+ for (i = 0; i < (int)a->args_len; ++i) {
+ if (a->args[i].mode == LS_ARGS_REQUIRED && !a->args[i].found) {
+ const size_t len = 64 + strlen(a->args[i].long_opt);
+ a->_allocated_error = LS_REALLOC(a->_allocated_error, len);
+ memset(a->_allocated_error, 0, len);
+ sprintf(a->_allocated_error, "Required argument '--%s' not found",
+ a->args[i].long_opt);
+ a->last_error = a->_allocated_error;
+ return 0;
+ }
+ }
+
return 1;
}
diff --git a/tests/ls_test.h b/tests/ls_test.h
index 31d87f8..2077477 100644
--- a/tests/ls_test.h
+++ b/tests/ls_test.h
@@ -1,6 +1,6 @@
/* Lion's Standard (LS) test harness.
*
- * Version: 1.2
+ * Version: 1.3
* Website: https://libls.org
* Repo: https://github.com/libls/test
* SPDX-License-Identifier: MIT
@@ -20,6 +20,8 @@
* you use asserts other than `ASSERT` (e.g. ASSERT_EQ), and the constructor
* attribute __attribute__((destructor)) for automatic test registration.
*
+ * Supports string comparisons using ASSERT_STR_EQ and ASSERT_STR_NEQ.
+ *
* ==== 2. HOW TO USE ====
*
* 1. Copy this file into your project and include it:
@@ -119,6 +121,38 @@
} \
} while (0)
+#define ASSERT_STR_EQ(a, b) \
+ do { \
+ __typeof__(a) _a = (a); \
+ __typeof__(b) _b = (b); \
+ if (strcmp(_a, _b) != 0) { \
+ const char* _func = __func__; \
+ if (strncmp(_func, "lst_t_", 6) == 0) \
+ _func += 6; \
+ fprintf(stderr, \
+ "%s: FAILED: %s == %s (actual: \"%s\" != \"%s\") (%s:%d)\n", \
+ _func, #a, #b, _a, _b, __FILE__, __LINE__); \
+ ++lst_fail; \
+ return 1; \
+ } \
+ } while (0)
+
+#define ASSERT_STR_NEQ(a, b) \
+ do { \
+ __typeof__(a) _a = (a); \
+ __typeof__(b) _b = (b); \
+ if (strcmp(_a, _b) == 0) { \
+ const char* _func = __func__; \
+ if (strncmp(_func, "lst_t_", 6) == 0) \
+ _func += 6; \
+ fprintf(stderr, \
+ "%s: FAILED: %s != %s (actual: \"%s\" == \"%s\") (%s:%d)\n", \
+ _func, #a, #b, _a, _b, __FILE__, __LINE__); \
+ ++lst_fail; \
+ return 1; \
+ } \
+ } while (0)
+
#define ASSERT_NEQ(a, b, fmt) \
do { \
__typeof__(a) _a = (a); \
diff --git a/tests/tests.c b/tests/tests.c
index 8b22e06..74ddb3e 100644
--- a/tests/tests.c
+++ b/tests/tests.c
@@ -42,6 +42,29 @@ TEST_CASE(basic_args) {
return 0;
}
+TEST_CASE(basic_args_required) {
+ int help = 0;
+ int test = 0;
+ ls_args args;
+ char* argv[] = { "./hello", "-h", NULL };
+ int argc = sizeof(argv) / sizeof(*argv) - 1;
+
+ ls_args_init(&args);
+ ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
+ ls_args_bool(&args, &test, "t", "test", "A test argument", LS_ARGS_REQUIRED);
+ ASSERT(!ls_args_parse(&args, argc, argv));
+ ASSERT_STR_EQ(args.last_error, "Required argument '--test' not found");
+
+ char* argv2[] = { "./hello", "-h", "-t", NULL };
+ int argc2 = sizeof(argv2) / sizeof(*argv2) - 1;
+ int ret = ls_args_parse(&args, argc2, argv2);
+ ASSERT_STR_EQ(args.last_error, "Success");
+
+ ls_args_free(&args);
+ return 0;
+}
+
+
TEST_CASE(basic_args_only_short) {
int help = 0;
int test = 0;
@@ -120,7 +143,7 @@ TEST_CASE(error_invalid_argument) {
ls_args_init(&args);
ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
ASSERT(!ls_args_parse(&args, argc, argv));
- ASSERT(strcmp(args.last_error, "Invalid argument '--test'") == 0);
+ ASSERT_STR_EQ(args.last_error, "Invalid argument '--test'");
ls_args_free(&args);
return 0;
}
@@ -136,7 +159,7 @@ TEST_CASE(error_expected_argument) {
ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
ls_args_string(&args, &file, "f", "file", "File to work on", 0);
ASSERT(!ls_args_parse(&args, argc, argv));
- ASSERT(strcmp(args.last_error, "Expected argument following '--file'") == 0);
+ ASSERT_STR_EQ(args.last_error, "Expected argument following '--file'");
ls_args_free(&args);
return 0;
}
@@ -150,7 +173,7 @@ TEST_CASE(error_expected_argument_last_arg) {
ls_args_init(&args);
ls_args_string(&args, &file, "f", "file", "File to work on", 0);
ASSERT(!ls_args_parse(&args, argc, argv));
- ASSERT(strcmp(args.last_error, "Expected argument following '--file'") == 0);
+ ASSERT_STR_EQ(args.last_error, "Expected argument following '--file'");
ls_args_free(&args);
return 0;
}
@@ -166,7 +189,7 @@ TEST_CASE(error_expected_argument_short_combined) {
ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
ls_args_string(&args, &file, "f", "file", "File to work on", 0);
ASSERT(!ls_args_parse(&args, argc, argv));
- ASSERT(strcmp(args.last_error, "Expected argument following '-f', instead got another argument '-h'") == 0);
+ ASSERT_STR_EQ(args.last_error, "Expected argument following '-f', instead got another argument '-h'");
ls_args_free(&args);
return 0;
}
@@ -179,7 +202,7 @@ TEST_CASE(error_parse_fail) {
ls_args_init(&args);
ASSERT(!ls_args_parse(&args, argc, argv));
- ASSERT(strcmp(args.last_error, "Invalid argument '-'") == 0);
+ ASSERT_STR_EQ(args.last_error, "Invalid argument '-'");
ls_args_free(&args);
return 0;
}
@@ -245,7 +268,7 @@ TEST_CASE(alloc_fail) {
ret = ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
fail_alloc = 0;
ASSERT(!ret);
- ASSERT(strcmp(args.last_error, "Allocation failure") == 0);
+ ASSERT_STR_EQ(args.last_error, "Allocation failure");
/* there is no documented error state for this; we simply fail to add the
* argument? */
ASSERT_EQ(args.args_len, 0, "%uz");
@@ -261,7 +284,7 @@ TEST_CASE(error_parse_fail_empty) {
ls_args_init(&args);
ASSERT(!ls_args_parse(&args, argc, argv));
- ASSERT(strcmp(args.last_error, "Invalid argument ''") == 0);
+ ASSERT_STR_EQ(args.last_error, "Invalid argument ''");
ls_args_free(&args);
return 0;
}
@@ -287,7 +310,7 @@ TEST_CASE(error_invalid_argument_short) {
ls_args_init(&args);
ls_args_bool(&args, &help, "h", "help", "Provides help", 0);
ASSERT(!ls_args_parse(&args, argc, argv));
- ASSERT(strcmp(args.last_error, "Invalid argument '-t'") == 0);
+ ASSERT_STR_EQ(args.last_error, "Invalid argument '-t'");
ls_args_free(&args);
return 0;
}
@@ -306,8 +329,8 @@ TEST_CASE(string_args) {
ls_args_string(&args, &output, "o", "output", "Output file path", 0);
ls_args_bool(&args, &verbose, "v", "verbose", "Verbose output", 0);
ASSERT(ls_args_parse(&args, argc, argv));
- ASSERT(strcmp(input, "file.txt") == 0);
- ASSERT(strcmp(output, "output.txt") == 0);
+ ASSERT_STR_EQ(input, "file.txt");
+ ASSERT_STR_EQ(output, "output.txt");
ASSERT_EQ(verbose, 1, "%d");
ls_args_free(&args);
return 0;