Skip to content

Commit c5c640b

Browse files
committed
add sub command test and example
1 parent 1509171 commit c5c640b

File tree

12 files changed

+177
-156
lines changed

12 files changed

+177
-156
lines changed

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
build/
1+
CMakeCache.txt
2+
CMakeFiles/
3+
cmake_install.cmake
24
tags
3-
test_argparse
45
*.[ao]
56
*.dylib
67
*.so

CMakeLists.txt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,3 @@ endif()
2626
if(NOT (ARGPARSE_STATIC OR ARGPARSE_SHARED))
2727
add_library(argparse OBJECT ${sources})
2828
endif()
29-
30-
option(ENABLE_TESTS "Enable tests" OFF)
31-
if((ENABLE_TESTS OR CMAKE_TESTING_ENABLED) AND UNIX)
32-
enable_testing()
33-
34-
add_executable(test_argparse test_argparse.c ${sources})
35-
add_test(NAME argparse_test COMMAND ${CMAKE_SOURCE_DIR}/test.sh)
36-
add_custom_command(
37-
TARGET test_argparse
38-
COMMENT "Running tests"
39-
POST_BUILD WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
40-
COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --output-on-failures)
41-
endif()

Makefile

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ endif
2929
all: $(DYLIBNAME) $(STLIBNAME)
3030

3131
OBJS += argparse.o
32-
OBJS += test_argparse.o
3332

3433
$(OBJS): %.o: %.c argparse.h
3534
$(CROSS_COMPILE)gcc -o $*.o -c $(ALL_CFLAGS) $<
@@ -40,15 +39,11 @@ $(DYLIBNAME): argparse.o
4039
$(STLIBNAME): argparse.o
4140
$(STLIB_MAKE_CMD) $^
4241

43-
test: test_argparse
44-
@echo "###### Unit Test #####"
45-
@./test.sh
46-
47-
test_argparse: $(OBJS)
48-
$(CROSS_COMPILE)gcc $(ALL_CFLAGS) -o $@ $^ $(ALL_LDFLAGS)
42+
test:
43+
make -C tests/ test
4944

5045
clean:
51-
rm -rf test_argparse
5246
rm -rf *.[ao]
5347
rm -rf *.so
5448
rm -rf *.dylib
49+
make -C tests/ clean

README.md

