HelenOS sources

root/uspace/lib/c/test/getopt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PCUT_TEST
  2. PCUT_TEST
  3. PCUT_TEST
  4. PCUT_TEST
  5. PCUT_TEST
  6. PCUT_TEST
  7. PCUT_TEST
  8. PCUT_TEST
  9. PCUT_TEST
  10. PCUT_TEST
  11. PCUT_TEST
  12. PCUT_TEST
  13. PCUT_TEST
  14. PCUT_TEST
  15. PCUT_TEST
  16. PCUT_TEST
  17. PCUT_TEST

/*
 * Copyright (c) 2019 Matthieu Riolo
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - The name of the author may not be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <pcut/pcut.h>
#include <getopt.h>
#include <stdio.h>

PCUT_INIT;

PCUT_TEST_SUITE(getopt);

PCUT_TEST(getopt_param_flag)
{
        int argc = 4;
        const char *argv[] = {
                "get_opt_test",
                "-f",
                "-p",
                "param",
        };

        const char *options = "fp:";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('p', ret);
        PCUT_ASSERT_INT_EQUALS(4, optind);
        PCUT_ASSERT_STR_EQUALS("param", optarg);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_concat_flags)
{
        int argc = 2;
        const char *argv[] = {
                "get_opt_test",
                "-fda",
        };

        const char *options = "afd";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(1, optind);

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('d', ret);
        PCUT_ASSERT_INT_EQUALS(1, optind);

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('a', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_concat_flag_param)
{
        int argc = 3;
        const char *argv[] = {
                "get_opt_test",
                "-fp",
                "param"
        };

        const char *options = "fp:";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(1, optind);

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('p', ret);
        PCUT_ASSERT_INT_EQUALS(3, optind);
        PCUT_ASSERT_STR_EQUALS("param", optarg);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_missing_param1)
{
        int argc = 2;
        const char *argv[] = {
                "get_opt_test",
                "-p",
        };

        const char *options = "p:";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('?', ret);
        PCUT_ASSERT_INT_EQUALS('p', optopt);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_missing_param2)
{
        int argc = 2;
        const char *argv[] = {
                "get_opt_test",
                "-p",
        };

        const char *options = ":p:";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS(':', ret);
        PCUT_ASSERT_INT_EQUALS('p', optopt);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_illegal_option)
{
        int argc = 2;
        const char *argv[] = {
                "get_opt_test",
                "-p",
        };

        const char *options = "a";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('?', ret);
        PCUT_ASSERT_INT_EQUALS('p', optopt);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);

        options = ":a";
        optreset = 1;
        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS(-1, ret);
        PCUT_ASSERT_INT_EQUALS('p', optopt);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_flag_with_param)
{
        int argc = 4;
        const char *argv[] = {
                "get_opt_test",
                "-f",
                "param",
                "-d"
        };

        const char *options = "fd";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        /* getopt() would print a error message but thx to opterror=0 it doesnt */
        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('d', ret);
        PCUT_ASSERT_INT_EQUALS(4, optind);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_case_sensitive)
{
        int argc = 3;
        const char *argv[] = {
                "get_opt_test",
                "-F",
                "-f"
        };

        const char *options = "fF";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('F', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(3, optind);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_optional_param)
{
        int argc = 4;
        const char *argv[] = {
                "get_opt_test",
                "-f",
                "-pparam"
        };

        const char *options = "f::p::";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);
        PCUT_ASSERT_NULL(optarg);

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('p', ret);
        PCUT_ASSERT_INT_EQUALS(3, optind);
        PCUT_ASSERT_STR_EQUALS("param", optarg);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_special_option)
{
        int argc = 4;
        const char *argv[] = {
                "get_opt_test",
                "-f",
                "--",
                "-p"
        };

        const char *options = "fp";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_gnu_plus)
{
        int argc = 4;
        const char *argv[] = {
                "get_opt_test",
                "-f",
                "break",
                "-p"
        };

        const char *options = "+fp";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_gnu_minus)
{
        int argc = 4;
        const char *argv[] = {
                "get_opt_test",
                "-f",
                "break",
                "-p"
        };

        const char *options = "-fp";

        int ret;
        optreset = 1;
        opterr = 0;

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS(1, ret);
        PCUT_ASSERT_INT_EQUALS(3, optind);
        PCUT_ASSERT_STR_EQUALS("break", optarg);

        ret = getopt(argc, (char *const *)argv, options);

        PCUT_ASSERT_INT_EQUALS('p', ret);
        PCUT_ASSERT_INT_EQUALS(4, optind);

        ret = getopt(argc, (char *const *)argv, options);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_long_flag_param)
{
        int argc = 4;
        const char *argv[] = {
                "get_opt_test",
                "--flag",
                "--parameter",
                "param"
        };

        const char *options = "fp:";

        const struct option long_options[] = {
                { "flag", no_argument, NULL, 'f' },
                { "parameter", required_argument, NULL, 'p' },
        };

        int ret;
        int idx;
        optreset = 1;
        opterr = 0;

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);
        PCUT_ASSERT_INT_EQUALS(0, idx);

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS('p', ret);
        PCUT_ASSERT_INT_EQUALS(4, optind);
        PCUT_ASSERT_INT_EQUALS(1, idx);
        PCUT_ASSERT_STR_EQUALS("param", optarg);

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_long_alt_param)
{
        int argc = 3;
        const char *argv[] = {
                "get_opt_test",
                "--flag=\"param param\"",
                "--parameter=param",
        };

        const char *options = "f:p:";

        const struct option long_options[] = {
                { "flag", required_argument, NULL, 'f' },
                { "parameter", required_argument, NULL, 'p' },
                { 0, 0, 0, 0 }
        };

        int ret;
        int idx;
        optreset = 1;
        opterr = 0;

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);
        PCUT_ASSERT_INT_EQUALS(0, idx);
        PCUT_ASSERT_STR_EQUALS("\"param param\"", optarg);

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS('p', ret);
        PCUT_ASSERT_INT_EQUALS(3, optind);
        PCUT_ASSERT_INT_EQUALS(1, idx);
        PCUT_ASSERT_STR_EQUALS("param", optarg);

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_long_optional_param)
{
        int argc = 3;
        const char *argv[] = {
                "get_opt_test",
                "--flag=param",
                "--parameter",
        };

        const char *options = "f::p::";

        const struct option long_options[] = {
                { "flag", optional_argument, NULL, 'f' },
                { "parameter", optional_argument, NULL, 'p' },
                { 0, 0, 0, 0 }
        };

        int ret;
        int idx;
        optreset = 1;
        opterr = 0;

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS('f', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);
        PCUT_ASSERT_INT_EQUALS(0, idx);
        PCUT_ASSERT_STR_EQUALS("param", optarg);

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS('p', ret);
        PCUT_ASSERT_INT_EQUALS(3, optind);
        PCUT_ASSERT_INT_EQUALS(1, idx);
        PCUT_ASSERT_NULL(optarg);

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_long_illegal_option)
{
        int argc = 3;
        const char *argv[] = {
                "get_opt_test",
                "--param",
                "param",
        };

        const char *options = "f::";

        const struct option long_options[] = {
                { "cflag", required_argument, NULL, 'c' },
                { "flag", required_argument, NULL, 'f' },
                { 0, 0, 0, 0 }
        };

        int ret;
        int idx;
        optreset = 1;
        opterr = 0;

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS('?', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);
        PCUT_ASSERT_INT_EQUALS(0, idx);
        PCUT_ASSERT_INT_EQUALS(0, optopt);

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_TEST(getopt_long_ambiguous_param)
{
        int argc = 3;
        const char *argv[] = {
                "get_opt_test",
                "--flag",
                "param",
        };

        const char *options = "f::";

        const struct option long_options[] = {
                { "flag1", optional_argument, NULL, 'f' },
                { "flag2", required_argument, NULL, 'f' },
                { 0, 0, 0, 0 }
        };

        int ret;
        int idx;
        optreset = 1;
        opterr = 0;

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS('?', ret);
        PCUT_ASSERT_INT_EQUALS(2, optind);
        PCUT_ASSERT_INT_EQUALS(0, idx);
        PCUT_ASSERT_INT_EQUALS(0, optopt);

        ret = getopt_long(argc, (char *const *)argv, options, long_options, &idx);
        PCUT_ASSERT_INT_EQUALS(-1, ret);
}

PCUT_EXPORT(getopt);

/* [<][>][^][v][top][bottom][index][help] */
HelenOS homepage, sources at GitHub