LCOV - code coverage report
Current view: top level - tests/ctest - test_opts.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 507 511 99.2 %
Date: 2019-09-12 12:28:41 Functions: 23 23 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include <kdberrors.h>
      10             : #include <kdbopts.h>
      11             : 
      12             : #include "tests.h"
      13             : 
      14             : #define PROC_BASE_KEY "proc/tests/opts"
      15             : #define SPEC_BASE_KEY "spec/tests/opts"
      16             : 
      17             : // version 6 and 7 of clang-format don't agree whether it is supposed to be *[] or * [] so disable it here
      18             : // TODO: re-enable clang-format once version 7 is used on build server
      19             : // clang-format off
      20             : #define NUMARGS(...) (sizeof ((void *[]){ __VA_ARGS__ }) / sizeof (void *))
      21             : #define ARGS(...) NUMARGS ("prog", __VA_ARGS__), ((const char *[]){ "prog", __VA_ARGS__, NULL })
      22             : #define NO_ARGS 1, ((const char *[]){ "prog" })
      23             : 
      24             : #define ENVP(...) ((const char *[]){ __VA_ARGS__, NULL })
      25             : #define NO_ENVP ((const char *[]){ NULL })
      26             : // clang-format on
      27             : 
      28             : #define xstr(a) str (a)
      29             : #define str(a) #a
      30             : 
      31             : #define RUN_TEST(ks, args, envp)                                                                                                           \
      32             :         {                                                                                                                                  \
      33             :                 Key * ek = keyNew (SPEC_BASE_KEY, KEY_END);                                                                                \
      34             :                 if (elektraGetOpts (ks, args, envp, ek) != 0)                                                                              \
      35             :                 {                                                                                                                          \
      36             :                         yield_error ("error found");                                                                                       \
      37             :                         output_error (ek);                                                                                                 \
      38             :                 }                                                                                                                          \
      39             :                 keyDel (ek);                                                                                                               \
      40             :         }
      41             : 
      42             : #define RUN_TEST_ERROR(ks, errorKey, args, envp)                                                                                           \
      43             :         {                                                                                                                                  \
      44             :                 errorKey = keyNew (SPEC_BASE_KEY, KEY_END);                                                                                \
      45             :                 if (elektraGetOpts (ks, args, envp, errorKey) >= 0)                                                                        \
      46             :                 {                                                                                                                          \
      47             :                         yield_error ("should have failed");                                                                                \
      48             :                 }                                                                                                                          \
      49             :         }
      50             : 
      51             : #ifdef _WIN32
      52             : #define ENV_SEP ";"
      53             : #else
      54             : #define ENV_SEP ":"
      55             : #endif
      56             : 
      57             : #define checkHelpMessage(errorKey, expected)                                                                                               \
      58             :         {                                                                                                                                  \
      59             :                 char * actual = elektraGetOptsHelpMessage (errorKey, NULL, NULL);                                                          \
      60             :                 succeed_if_same_string (actual, expected);                                                                                 \
      61             :                 elektraFree (actual);                                                                                                      \
      62             :         }
      63             : 
      64          36 : static inline Key * keyWithOpt (const char * name, const char shortOpt, const char * longOpt, const char * envVar)
      65             : {
      66          36 :         return keyNew (name, KEY_META, "opt", (const char[]){ shortOpt, '\0' }, KEY_META, "opt/long", longOpt, KEY_META, "env", envVar,
      67             :                        KEY_END);
      68             : }
      69             : 
      70         168 : static bool checkValue (KeySet * ks, const char * name, const char * expected)
      71             : {
      72         168 :         Key * key = ksLookupByName (ks, name, 0);
      73         168 :         if (key == NULL)
      74             :         {
      75          10 :                 return expected == NULL;
      76             :         }
      77             : 
      78         158 :         const char * actual = keyString (key);
      79         158 :         return expected == NULL ? strlen (actual) == 0 : strcmp (actual, expected) == 0;
      80             : }
      81             : 
      82          10 : static bool checkMeta (KeySet * ks, const char * name, const char * meta, const char * expected)
      83             : {
      84          10 :         Key * key = ksLookupByName (ks, name, 0);
      85          10 :         if (key == NULL)
      86             :         {
      87           0 :                 return expected == NULL;
      88             :         }
      89             : 
      90          10 :         const Key * metaKey = keyGetMeta (key, meta);
      91          10 :         if (metaKey == NULL)
      92             :         {
      93           0 :                 return expected == NULL;
      94             :         }
      95             : 
      96          10 :         const char * actual = keyString (metaKey);
      97          10 :         return expected == NULL ? strlen (actual) == 0 : strcmp (actual, expected) == 0;
      98             : }
      99             : 
     100          46 : static bool checkError (Key * errorKey, const char * expectedNumber, const char * expectedReason)
     101             : {
     102          46 :         const Key * metaError = keyGetMeta (errorKey, "error");
     103          46 :         if (metaError == NULL)
     104             :         {
     105             :                 return false;
     106             :         }
     107             : 
     108          46 :         const char * actualNumber = keyString (keyGetMeta (errorKey, "error/number"));
     109          46 :         const char * actualReason = keyString (keyGetMeta (errorKey, "error/reason"));
     110             : 
     111          46 :         bool result = strcmp (actualNumber, expectedNumber) == 0 && strcmp (actualReason, expectedReason) == 0;
     112             : 
     113          46 :         keyDel (errorKey);
     114             : 
     115          46 :         return result;
     116             : }
     117             : 
     118         166 : static void clearValues (KeySet * ks)
     119             : {
     120         166 :         cursor_t cursor = ksGetCursor (ks);
     121             : 
     122         166 :         ksRewind (ks);
     123             :         Key * cur;
     124         716 :         while ((cur = ksNext (ks)) != NULL)
     125             :         {
     126         384 :                 keySetString (cur, NULL);
     127         384 :                 keySetMeta (cur, "array", NULL);
     128             :         }
     129             : 
     130         166 :         ksSetCursor (ks, cursor);
     131         166 : }
     132             : 
     133           2 : static void test_simple (void)
     134             : {
     135           2 :         KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", "APPLE"), KS_END);
     136             : 
     137           2 :         RUN_TEST (ks, NO_ARGS, NO_ENVP);
     138           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", NULL), "no option failed");
     139           2 :         clearValues (ks);
     140             : 
     141           2 :         RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
     142           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option failed");
     143           2 :         clearValues (ks);
     144             : 
     145           2 :         RUN_TEST (ks, ARGS ("-ashort"), NO_ENVP);
     146           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option (combined) failed");
     147           2 :         clearValues (ks);
     148             : 
     149           2 :         RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
     150           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option failed");
     151           2 :         clearValues (ks);
     152             : 
     153           2 :         RUN_TEST (ks, ARGS ("--apple=long"), NO_ENVP);
     154           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
     155           2 :         clearValues (ks);
     156             : 
     157           2 :         RUN_TEST (ks, NO_ARGS, ENVP ("APPLE=env"));
     158           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "env"), "env-var failed");
     159           2 :         clearValues (ks);
     160             : 
     161           2 :         ksDel (ks);
     162           2 : }
     163             : 
     164           2 : static void test_short_only (void)
     165             : {
     166           2 :         KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', NULL, NULL), KS_END);
     167             : 
     168           2 :         RUN_TEST (ks, NO_ARGS, NO_ENVP);
     169           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", NULL), "no option failed");
     170           2 :         clearValues (ks);
     171             : 
     172           2 :         RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
     173           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option failed");
     174           2 :         clearValues (ks);
     175             : 
     176           2 :         RUN_TEST (ks, ARGS ("-ashort"), NO_ENVP);
     177           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option (combined) failed");
     178           2 :         clearValues (ks);
     179             : 
     180           2 :         ksDel (ks);
     181           2 : }
     182             : 
     183           2 : static void test_long_only (void)
     184             : {
     185           2 :         KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 0, "apple", NULL), KS_END);
     186             : 
     187           2 :         RUN_TEST (ks, NO_ARGS, NO_ENVP);
     188           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", NULL), "no option failed");
     189           2 :         clearValues (ks);
     190             : 
     191           2 :         RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
     192           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option failed");
     193           2 :         clearValues (ks);
     194             : 
     195           2 :         RUN_TEST (ks, ARGS ("--apple=long"), NO_ENVP);
     196           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
     197           2 :         clearValues (ks);
     198             : 
     199           2 :         ksDel (ks);
     200           2 : }
     201             : 
     202           2 : static void test_env_only (void)
     203             : {
     204           2 :         KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 0, NULL, "APPLE"), KS_END);
     205             : 
     206           2 :         RUN_TEST (ks, NO_ARGS, NO_ENVP);
     207           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", NULL), "no option failed");
     208           2 :         clearValues (ks);
     209             : 
     210           2 :         RUN_TEST (ks, NO_ARGS, ENVP ("APPLE=env"));
     211           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "env"), "env-var failed");
     212           2 :         clearValues (ks);
     213             : 
     214           2 :         ksDel (ks);
     215           2 : }
     216             : 
     217           2 : static void test_flag (void)
     218             : {
     219           2 :         Key * k = keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL);
     220           2 :         keySetMeta (k, "opt/arg", "none");
     221           2 :         KeySet * ks = ksNew (1, k, KS_END);
     222             : 
     223           2 :         RUN_TEST (ks, ARGS ("-a"), NO_ENVP);
     224           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "short flag failed");
     225           2 :         clearValues (ks);
     226             : 
     227           2 :         RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
     228           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "short flag (with arg) failed");
     229           2 :         clearValues (ks);
     230             : 
     231             :         Key * errorKey;
     232           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("-ashort"), NO_ENVP);
     233           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Unknown short option: -s"),
     234             :                     "short flag (with arg, combined) should have failed");
     235           2 :         clearValues (ks);
     236             : 
     237           2 :         RUN_TEST (ks, ARGS ("--apple"), NO_ENVP);
     238           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "long flag failed");
     239           2 :         clearValues (ks);
     240             : 
     241           2 :         RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
     242           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "long flag (with arg) failed");
     243           2 :         clearValues (ks);
     244             : 
     245           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple=long"), NO_ENVP);
     246           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot have an argument: --apple"),
     247             :                     "long flag (with arg, combined) should have failed");
     248           2 :         clearValues (ks);
     249             : 
     250           2 :         ksDel (ks);
     251           2 : }
     252             : 
     253           2 : static void test_flag_value (void)
     254             : {
     255           2 :         Key * k = keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL);
     256           2 :         keySetMeta (k, "opt/arg", "none");
     257           2 :         keySetMeta (k, "opt/flagvalue", "set");
     258           2 :         KeySet * ks = ksNew (1, k, KS_END);
     259             : 
     260           2 :         RUN_TEST (ks, ARGS ("-a"), NO_ENVP);
     261           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "short flag with value failed");
     262           2 :         clearValues (ks);
     263             : 
     264           2 :         RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
     265           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "short flag with value (with arg) failed");
     266           2 :         clearValues (ks);
     267             : 
     268             :         Key * errorKey;
     269           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("-ashort"), NO_ENVP);
     270           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Unknown short option: -s"),
     271             :                     "short flag with value (with arg, combined) should have failed");
     272           2 :         clearValues (ks);
     273             : 
     274           2 :         RUN_TEST (ks, ARGS ("--apple"), NO_ENVP);
     275           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "long flag with value failed");
     276           2 :         clearValues (ks);
     277             : 
     278           2 :         RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
     279           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "long flag with value (with arg) failed");
     280           2 :         clearValues (ks);
     281             : 
     282           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple=long"), NO_ENVP);
     283           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot have an argument: --apple"),
     284             :                     "long flag with value (with arg, combined) should have failed");
     285           2 :         clearValues (ks);
     286             : 
     287           2 :         ksDel (ks);
     288           2 : }
     289             : 
     290           2 : static void test_optional (void)
     291             : {
     292           2 :         Key * k = keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL);
     293           2 :         keySetMeta (k, "opt/arg", "optional");
     294           2 :         KeySet * ks = ksNew (1, k, KS_END);
     295             : 
     296           2 :         RUN_TEST (ks, ARGS ("-a"), NO_ENVP);
     297           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "short flag failed");
     298           2 :         clearValues (ks);
     299             : 
     300           2 :         RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
     301           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "short flag (with arg) failed");
     302           2 :         clearValues (ks);
     303             : 
     304             :         Key * errorKey;
     305           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("-ashort"), NO_ENVP);
     306           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Unknown short option: -s"),
     307             :                     "short flag (with arg, combined) should have failed");
     308           2 :         clearValues (ks);
     309             : 
     310           2 :         RUN_TEST (ks, ARGS ("--apple"), NO_ENVP);
     311           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "long flag failed");
     312           2 :         clearValues (ks);
     313             : 
     314           2 :         RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
     315           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "long flag (with arg) failed");
     316           2 :         clearValues (ks);
     317             : 
     318           2 :         RUN_TEST (ks, ARGS ("--apple=long"), NO_ENVP);
     319           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
     320           2 :         clearValues (ks);
     321             : 
     322           2 :         ksDel (ks);
     323           2 : }
     324             : 
     325           2 : static void test_optional_value (void)
     326             : {
     327           2 :         Key * k = keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL);
     328           2 :         keySetMeta (k, "opt/arg", "optional");
     329           2 :         keySetMeta (k, "opt/flagvalue", "set");
     330           2 :         KeySet * ks = ksNew (1, k, KS_END);
     331             : 
     332           2 :         RUN_TEST (ks, ARGS ("-a"), NO_ENVP);
     333           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "short flag with value failed");
     334           2 :         clearValues (ks);
     335             : 
     336           2 :         RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
     337           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "short flag with value (with arg) failed");
     338           2 :         clearValues (ks);
     339             : 
     340             :         Key * errorKey;
     341           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("-ashort"), NO_ENVP);
     342           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Unknown short option: -s"),
     343             :                     "short flag with value (with arg, combined) should have failed");
     344           2 :         clearValues (ks);
     345             : 
     346           2 :         RUN_TEST (ks, ARGS ("--apple"), NO_ENVP);
     347           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "long flag with value failed");
     348           2 :         clearValues (ks);
     349             : 
     350           2 :         RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
     351           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "long flag with value (with arg) failed");
     352           2 :         clearValues (ks);
     353             : 
     354           2 :         RUN_TEST (ks, ARGS ("--apple=long"), NO_ENVP);
     355           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
     356           2 :         clearValues (ks);
     357             : 
     358           2 :         ksDel (ks);
     359           2 : }
     360             : 
     361           2 : static void test_precedence (void)
     362             : {
     363           2 :         KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", "APPLE"), KS_END);
     364             : 
     365           2 :         RUN_TEST (ks, ARGS ("--apple=long", "-ashort"), ENVP ("APPLE=env"));
     366           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option didn't take precedence");
     367           2 :         clearValues (ks);
     368             : 
     369           2 :         RUN_TEST (ks, ARGS ("--apple=long"), ENVP ("APPLE=env"));
     370           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option didn't take precedence");
     371           2 :         clearValues (ks);
     372             : 
     373           2 :         ksDel (ks);
     374           2 : }
     375             : 
     376           2 : static void test_repeated (void)
     377             : {
     378           2 :         KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple/#", 'a', "apple", "APPLE"), KS_END);
     379             : 
     380           2 :         RUN_TEST (ks, ARGS ("-a", "short0", "-ashort1", "-a", "short2"), NO_ENVP);
     381           2 :         succeed_if (checkMeta (ks, PROC_BASE_KEY "/apple", "array", "#2"), "short repeated failed (wrong count)");
     382           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#0", "short0"), "short repeated failed (#0)");
     383           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#1", "short1"), "short repeated failed (#1)");
     384           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#2", "short2"), "short repeated failed (#2)");
     385           2 :         clearValues (ks);
     386             : 
     387           2 :         RUN_TEST (ks, ARGS ("--apple", "long0", "--apple=long1", "--apple", "long2"), NO_ENVP);
     388           2 :         succeed_if (checkMeta (ks, PROC_BASE_KEY "/apple", "array", "#2"), "long repeated failed (wrong count)");
     389           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#0", "long0"), "long repeated failed (#0)");
     390           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#1", "long1"), "long repeated failed (#1)");
     391           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#2", "long2"), "long repeated failed (#2)");
     392           2 :         clearValues (ks);
     393             : 
     394           2 :         RUN_TEST (ks, NO_ARGS, ENVP ("APPLE=env0" ENV_SEP "env1" ENV_SEP "env2"));
     395           2 :         succeed_if (checkMeta (ks, PROC_BASE_KEY "/apple", "array", "#2"), "env-var repeated failed (wrong count)");
     396           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#0", "env0"), "env-var repeated failed (#0)");
     397           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#1", "env1"), "env-var repeated failed (#1)");
     398           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#2", "env2"), "env-var repeated failed (#2)");
     399           2 :         clearValues (ks);
     400             : 
     401           2 :         ksDel (ks);
     402           2 : }
     403             : 
     404           2 : static void test_multiple (void)
     405             : {
     406           2 :         Key * k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
     407           2 :         keySetMeta (k, "opt", "#1");
     408           2 :         keySetMeta (k, "opt/#0", "a");
     409           2 :         keySetMeta (k, "opt/#0/long", "apple");
     410           2 :         keySetMeta (k, "opt/#1", "b");
     411           2 :         keySetMeta (k, "opt/#1/long", "banana");
     412           2 :         keySetMeta (k, "env", "#1");
     413           2 :         keySetMeta (k, "env/#0", "APPLE");
     414           2 :         keySetMeta (k, "env/#1", "BANANA");
     415           2 :         KeySet * ks = ksNew (1, k, KS_END);
     416             : 
     417           2 :         RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
     418           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option failed");
     419           2 :         clearValues (ks);
     420             : 
     421           2 :         RUN_TEST (ks, ARGS ("-ashort"), NO_ENVP);
     422           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option (combined) failed");
     423           2 :         clearValues (ks);
     424             : 
     425           2 :         RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
     426           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option failed");
     427           2 :         clearValues (ks);
     428             : 
     429           2 :         RUN_TEST (ks, ARGS ("--apple=long"), NO_ENVP);
     430           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
     431           2 :         clearValues (ks);
     432             : 
     433           2 :         RUN_TEST (ks, NO_ARGS, ENVP ("APPLE=env"));
     434           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "env"), "env-var failed");
     435           2 :         clearValues (ks);
     436             : 
     437           2 :         RUN_TEST (ks, ARGS ("-b", "short"), NO_ENVP);
     438           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option failed");
     439           2 :         clearValues (ks);
     440             : 
     441           2 :         RUN_TEST (ks, ARGS ("-bshort"), NO_ENVP);
     442           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option (combined) failed");
     443           2 :         clearValues (ks);
     444             : 
     445           2 :         RUN_TEST (ks, ARGS ("--banana", "long"), NO_ENVP);
     446           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option failed");
     447           2 :         clearValues (ks);
     448             : 
     449           2 :         RUN_TEST (ks, ARGS ("--banana=long"), NO_ENVP);
     450           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
     451           2 :         clearValues (ks);
     452             : 
     453           2 :         RUN_TEST (ks, NO_ARGS, ENVP ("BANANA=env"));
     454           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "env"), "env-var failed");
     455           2 :         clearValues (ks);
     456             : 
     457           2 :         ksDel (ks);
     458           2 : }
     459             : 
     460           2 : static void test_precedence_repeated (void)
     461             : {
     462           2 :         KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple/#", 'a', "apple", "APPLE"), KS_END);
     463             : 
     464           2 :         RUN_TEST (ks, ARGS ("--apple=long1", "-a", "short0", "-a", "short1", "--apple", "long0", "--apple", "long2", "-ashort2"),
     465             :                   ENVP ("APPLE=env0" ENV_SEP "env1" ENV_SEP "env2"));
     466           2 :         succeed_if (checkMeta (ks, PROC_BASE_KEY "/apple", "array", "#2"), "short repeated failed (wrong count), should take precedence");
     467           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#0", "short0"), "short repeated failed (#0), should take precedence");
     468           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#1", "short1"), "short repeated failed (#1), should take precedence");
     469           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#2", "short2"), "short repeated failed (#2), should take precedence");
     470           2 :         clearValues (ks);
     471             : 
     472           2 :         RUN_TEST (ks, ARGS ("--apple", "long0", "--apple=long1", "--apple", "long2"), ENVP ("APPLE=env0" ENV_SEP "env1" ENV_SEP "env2"));
     473           2 :         succeed_if (checkMeta (ks, PROC_BASE_KEY "/apple", "array", "#2"), "long repeated failed (wrong count), should take precedence");
     474           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#0", "long0"), "long repeated failed (#0), should take precedence");
     475           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#1", "long1"), "long repeated failed (#1), should take precedence");
     476           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#2", "long2"), "long repeated failed (#2), should take precedence");
     477           2 :         clearValues (ks);
     478             : 
     479           2 :         ksDel (ks);
     480           2 : }
     481             : 
     482           2 : static void test_illegal_spec (void)
     483             : {
     484             :         // ---
     485             :         // illegal flagvalue
     486             :         // ---
     487             : 
     488           2 :         Key * k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
     489           2 :         keySetMeta (k, "opt", "a");
     490           2 :         keySetMeta (k, "opt/flagvalue", "set");
     491           2 :         KeySet * ks = ksNew (1, k, KS_END);
     492             : 
     493             :         Key * errorKey;
     494           2 :         RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
     495           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
     496             :                                 "The flagvalue metadata can only be used, if the opt/arg metadata is set to 'none' or 'optional'. "
     497             :                                 "(key: " SPEC_BASE_KEY "/apple)"),
     498             :                     "flagvalue should be illegal");
     499           2 :         clearValues (ks);
     500             : 
     501           2 :         ksDel (ks);
     502             : 
     503             :         // ---
     504             :         // duplicate option (short)
     505             :         // ---
     506             : 
     507           2 :         ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', NULL, NULL), keyWithOpt (SPEC_BASE_KEY "/banana", 'a', NULL, NULL), KS_END);
     508             : 
     509           2 :         RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
     510           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
     511             :                                 "The option '-a' has already been specified for the key '" SPEC_BASE_KEY
     512             :                                 "/apple'. Additional key: " SPEC_BASE_KEY "/banana"),
     513             :                     "duplicate short option should be illegal");
     514           2 :         clearValues (ks);
     515             : 
     516           2 :         ksDel (ks);
     517             : 
     518             :         // ---
     519             :         // duplicate option (long)
     520             :         // ---
     521             : 
     522           2 :         ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 0, "apple", NULL), keyWithOpt (SPEC_BASE_KEY "/banana", 0, "apple", NULL),
     523             :                     KS_END);
     524             : 
     525           2 :         RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
     526           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
     527             :                                 "The option '--apple' has already been specified for the key '" SPEC_BASE_KEY
     528             :                                 "/apple'. Additional key: " SPEC_BASE_KEY "/banana"),
     529             :                     "duplicate long option should be illegal");
     530           2 :         clearValues (ks);
     531             : 
     532           2 :         ksDel (ks);
     533             : 
     534             :         // ---
     535             :         // args remaining not array
     536             :         // ---
     537             : 
     538           2 :         k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
     539           2 :         keySetMeta (k, "args", "remaining");
     540           2 :         ks = ksNew (1, k, KS_END);
     541             : 
     542           2 :         RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
     543           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
     544             :                                 "'args=remaining' can only be set on array keys (basename = '#'). Offending key: " SPEC_BASE_KEY "/apple"),
     545             :                     "non-array remaining args should be illegal");
     546           2 :         clearValues (ks);
     547             : 
     548           2 :         ksDel (ks);
     549             : 
     550             :         // ---
     551             :         // '-' option
     552             :         // ---
     553             : 
     554           2 :         k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
     555           2 :         keySetMeta (k, "opt", "-");
     556           2 :         ks = ksNew (1, k, KS_END);
     557             : 
     558           2 :         RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
     559           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
     560             :                                 "Character '-' cannot be used as a short option. It would collide with the "
     561             :                                 "special string '--'. Offending key: " SPEC_BASE_KEY "/apple"),
     562             :                     "'-' option should be illegal");
     563           2 :         clearValues (ks);
     564             : 
     565           2 :         ksDel (ks);
     566             : 
     567             :         // ---
     568             :         // 'h' option
     569             :         // ---
     570             : 
     571           2 :         k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
     572           2 :         keySetMeta (k, "opt", "h");
     573           2 :         ks = ksNew (1, k, KS_END);
     574             : 
     575           2 :         RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
     576           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
     577             :                                 "Character 'h' cannot be used as a short option. It would collide with the "
     578             :                                 "help option '-h'. Offending key: " SPEC_BASE_KEY "/apple"),
     579             :                     "'h' option should be illegal");
     580           2 :         clearValues (ks);
     581             : 
     582           2 :         ksDel (ks);
     583             : 
     584             :         // ---
     585             :         // 'help' option
     586             :         // ---
     587             : 
     588           2 :         k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
     589           2 :         keySetMeta (k, "opt/long", "help");
     590           2 :         ks = ksNew (1, k, KS_END);
     591             : 
     592           2 :         RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
     593           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
     594             :                                 "Option 'help' cannot be used as a long option. It would collide with the "
     595             :                                 "help option '--help'. Offending key: " SPEC_BASE_KEY "/apple"),
     596             :                     "'help' option should be illegal");
     597           2 :         clearValues (ks);
     598             : 
     599           2 :         ksDel (ks);
     600           2 : }
     601             : 
     602           2 : static void test_illegal_use (void)
     603             : {
     604             :         // ---
     605             :         // illegal repeat
     606             :         // ---
     607             : 
     608           2 :         KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL), KS_END);
     609             : 
     610             :         Key * errorKey;
     611           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("-ashort0", "-ashort1"), NO_ENVP);
     612           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot be repeated: -a"),
     613             :                     "repeat should be illegal (short)");
     614           2 :         clearValues (ks);
     615             : 
     616           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple", "long0", "--apple", "long1"), NO_ENVP);
     617           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot be repeated: --apple"),
     618             :                     "repeat should be illegal (long)");
     619           2 :         clearValues (ks);
     620             : 
     621           2 :         ksDel (ks);
     622             : 
     623             :         // ---
     624             :         // missing argument
     625             :         // ---
     626             : 
     627           2 :         ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL), KS_END);
     628             : 
     629           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("-a"), NO_ENVP);
     630           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Missing argument for short option: -a"),
     631             :                     "missing argument (short) failed");
     632           2 :         clearValues (ks);
     633             : 
     634           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple"), NO_ENVP);
     635           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Missing argument for long option: --apple"),
     636             :                     "missing argument (long) failed");
     637           2 :         clearValues (ks);
     638             : 
     639           2 :         ksDel (ks);
     640             : 
     641             :         // ---
     642             :         // argument not allowed
     643             :         // ---
     644             : 
     645           2 :         Key * k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
     646           2 :         keySetMeta (k, "opt", "a");
     647           2 :         keySetMeta (k, "opt/long", "apple");
     648           2 :         keySetMeta (k, "opt/arg", "none");
     649           2 :         ks = ksNew (1, k, KS_END);
     650             : 
     651           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple=short"), NO_ENVP);
     652           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot have an argument: --apple"),
     653             :                     "argument should not be allowed");
     654           2 :         clearValues (ks);
     655             : 
     656           2 :         ksDel (ks);
     657             : 
     658             :         // ---
     659             :         // multiple repeated
     660             :         // ---
     661             : 
     662           2 :         k = keyNew (SPEC_BASE_KEY "/apple/#", KEY_END);
     663           2 :         keySetMeta (k, "opt", "#1");
     664           2 :         keySetMeta (k, "opt/#0", "a");
     665           2 :         keySetMeta (k, "opt/#0/long", "apple");
     666           2 :         keySetMeta (k, "opt/#1", "b");
     667           2 :         keySetMeta (k, "opt/#1/long", "banana");
     668           2 :         keySetMeta (k, "env", "#1");
     669           2 :         keySetMeta (k, "env/#0", "APPLE");
     670           2 :         keySetMeta (k, "env/#1", "BANANA");
     671           2 :         ks = ksNew (1, k, KS_END);
     672             : 
     673           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("-a", "short0", "-ashort1", "-a", "short2", "-b", "short3", "-bshort4"), NO_ENVP);
     674           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
     675             :                                 "The option '-b' cannot be used, because another option has already been used for the key "
     676             :                                 "'" SPEC_BASE_KEY "/apple/#'"),
     677             :                     "multiple repeated short options should have failed");
     678           2 :         clearValues (ks);
     679             : 
     680           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple", "long0", "--apple=long1", "--apple", "long2", "--banana=long3", "--banana", "long4"),
     681             :                         NO_ENVP);
     682           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
     683             :                                 "The option '--banana' cannot be used, because another option has already been used for the key "
     684             :                                 "'" SPEC_BASE_KEY "/apple/#'"),
     685             :                     "multiple repeated long options should have failed");
     686           2 :         clearValues (ks);
     687             : 
     688           2 :         RUN_TEST_ERROR (ks, errorKey, NO_ARGS, ENVP ("APPLE=env0" ENV_SEP "env1" ENV_SEP "env2", "BANANA=env3" ENV_SEP "env4"));
     689           2 :         succeed_if (
     690             :                 checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
     691             :                             "The environment variable 'BANANA' cannot be used, because another variable has already been used for the key "
     692             :                             "'" SPEC_BASE_KEY "/apple/#'."),
     693             :                 "multiple repeated env-vars should have failed");
     694           2 :         clearValues (ks);
     695             : 
     696           2 :         ksDel (ks);
     697           2 : }
     698             : 
     699           2 : static void test_help (void)
     700             : {
     701             :         // ---
     702             :         // no options
     703             :         // ---
     704             : 
     705           2 :         KeySet * ks = ksNew (0, KS_END);
     706             : 
     707           2 :         Key * errorKey = keyNew (SPEC_BASE_KEY, KEY_END);
     708             : 
     709           2 :         succeed_if (elektraGetOpts (ks, ARGS ("-h"), NO_ENVP, errorKey) == 1, "help not generated");
     710           2 :         checkHelpMessage (errorKey, "Usage: prog\n");
     711           2 :         succeed_if (elektraGetOpts (ks, ARGS ("-h", "short"), NO_ENVP, errorKey) == 1, "help not generated");
     712           2 :         checkHelpMessage (errorKey, "Usage: prog\n");
     713           2 :         succeed_if (elektraGetOpts (ks, ARGS ("--help"), NO_ENVP, errorKey) == 1, "help not generated");
     714           2 :         checkHelpMessage (errorKey, "Usage: prog\n");
     715           2 :         succeed_if (elektraGetOpts (ks, ARGS ("--help", "long"), NO_ENVP, errorKey) == 1, "help not generated");
     716           2 :         checkHelpMessage (errorKey, "Usage: prog\n");
     717             : 
     718           2 :         keyDel (errorKey);
     719             : 
     720           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("-hshort"), NO_ENVP);
     721           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Unknown short option: -s"),
     722             :                     "short help with value (with arg, combined) should have failed");
     723           2 :         clearValues (ks);
     724             : 
     725           2 :         RUN_TEST_ERROR (ks, errorKey, ARGS ("--help=long"), NO_ENVP);
     726           2 :         succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot have an argument: --help"),
     727             :                     "long help with value (with arg, combined) should have failed");
     728           2 :         clearValues (ks);
     729             : 
     730           2 :         ksDel (ks);
     731             : 
     732             :         // ---
     733             :         // with options
     734             :         // ---
     735             : 
     736           2 :         const char * expectedHelp =
     737             :                 "Usage: prog [OPTION]... [ARG]...\n"
     738             :                 "OPTIONS\n"
     739             :                 "  -a, -b BANANA, -C, --apple, --banana=BANANA, --cherry=[ARG]\n"
     740             :                 "                                Apple/Banana/Cherry description\n"
     741             :                 "  -p ARG                      A pear is not an apple, nor a banana, nor a cherry.\n";
     742             : 
     743           2 :         Key * k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
     744           2 :         keySetMeta (k, "opt", "#3");
     745           2 :         keySetMeta (k, "opt/#0", "a");
     746           2 :         keySetMeta (k, "opt/#0/long", "apple");
     747           2 :         keySetMeta (k, "opt/#0/arg", "none");
     748           2 :         keySetMeta (k, "opt/#1", "b");
     749           2 :         keySetMeta (k, "opt/#1/long", "banana");
     750           2 :         keySetMeta (k, "opt/#1/arg/help", "BANANA");
     751           2 :         keySetMeta (k, "opt/#2", "C");
     752           2 :         keySetMeta (k, "opt/#2/long", "cherry");
     753           2 :         keySetMeta (k, "opt/#2/arg", "optional");
     754           2 :         keySetMeta (k, "opt/#3", "d");
     755           2 :         keySetMeta (k, "opt/#3/hidden", "1");
     756           2 :         keySetMeta (k, "description", "Apple/Banana/Cherry description");
     757           2 :         ks = ksNew (4, k,
     758             :                     keyNew (SPEC_BASE_KEY "/pear", KEY_META, "opt", "p", KEY_META, "description",
     759             :                             "A pear is not an apple, nor a banana, nor a cherry.", KEY_END),
     760             :                     keyNew (SPEC_BASE_KEY "/args/#", KEY_META, "args", "remaining", KEY_END),
     761             :                     keyNew (SPEC_BASE_KEY "/none", KEY_META, "opt", "n", KEY_META, "opt/hidden", "1", KEY_END), KS_END);
     762           2 :         errorKey = keyNew (SPEC_BASE_KEY, KEY_END);
     763             : 
     764           2 :         succeed_if (elektraGetOpts (ks, ARGS ("-h"), NO_ENVP, errorKey) == 1, "help not generated");
     765           2 :         checkHelpMessage (errorKey, expectedHelp);
     766           2 :         succeed_if (elektraGetOpts (ks, ARGS ("-h", "short"), NO_ENVP, errorKey) == 1, "help not generated");
     767           2 :         checkHelpMessage (errorKey, expectedHelp);
     768           2 :         succeed_if (elektraGetOpts (ks, ARGS ("--help"), NO_ENVP, errorKey) == 1, "help not generated");
     769           2 :         checkHelpMessage (errorKey, expectedHelp);
     770           2 :         succeed_if (elektraGetOpts (ks, ARGS ("--help", "long"), NO_ENVP, errorKey) == 1, "help not generated");
     771           2 :         checkHelpMessage (errorKey, expectedHelp);
     772             : 
     773           2 :         keyDel (errorKey);
     774             : 
     775           2 :         ksDel (ks);
     776           2 : }
     777             : 
     778           2 : static void test_stop (void)
     779             : {
     780           2 :         KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", "APPLE"),
     781             :                              keyNew (SPEC_BASE_KEY "/rest/#", KEY_META, "args", "remaining", KEY_END), KS_END);
     782             : 
     783           2 :         RUN_TEST (ks, ARGS ("--", "-a", "short"), NO_ENVP);
     784           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", NULL), "should have stopped");
     785           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest", "#1"), "rest has wrong count");
     786           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#0", "-a"), "rest has wrong value (#0)");
     787           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#1", "short"), "rest has wrong value (#1)");
     788           2 :         clearValues (ks);
     789             : 
     790           2 :         RUN_TEST (ks, ARGS ("-ashort", "--", "-a", "short2"), NO_ENVP);
     791           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "should have stopped after short option");
     792           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest", "#1"), "rest has wrong count");
     793           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#0", "-a"), "rest has wrong value (#0)");
     794           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#1", "short2"), "rest has wrong value (#1)");
     795           2 :         clearValues (ks);
     796             : 
     797           2 :         RUN_TEST (ks, ARGS ("--apple", "long", "--", "-a", "short2"), NO_ENVP);
     798           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "hould have stopped after long option");
     799           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest", "#1"), "rest has wrong count");
     800           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#0", "-a"), "rest has wrong value (#0)");
     801           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#1", "short2"), "rest has wrong value (#1)");
     802           2 :         clearValues (ks);
     803             : 
     804           2 :         RUN_TEST (ks, ARGS ("--"), ENVP ("APPLE=env"));
     805           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "env"), "env-var failed (stopped options)");
     806           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest", "#"), "rest has wrong count");
     807           2 :         clearValues (ks);
     808             : 
     809             : 
     810           2 :         Key * errorKey = keyNew ("spec/tests/opts", KEY_META, "posixly", "1", KEY_END);
     811           2 :         if (elektraGetOpts (ks, ARGS ("-ashort", "other", "-a", "short2"), NO_ENVP, errorKey) != 0)
     812             :         {
     813           0 :                 yield_error ("error found");
     814           0 :                 output_error (errorKey);
     815             :         }
     816           2 :         keyDel (errorKey);
     817           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "should have stopped after short option");
     818           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest", "#2"), "rest has wrong count");
     819           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#0", "other"), "rest has wrong value (#0)");
     820           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#1", "-a"), "rest has wrong value (#1)");
     821           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#2", "short2"), "rest has wrong value (#2)");
     822           2 :         clearValues (ks);
     823             : 
     824           2 :         ksDel (ks);
     825           2 : }
     826             : 
     827           2 : static void test_mixed_config (void)
     828             : {
     829           2 :         Key * k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
     830           2 :         keySetMeta (k, "opt", "#1");
     831           2 :         keySetMeta (k, "opt/#0", "a");
     832           2 :         keySetMeta (k, "opt/#0/long", "apple");
     833           2 :         keySetMeta (k, "opt/#0/arg", "none");
     834           2 :         keySetMeta (k, "opt/#1", "b");
     835           2 :         keySetMeta (k, "opt/#1/long", "banana");
     836           2 :         KeySet * ks = ksNew (1, k, KS_END);
     837             : 
     838           2 :         RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
     839           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "mixed config failed");
     840           2 :         clearValues (ks);
     841             : 
     842           2 :         RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
     843           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "mixed config failed");
     844           2 :         clearValues (ks);
     845             : 
     846           2 :         RUN_TEST (ks, ARGS ("-b", "short"), NO_ENVP);
     847           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "mixed config failed");
     848           2 :         clearValues (ks);
     849             : 
     850           2 :         RUN_TEST (ks, ARGS ("-bshort"), NO_ENVP);
     851           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "mixed config failed");
     852           2 :         clearValues (ks);
     853             : 
     854           2 :         RUN_TEST (ks, ARGS ("--banana", "long"), NO_ENVP);
     855           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "mixed config failed");
     856           2 :         clearValues (ks);
     857             : 
     858           2 :         RUN_TEST (ks, ARGS ("--banana=long"), NO_ENVP);
     859           2 :         succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "mixed config failed");
     860           2 :         clearValues (ks);
     861             : 
     862           2 :         ksDel (ks);
     863           2 : }
     864             : 
     865           2 : int main (int argc, char ** argv)
     866             : {
     867           2 :         printf (" OPTS   TESTS\n");
     868           2 :         printf ("==================\n\n");
     869             : 
     870           2 :         init (argc, argv);
     871             : 
     872           2 :         test_simple ();
     873           2 :         test_short_only ();
     874           2 :         test_long_only ();
     875           2 :         test_env_only ();
     876           2 :         test_flag ();
     877           2 :         test_flag_value ();
     878           2 :         test_optional ();
     879           2 :         test_optional_value ();
     880           2 :         test_precedence ();
     881           2 :         test_repeated ();
     882           2 :         test_multiple ();
     883           2 :         test_precedence_repeated ();
     884           2 :         test_illegal_spec ();
     885           2 :         test_illegal_use ();
     886           2 :         test_help ();
     887           2 :         test_stop ();
     888           2 :         test_mixed_config ();
     889             : 
     890           2 :         print_result ("test_opts");
     891             : 
     892           2 :         return nbError;
     893             : }

Generated by: LCOV version 1.13