ref: f9ddf46b12b9ee88e3b81f35f80e374722ca6f9d
dir: /parg/test/test_parg.c/
/*
* test_parg - parg unit test
*
* Written in 2015-2016 by Joergen Ibsen
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty. <http://creativecommons.org/publicdomain/zero/1.0/>
*/
#include "parg.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "greatest.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
static const char *os_def = ":no::r:";
static const struct parg_option po_def[] = {
{ "noarg", PARG_NOARG, NULL, 'n' },
{ "optarg", PARG_OPTARG, NULL, 'o' },
{ "reqarg", PARG_REQARG, NULL, 'r' },
{ "foo", PARG_NOARG, NULL, 'f' },
{ "foobar", PARG_NOARG, NULL, 'b' },
{ 0, 0, 0, 0 }
};
/*
* parg_getopt tests
*/
TEST parg_getopt_app_only(void)
{
struct parg_state ps;
char *argv[] = { "app" };
parg_init(&ps);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(1, ps.optind);
PASS();
}
TEST parg_getopt_dash(void)
{
struct parg_state ps;
char *argv[] = { "app", "-" };
parg_init(&ps);
ASSERT_EQ(1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(argv[1], ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_double_dash(void)
{
struct parg_state ps;
char *argv[] = { "app", "--" };
parg_init(&ps);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_nonopt(void)
{
struct parg_state ps;
char *argv[] = { "app", "foo" };
parg_init(&ps);
ASSERT_EQ(1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(argv[1], ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_no_match(void)
{
struct parg_state ps;
char *argv[] = { "app", "-u" };
parg_init(&ps);
ASSERT_EQ('?', parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ('u', ps.optopt);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_noarg(void)
{
struct parg_state ps;
char *argv[] = { "app", "-n" };
parg_init(&ps);
ASSERT_EQ('n', parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_optarg_missing(void)
{
struct parg_state ps;
char *argv[] = { "app", "-o" };
parg_init(&ps);
ASSERT_EQ('o', parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_optarg_inline(void)
{
struct parg_state ps;
char *argv[] = { "app", "-oarg" };
parg_init(&ps);
ASSERT_EQ('o', parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(&argv[1][2], ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_reqarg_missing(void)
{
struct parg_state ps;
char *argv[] = { "app", "-r" };
parg_init(&ps);
ASSERT_EQ(':', parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ('r', ps.optopt);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_reqarg_inline(void)
{
struct parg_state ps;
char *argv[] = { "app", "-rarg" };
parg_init(&ps);
ASSERT_EQ('r', parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(&argv[1][2], ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_reqarg_nextarg(void)
{
struct parg_state ps;
char *argv[] = { "app", "-r", "arg" };
parg_init(&ps);
ASSERT_EQ('r', parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(argv[2], ps.optarg);
ASSERT_EQ(3, ps.optind);
ASSERT_EQ(-1, parg_getopt(&ps, ARRAY_SIZE(argv), argv, os_def));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(3, ps.optind);
PASS();
}
/*
* parg_getopt_long tests
*/
TEST parg_getopt_long_app_only(void)
{
struct parg_state ps;
char *argv[] = { "app" };
int li = -1;
parg_init(&ps);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(1, ps.optind);
PASS();
}
TEST parg_getopt_long_dash(void)
{
struct parg_state ps;
char *argv[] = { "app", "-" };
int li = -1;
parg_init(&ps);
ASSERT_EQ(1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(argv[1], ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_double_dash(void)
{
struct parg_state ps;
char *argv[] = { "app", "--" };
int li = -1;
parg_init(&ps);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_nonopt(void)
{
struct parg_state ps;
char *argv[] = { "app", "foo" };
int li = -1;
parg_init(&ps);
ASSERT_EQ(1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(argv[1], ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_no_match(void)
{
struct parg_state ps;
char *argv[] = { "app", "--unknown" };
int li = -1;
parg_init(&ps);
ASSERT_EQ('?', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_flag(void)
{
struct parg_state ps;
char *argv[] = { "app", "--flag" };
int li = -1;
int flag = 0;
struct parg_option po_flag[] = {
{ "flag", PARG_NOARG, 0, 1 },
{ 0, 0, 0, 0 }
};
po_flag[0].flag = &flag;
parg_init(&ps);
ASSERT_EQ(0, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_flag, &li));
ASSERT_EQ(0, li);
ASSERT_EQ(1, flag);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_flag, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_noarg(void)
{
struct parg_state ps;
char *argv[] = { "app", "--noarg" };
int li = -1;
parg_init(&ps);
ASSERT_EQ('n', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(0, li);
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_noarg_inline(void)
{
struct parg_state ps;
char *argv[] = { "app", "--noarg=arg" };
int li = -1;
parg_init(&ps);
ASSERT_EQ(':', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(0, li);
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ('n', ps.optopt);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_optarg_missing(void)
{
struct parg_state ps;
char *argv[] = { "app", "--optarg" };
int li = -1;
parg_init(&ps);
ASSERT_EQ('o', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(1, li);
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_optarg_inline(void)
{
struct parg_state ps;
char *argv[] = { "app", "--optarg=arg" };
int li = -1;
parg_init(&ps);
ASSERT_EQ('o', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(1, li);
ASSERT_EQ(&argv[1][9], ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_reqarg_missing(void)
{
struct parg_state ps;
char *argv[] = { "app", "--reqarg" };
int li = -1;
parg_init(&ps);
ASSERT_EQ(':', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(2, li);
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ('r', ps.optopt);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_reqarg_inline(void)
{
struct parg_state ps;
char *argv[] = { "app", "--reqarg=arg" };
int li = -1;
parg_init(&ps);
ASSERT_EQ('r', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(2, li);
ASSERT_EQ(&argv[1][9], ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_reqarg_nextarg(void)
{
struct parg_state ps;
char *argv[] = { "app", "--reqarg", "arg" };
int li = -1;
parg_init(&ps);
ASSERT_EQ('r', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(2, li);
ASSERT_EQ(argv[2], ps.optarg);
ASSERT_EQ(3, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(3, ps.optind);
PASS();
}
TEST parg_getopt_long_prefix_ambiguous(void)
{
struct parg_state ps;
char *argv[] = { "app", "--fo" };
int li = -1;
parg_init(&ps);
ASSERT_EQ('?', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_prefix_exact(void)
{
struct parg_state ps;
char *argv[] = { "app", "--foo" };
int li = -1;
parg_init(&ps);
ASSERT_EQ('f', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(3, li);
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
TEST parg_getopt_long_prefix_unambiguous(void)
{
struct parg_state ps;
char *argv[] = { "app", "--foob" };
int li = -1;
parg_init(&ps);
ASSERT_EQ('b', parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(4, li);
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
ASSERT_EQ(-1, parg_getopt_long(&ps, ARRAY_SIZE(argv), argv, ":", po_def, &li));
ASSERT_EQ(NULL, ps.optarg);
ASSERT_EQ(2, ps.optind);
PASS();
}
/*
* parg_reorder tests
*/
TEST parg_reorder_short(void)
{
char *argv[] = {
"app", "first", "-r", "--", "foo", "-u", "bar", "-o", "--",
"-n", "last"
};
char *argv_expected[] = {
"app", "-r", "--", "-u", "-o", "--", "first", "foo", "bar",
"-n", "last"
};
size_t i;
ASSERT_EQ(6, parg_reorder(ARRAY_SIZE(argv), argv, os_def, NULL));
for (i = 0; i < ARRAY_SIZE(argv); ++i) {
ASSERT_STR_EQ(argv_expected[i], argv[i]);
}
PASS();
}
TEST parg_reorder_long(void)
{
char *argv[] = {
"app", "first", "--reqarg", "--", "foo", "--unknown", "bar",
"--optarg", "--", "--noarg", "last"
};
char *argv_expected[] = {
"app", "--reqarg", "--", "--unknown", "--optarg", "--",
"first", "foo", "bar", "--noarg", "last"
};
size_t i;
ASSERT_EQ(6, parg_reorder(ARRAY_SIZE(argv), argv, "", po_def));
for (i = 0; i < ARRAY_SIZE(argv); ++i) {
ASSERT_STR_EQ(argv_expected[i], argv[i]);
}
PASS();
}
TEST parg_reorder_app_only(void)
{
char *argv[] = { "app" };
ASSERT_EQ(1, parg_reorder(ARRAY_SIZE(argv), argv, os_def, NULL));
PASS();
}
TEST parg_reorder_double_dash_last(void)
{
char *argv[] = { "app", "foo", "-n", "--" };
char *argv_expected[] = { "app", "-n", "--", "foo" };
size_t i;
ASSERT_EQ(3, parg_reorder(ARRAY_SIZE(argv), argv, os_def, NULL));
for (i = 0; i < ARRAY_SIZE(argv); ++i) {
ASSERT_STR_EQ(argv_expected[i], argv[i]);
}
PASS();
}
TEST parg_reorder_missing_arg_last(void)
{
char *argv[] = { "app", "foo", "-r" };
char *argv_expected[] = { "app", "-r", "foo" };
size_t i;
ASSERT_EQ(2, parg_reorder(ARRAY_SIZE(argv), argv, os_def, NULL));
for (i = 0; i < ARRAY_SIZE(argv); ++i) {
ASSERT_STR_EQ(argv_expected[i], argv[i]);
}
PASS();
}
SUITE(parg_getopt_tests)
{
RUN_TEST(parg_getopt_app_only);
RUN_TEST(parg_getopt_dash);
RUN_TEST(parg_getopt_double_dash);
RUN_TEST(parg_getopt_nonopt);
RUN_TEST(parg_getopt_no_match);
RUN_TEST(parg_getopt_noarg);
RUN_TEST(parg_getopt_optarg_missing);
RUN_TEST(parg_getopt_optarg_inline);
RUN_TEST(parg_getopt_reqarg_missing);
RUN_TEST(parg_getopt_reqarg_inline);
RUN_TEST(parg_getopt_reqarg_nextarg);
}
SUITE(parg_getopt_long_tests)
{
RUN_TEST(parg_getopt_long_app_only);
RUN_TEST(parg_getopt_long_dash);
RUN_TEST(parg_getopt_long_double_dash);
RUN_TEST(parg_getopt_long_nonopt);
RUN_TEST(parg_getopt_long_no_match);
RUN_TEST(parg_getopt_long_flag);
RUN_TEST(parg_getopt_long_noarg);
RUN_TEST(parg_getopt_long_noarg_inline);
RUN_TEST(parg_getopt_long_optarg_missing);
RUN_TEST(parg_getopt_long_optarg_inline);
RUN_TEST(parg_getopt_long_reqarg_missing);
RUN_TEST(parg_getopt_long_reqarg_inline);
RUN_TEST(parg_getopt_long_reqarg_nextarg);
RUN_TEST(parg_getopt_long_prefix_ambiguous);
RUN_TEST(parg_getopt_long_prefix_exact);
RUN_TEST(parg_getopt_long_prefix_unambiguous);
}
SUITE(parg_reorder_tests)
{
RUN_TEST(parg_reorder_short);
RUN_TEST(parg_reorder_long);
RUN_TEST(parg_reorder_app_only);
RUN_TEST(parg_reorder_double_dash_last);
RUN_TEST(parg_reorder_missing_arg_last);
}
GREATEST_MAIN_DEFS();
int main(int argc, char *argv[])
{
GREATEST_MAIN_BEGIN();
RUN_SUITE(parg_getopt_tests);
RUN_SUITE(parg_getopt_long_tests);
RUN_SUITE(parg_reorder_tests);
GREATEST_MAIN_END();
}