Lines changed: 5 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
# argparse [![Build Status](https://travis-ci.org/cofyc/argparse.png)](https://travis-ci.org/cofyc/argparse)
1+
# argparse
2+
3+
[![Build Status](https://github.com/cofyc/argparse/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/cofyc/argparse/actions/workflows/ci.yaml)
24

35
argparse - A command line arguments parsing library in C (compatible with C++).
46

@@ -41,64 +43,5 @@ Options and non-option arguments can clearly be separated using the `--` option.
4143

4244
## Examples
4345

44-
```c
45-
#include <stdio.h>
46-
#include "argparse.h"
47-
48-
static const char *const usage[] = {
49-
"test_argparse [options] [[--] args]",
50-
"test_argparse [options]",
51-
NULL,
52-
};
53-
54-
#define PERM_READ (1<<0)
55-
#define PERM_WRITE (1<<1)
56-
#define PERM_EXEC (1<<2)
57-
58-
int
59-
main(int argc, const char **argv)
60-
{
61-
int force = 0;
62-
int test = 0;
63-
int num = 0;
64-
const char *path = NULL;
65-
int perms = 0;
66-
struct argparse_option options[] = {
67-
OPT_HELP(),
68-
OPT_GROUP("Basic options"),
69-
OPT_BOOLEAN('f', "force", &force, "force to do"),
70-
OPT_BOOLEAN('t', "test", &test, "test only"),
71-
OPT_STRING('p', "path", &path, "path to read"),
72-
OPT_INTEGER('n', "num", &num, "selected num"),
73-
OPT_GROUP("Bits options"),
74-
OPT_BIT(0, "read", &perms, "read perm", NULL, PERM_READ, OPT_NONEG),
75-
OPT_BIT(0, "write", &perms, "write perm", NULL, PERM_WRITE),
76-
OPT_BIT(0, "exec", &perms, "exec perm", NULL, PERM_EXEC),
77-
OPT_END(),
78-
};
79-
80-
struct argparse argparse;
81-
argparse_init(&argparse, options, usage, 0);
82-
argparse_describe(&argparse, "\nA brief description of what the program does and how it works.", "\nAdditional description of the program after the description of the arguments.");
83-
argc = argparse_parse(&argparse, argc, argv);
84-
if (force != 0)
85-
printf("force: %d\n", force);
86-
if (test != 0)
87-
printf("test: %d\n", test);
88-
if (path != NULL)
89-
printf("path: %s\n", path);
90-
if (num != 0)
91-
printf("num: %d\n", num);
92-
if (argc != 0) {
93-
printf("argc: %d\n", argc);
94-
int i;
95-
for (i = 0; i < argc; i++) {
96-
printf("argv[%d]: %s\n", i, *(argv + i));
97-
}
98-
}
99-
if (perms) {
100-
printf("perms: %d\n", perms);
101-
}
102-
return 0;
103-
}
104-
```
46+
- [basic](tests/basic.c)
47+
- [subcommands](tests/subcommands.c)

test.sh

Lines changed: 0 additions & 69 deletions
This file was deleted.

tests/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
basic
2+
subcommands

tests/Makefile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
all:: test
2+
3+
OBJS += $(patsubst %.c,%,$(wildcard *.c))
4+
5+
${OBJS}: %: %.c ../argparse.c
6+
$(CC) -I../ -o $@ ${DEP_LIBS} $^
7+
8+
test: ${OBJS}
9+
prove *.sh
10+
.PHONY: test
11+
12+
clean:
13+
rm -f ${OBJS}
14+
find . -name '.o' -exec rm \;
15+
.PHONY: clean

test_argparse.c renamed to tests/basic.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
#include "argparse.h"
55

66
static const char *const usages[] = {
7-
"test_argparse [options] [[--] args]",
8-
"test_argparse [options]",
7+
"basic [options] [[--] args]",
8+
"basic [options]",
99
NULL,
1010
};
1111

tests/basic.sh

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/bin/bash
2+
3+
. $(dirname ${BASH_SOURCE[0]})/tap-functions
4+
plan_no_plan
5+
6+
is "$(./basic -f --path=/path/to/file a 2>&1)" 'force: 1
7+
path: /path/to/file
8+
argc: 1
9+
argv[0]: a'
10+
11+
is "$(./basic -f -f --force --no-force 2>&1)" 'force: 2'
12+
13+
is "$(./basic -i 2>&1)" 'error: option `-i` requires a value'
14+
15+
is "$(./basic -i 2 2>&1)" 'int_num: 2'
16+
17+
is "$(./basic -i2 2>&1)" 'int_num: 2'
18+
19+
is "$(./basic -ia 2>&1)" 'error: option `-i` expects an integer value'
20+
21+
is "$(./basic -i 0xFFFFFFFFFFFFFFFFF 2>&1)" \
22+
'error: option `-i` numerical result out of range'
23+
24+
is "$(./basic -s 2.4 2>&1)" 'flt_num: 2.4'
25+
26+
is "$(./basic -s2.4 2>&1)" 'flt_num: 2.4'
27+
28+
is "$(./basic -sa 2>&1)" 'error: option `-s` expects a numerical value'
29+
30+
is "$(./basic -s 1e999 2>&1)" \
31+
'error: option `-s` numerical result out of range'
32+
33+
is "$(./basic -f -- do -f -h 2>&1)" 'force: 1
34+
argc: 3
35+
argv[0]: do
36+
argv[1]: -f
37+
argv[2]: -h'
38+
39+
is "$(./basic -tf 2>&1)" 'force: 1
40+
test: 1'
41+
42+
is "$(./basic --read --write 2>&1)" 'perms: 3'
43+
44+
help_usage='Usage: basic [options] [[--] args]
45+
or: basic [options]
46+
47+
A brief description of what the program does and how it works.
48+
49+
-h, --help show this help message and exit
50+
51+
Basic options
52+
-f, --force force to do
53+
-t, --test test only
54+
-p, --path=<str> path to read
55+
-i, --int=<int> selected integer
56+
-s, --float=<flt> selected float
57+
58+
Bits options
59+
--read read perm
60+
--write write perm
61+
--exec exec perm
62+
63+
Additional description of the program after the description of the arguments.'
64+
65+
is "$(./basic -h)" "$help_usage"
66+
67+
is "$(./basic --help)" "$help_usage"
68+
69+
is "$(./basic --no-help 2>&1)" 'error: unknown option `--no-help`'$'\n'"$help_usage"

tests/subcommands.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include "argparse.h"
5+
6+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
7+
8+
static const char *const usages[] = {
9+
"subcommands [options] [cmd] [args]",
10+
NULL,
11+
};
12+
13+
struct cmd_struct {
14+
const char *cmd;
15+
int len;
16+
int (*fn) (int, const char **);
17+
const char *help;
18+
};
19+
20+
int
21+
cmd_foo(int argc, const char **argv)
22+
{
23+
printf("executing subcommand foo\n");
24+
for (int i = 0; i < argc; i++) {
25+
printf("argv[%d]: %s\n", i, *(argv + i));
26+
}
27+
return 0;
28+
}
29+
30+
int
31+
cmd_bar(int argc, const char **argv)
32+
{
33+
printf("executing subcommand bar\n");
34+
for (int i = 0; i < argc; i++) {
35+
printf("argv[%d]: %s\n", i, *(argv + i));
36+
}
37+
return 0;
38+
}
39+
40+
static struct cmd_struct commands[] = {
41+
{"foo", 3, cmd_foo, NULL},
42+
{"bar", 3, cmd_bar, NULL},
43+
};
44+
45+
int
46+
main(int argc, const char **argv)
47+
{
48+
struct argparse argparse;
49+
struct argparse_option options[] = {
50+
OPT_HELP(),
51+
OPT_END(),
52+
};
53+
argparse_init(&argparse, options, usages, 0);
54+
argc = argparse_parse(&argparse, argc, argv);
55+
if (argc < 1) {
56+
argparse_usage(&argparse);
57+
return -1;
58+
}
59+
60+
/* Try to run command with args provided. */
61+
struct cmd_struct *cmd = NULL;
62+
for (int i = 0; i < ARRAY_SIZE(commands); i++) {
63+
if (!strcmp(commands[i].cmd, argv[0])) {
64+
cmd = &commands[i];
65+
}
66+
}
67+
if (cmd) {
68+
return cmd->fn(argc, argv);
69+
}
70+
return 0;
71+
}

0 commit comments

Comments
 (0)