diff options
Diffstat (limited to '')
-rw-r--r-- | src/VBox/Runtime/testcase/tstRTGetOpt.cpp | 661 |
1 files changed, 661 insertions, 0 deletions
diff --git a/src/VBox/Runtime/testcase/tstRTGetOpt.cpp b/src/VBox/Runtime/testcase/tstRTGetOpt.cpp new file mode 100644 index 00000000..fef9ddaa --- /dev/null +++ b/src/VBox/Runtime/testcase/tstRTGetOpt.cpp @@ -0,0 +1,661 @@ +/* $Id: tstRTGetOpt.cpp $ */ +/** @file + * IPRT Testcase - RTGetOpt + */ + +/* + * Copyright (C) 2007-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <iprt/net.h> +#include <iprt/getopt.h> + +#include <iprt/err.h> +#include <iprt/string.h> +#include <iprt/test.h> + + +int main() +{ + RTTEST hTest; + int rc = RTTestInitAndCreate("tstRTGetOpt", &hTest); + if (rc) + return rc; + + RTGETOPTSTATE GetState; + RTGETOPTUNION Val; +#define CHECK(expr) do { if (!(expr)) { RTTestIFailed("error line %d (iNext=%d): %s\n", __LINE__, GetState.iNext, #expr); } } while (0) +#define CHECK2(expr, fmt) \ + do { \ + if (!(expr)) { \ + RTTestIFailed("error line %d (iNext=%d): %s\n", __LINE__, GetState.iNext, #expr); \ + RTTestIFailureDetails fmt; \ + } \ + } while (0) + +#define CHECK_pDef(paOpts, i) \ + CHECK2(Val.pDef == &(paOpts)[(i)], ("Got #%d (%p) expected #%d\n", (int)(Val.pDef - &(paOpts)[0]), Val.pDef, i)); + +#define CHECK_GETOPT(expr, chRet, iInc) \ + do { \ + const int iPrev = GetState.iNext; \ + const int rcGetOpt = (expr); \ + CHECK2(rcGetOpt == (chRet), ("got %d, expected %d\n", rcGetOpt, (chRet))); \ + CHECK2(GetState.iNext == (iInc) + iPrev, ("iNext=%d expected %d\n", GetState.iNext, (iInc) + iPrev)); \ + GetState.iNext = (iInc) + iPrev; \ + } while (0) + +#define CHECK_GETOPT_STR(expr, chRet, iInc, str) \ + do { \ + const int iPrev = GetState.iNext; \ + const int rcGetOpt = (expr); \ + CHECK2(rcGetOpt == (chRet), ("got %d, expected %d\n", rcGetOpt, (chRet))); \ + CHECK2(GetState.iNext == (iInc) + iPrev, ("iNext=%d expected %d\n", GetState.iNext, (iInc) + iPrev)); \ + CHECK2(VALID_PTR(Val.psz) && !strcmp(Val.psz, (str)), ("got %s, expected %s\n", Val.psz, (str))); \ + GetState.iNext = (iInc) + iPrev; \ + } while (0) + + + /* + * The basics. + */ + RTTestSub(hTest, "Basics"); + static const RTGETOPTDEF s_aOpts2[] = + { + { "--optwithstring", 's', RTGETOPT_REQ_STRING }, + { "--optwithint", 'i', RTGETOPT_REQ_INT32 }, + { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, + { NULL, 'q', RTGETOPT_REQ_NOTHING }, + { "--quiet", 384, RTGETOPT_REQ_NOTHING }, + { "-novalue", 385, RTGETOPT_REQ_NOTHING }, + { "-startvm", 386, RTGETOPT_REQ_STRING }, + { "nodash", 387, RTGETOPT_REQ_NOTHING }, + { "nodashval", 388, RTGETOPT_REQ_STRING }, + { "--gateway", 'g', RTGETOPT_REQ_IPV4ADDR }, + { "--mac", 'm', RTGETOPT_REQ_MACADDR }, + { "--strindex", 400, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX }, + { "strindex", 400, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX }, + { "--intindex", 401, RTGETOPT_REQ_INT32 | RTGETOPT_FLAG_INDEX }, + { "--macindex", 402, RTGETOPT_REQ_MACADDR | RTGETOPT_FLAG_INDEX }, + { "--indexnovalue", 403, RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_INDEX }, + { "--macindexnegative", 404, RTGETOPT_REQ_NOTHING }, + { "--twovalues", 405, RTGETOPT_REQ_STRING }, + { "--twovaluesindex", 406, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_INDEX }, + { "--threevalues", 407, RTGETOPT_REQ_UINT32 }, + { "--boolean", 408, RTGETOPT_REQ_BOOL_ONOFF }, + { "--booleanindex", 409, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX }, + { "--pair32", 410, RTGETOPT_REQ_UINT32_PAIR }, + { "--optpair32", 411, RTGETOPT_REQ_UINT32_OPTIONAL_PAIR }, + { "--optpair64", 412, RTGETOPT_REQ_UINT64_OPTIONAL_PAIR }, + }; + + const char *argv2[] = + { + "-s", "string1", + "-sstring2", + "-s:string3", + "-s=string4", + "-s:", + "-s=", + "--optwithstring", "string5", + "--optwithstring:string6", + "--optwithstring=string7", + "--optwithstring:", + "--optwithstring=", + + "-i", "-42", + "-i:-42", + "-i=-42", + + "--optwithint", "42", + "--optwithint:42", + "--optwithint=42", + + "-v", + "--verbose", + "-q", + "--quiet", + + "-novalue", + "-startvm", "myvm", + + "nodash", + "nodashval", "string9", + + "filename1", + "-q", + "filename2", + + "-vqi999", + + "-g192.168.1.1", + + "-m08:0:27:00:ab:f3", + "--mac:1:::::c", + + "--strindex786", "string10", + "--strindex786:string11", + "--strindex786=string12", + "strindex687", "string13", + "strindex687:string14", + "strindex687=string15", + "strindex688:", + "strindex689=", + "--intindex137", "1000", + "--macindex138", "08:0:27:00:ab:f3", + "--indexnovalue1", + "--macindexnegative", + + "--twovalues", "firstvalue", "secondvalue", + "--twovalues:firstvalue", "secondvalue", + "--twovaluesindex4", "1", "0xA", + "--twovaluesindex5=2", "0xB", + "--threevalues", "1", "0xC", "thirdvalue", + + /* bool on/off */ + "--boolean", "on", + "--boolean", "off", + "--boolean", "invalid", + "--booleanindex2", "on", + "--booleanindex7", "off", + "--booleanindex9", "invalid", + + /* standard options */ + "--help", + "-help", + "-?", + "-h", + "--version", + "-version", + "-V", + + /* 32-bit pairs */ + "--pair32", "1536:0x1536", + "--optpair32", "0x42:042", + "--optpair32", "0128", + "--optpair64", "0x128 0x42", + "--optpair64", "0x128 :0x42", + "--optpair64", "0x128", + + /* done */ + NULL + }; + int argc2 = (int)RT_ELEMENTS(argv2) - 1; + + CHECK(RT_SUCCESS(RTGetOptInit(&GetState, argc2, (char **)argv2, &s_aOpts2[0], RT_ELEMENTS(s_aOpts2), 0, 0 /* fFlags */))); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 2); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string1")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string2")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string3")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string4")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 2); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string5")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string6")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string7")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); + CHECK(GetState.uIndex == UINT32_MAX); + + /* -i */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2); + CHECK(Val.i32 == -42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == -42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == -42); + + /* --optwithint */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2); + CHECK(Val.i32 == 42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == 42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == 42); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'v', 1); + CHECK_pDef(s_aOpts2, 2); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'v', 1); + CHECK_pDef(s_aOpts2, 2); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'q', 1); + CHECK_pDef(s_aOpts2, 3); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 384, 1); + CHECK_pDef(s_aOpts2, 4); + + /* -novalue / -startvm (single dash long options) */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 385, 1); + CHECK_pDef(s_aOpts2, 5); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 386, 2); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "myvm")); + + /* no-dash options */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 387, 1); + CHECK_pDef(s_aOpts2, 7); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 388, 2); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string9")); + + /* non-option, option, non-option */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1); + CHECK(Val.psz && !strcmp(Val.psz, "filename1")); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'q', 1); + CHECK_pDef(s_aOpts2, 3); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1); + CHECK(Val.psz && !strcmp(Val.psz, "filename2")); + + /* compress short options */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'v', 0); + CHECK_pDef(s_aOpts2, 2); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'q', 0); + CHECK_pDef(s_aOpts2, 3); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == 999); + + /* IPv4 */ + RTTestSub(hTest, "RTGetOpt - IPv4"); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'g', 1); + CHECK(Val.IPv4Addr.u == RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8(192,168,1,1)))); + + /* Ethernet MAC address. */ + RTTestSub(hTest, "RTGetOpt - MAC Address"); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'm', 1); + CHECK( Val.MacAddr.au8[0] == 0x08 + && Val.MacAddr.au8[1] == 0x00 + && Val.MacAddr.au8[2] == 0x27 + && Val.MacAddr.au8[3] == 0x00 + && Val.MacAddr.au8[4] == 0xab + && Val.MacAddr.au8[5] == 0xf3); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'm', 1); + CHECK( Val.MacAddr.au8[0] == 0x01 + && Val.MacAddr.au8[1] == 0x00 + && Val.MacAddr.au8[2] == 0x00 + && Val.MacAddr.au8[3] == 0x00 + && Val.MacAddr.au8[4] == 0x00 + && Val.MacAddr.au8[5] == 0x0c); + + /* string with indexed argument */ + RTTestSub(hTest, "RTGetOpt - Option w/ Index"); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 2); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string10")); + CHECK(GetState.uIndex == 786); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string11")); + CHECK(GetState.uIndex == 786); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string12")); + CHECK(GetState.uIndex == 786); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 2); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string13")); + CHECK(GetState.uIndex == 687); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string14")); + CHECK(GetState.uIndex == 687); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string15")); + CHECK(GetState.uIndex == 687); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); + CHECK(GetState.uIndex == 688); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); + CHECK(GetState.uIndex == 689); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 401, 2); + CHECK(Val.i32 == 1000); + CHECK(GetState.uIndex == 137); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 402, 2); + CHECK( Val.MacAddr.au8[0] == 0x08 + && Val.MacAddr.au8[1] == 0x00 + && Val.MacAddr.au8[2] == 0x27 + && Val.MacAddr.au8[3] == 0x00 + && Val.MacAddr.au8[4] == 0xab + && Val.MacAddr.au8[5] == 0xf3); + CHECK(GetState.uIndex == 138); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 403, 1); + CHECK(GetState.uIndex == 1); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 404, 1); + CHECK(GetState.uIndex == UINT32_MAX); + + /* RTGetOptFetchValue tests */ + RTTestSub(hTest, "RTGetOptFetchValue"); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 405, 2); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "firstvalue")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "secondvalue")); + CHECK(GetState.uIndex == UINT32_MAX); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 405, 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "firstvalue")); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "secondvalue")); + CHECK(GetState.uIndex == UINT32_MAX); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 406, 2); + CHECK(Val.u32 == 1); + CHECK(GetState.uIndex == 4); + CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_UINT32), VINF_SUCCESS, 1); + CHECK(Val.u32 == 10); + CHECK(GetState.uIndex == 4); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 406, 1); + CHECK(Val.u32 == 2); + CHECK(GetState.uIndex == 5); + CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_UINT32), VINF_SUCCESS, 1); + CHECK(Val.u32 == 11); + CHECK(GetState.uIndex == 5); + + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 407, 2); + CHECK(Val.u32 == 1); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_UINT32), VINF_SUCCESS, 1); + CHECK(Val.u32 == 12); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "thirdvalue")); + CHECK(GetState.uIndex == UINT32_MAX); + + /* bool on/off tests */ + RTTestSub(hTest, "RTGetOpt - bool on/off"); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 408, 2); + CHECK(Val.f); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 408, 2); + CHECK(!Val.f); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), VERR_GETOPT_UNKNOWN_OPTION, 2); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "invalid")); + + /* bool on/off with indexed argument */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 409, 2); + CHECK(Val.f); + CHECK(GetState.uIndex == 2); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 409, 2); + CHECK(!Val.f); + CHECK(GetState.uIndex == 7); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), VERR_GETOPT_UNKNOWN_OPTION, 2); + CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "invalid")); + + /* standard options. */ + RTTestSub(hTest, "Standard options"); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'V', 1); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'V', 1); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'V', 1); + + /* 32-bit pairs */ + RTTestSub(hTest, "RTGetOpt - pairs"); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 410, 2); + CHECK(Val.PairU32.uFirst == 1536); + CHECK(Val.PairU32.uSecond == 0x1536); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 411, 2); + CHECK(Val.PairU32.uFirst == 0x42); + CHECK(Val.PairU32.uSecond == 42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 411, 2); + CHECK(Val.PairU32.uFirst == 128); + CHECK(Val.PairU32.uSecond == UINT32_MAX); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 412, 2); + CHECK(Val.PairU64.uFirst == 0x128); + CHECK(Val.PairU64.uSecond == 0x42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 412, 2); + CHECK(Val.PairU64.uFirst == 0x128); + CHECK(Val.PairU64.uSecond == 0x42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 412, 2); + CHECK(Val.PairU64.uFirst == 0x128); + CHECK(Val.PairU64.uSecond == UINT64_MAX); + + /* the end */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 0, 0); + CHECK(Val.pDef == NULL); + CHECK(argc2 == GetState.iNext); + + /* + * Options first. + */ + RTTestSub(hTest, "Options first"); + const char *argv3[] = + { + "foo1", + "-s", "string1", + "foo2", + "--optwithstring", "string2", + "foo3", + "-i", "-42", + "foo4", + "-i:-42", + "-i=-42", + "foo5", + "foo6", + "foo7", + "-i:-42", + "-i=-42", + "foo8", + "--twovalues", "firstvalue", "secondvalue", + "foo9", + "--twovalues:firstvalue", "secondvalue", + "foo10", + "--", + "--optwithstring", + "-s", + "-i", + "foo11", + "foo12", + + /* done */ + NULL + }; + int argc3 = (int)RT_ELEMENTS(argv3) - 1; + + CHECK(RT_SUCCESS(RTGetOptInit(&GetState, argc3, (char **)argv3, &s_aOpts2[0], RT_ELEMENTS(s_aOpts2), 0, + RTGETOPTINIT_FLAGS_OPTS_FIRST))); + + /* -s */ + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string1"); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string2"); + CHECK(GetState.uIndex == UINT32_MAX); + + /* -i */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2); + CHECK(Val.i32 == -42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == -42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == -42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == -42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == -42); + + /* --twovalues */ + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 2, "firstvalue"); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue"); + CHECK(GetState.uIndex == UINT32_MAX); + + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 1, "firstvalue"); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue"); + CHECK(GetState.uIndex == UINT32_MAX); + + /* -- */ + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 2, "foo1"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo2"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo3"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo4"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo5"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo6"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo7"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo8"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo9"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo10"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "--optwithstring"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "-s"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "-i"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo11"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo12"); + + /* the end */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 0, 0); + CHECK(Val.pDef == NULL); + CHECK(argc3 == GetState.iNext); + + /* + * Options first, part 2: No dash-dash. + */ + const char *argv4[] = + { + "foo1", + "-s", "string1", + "foo2", + "--optwithstring", "string2", + "foo3", + "-i", "-42", + "foo4", + "-i:-42", + "-i=-42", + "foo5", + "foo6", + "foo7", + "-i:-42", + "-i=-42", + "foo8", + "--twovalues", "firstvalue", "secondvalue", + "foo9", + "--twovalues:firstvalue", "secondvalue", + "foo10", + "foo11", + "foo12", + + /* done */ + NULL + }; + int argc4 = (int)RT_ELEMENTS(argv4) - 1; + + CHECK(RT_SUCCESS(RTGetOptInit(&GetState, argc4, (char **)argv4, &s_aOpts2[0], RT_ELEMENTS(s_aOpts2), 0, + RTGETOPTINIT_FLAGS_OPTS_FIRST))); + + /* -s */ + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string1"); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string2"); + CHECK(GetState.uIndex == UINT32_MAX); + + /* -i */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2); + CHECK(Val.i32 == -42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == -42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == -42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == -42); + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); + CHECK(Val.i32 == -42); + + /* --twovalues */ + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 2, "firstvalue"); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue"); + CHECK(GetState.uIndex == UINT32_MAX); + + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 1, "firstvalue"); + CHECK(GetState.uIndex == UINT32_MAX); + CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue"); + CHECK(GetState.uIndex == UINT32_MAX); + + /* -- */ + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo1"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo2"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo3"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo4"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo5"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo6"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo7"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo8"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo9"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo10"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo11"); + CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo12"); + + /* the end */ + CHECK_GETOPT(RTGetOpt(&GetState, &Val), 0, 0); + CHECK(Val.pDef == NULL); + CHECK(argc4 == GetState.iNext); + + /* + * Some negative testing. + */ + const char *argv5[] = + { + "non-option-argument", + "--optwithstring", /* missing string */ + /* done */ + NULL + }; + int argc5 = (int)RT_ELEMENTS(argv5) - 1; + CHECK(RT_SUCCESS(RTGetOptInit(&GetState, argc5, (char **)argv5, &s_aOpts2[0], RT_ELEMENTS(s_aOpts2), 0, + RTGETOPTINIT_FLAGS_OPTS_FIRST))); + RTTESTI_CHECK_RC(RTGetOpt(&GetState, &Val), VERR_GETOPT_REQUIRED_ARGUMENT_MISSING); + + + /* + * Summary. + */ + return RTTestSummaryAndDestroy(hTest); +} + |