VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTGetOptArgv.cpp@ 98103

Last change on this file since 98103 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.6 KB
Line 
1/* $Id: tstRTGetOptArgv.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTGetOptArgv*.
4 */
5
6/*
7 * Copyright (C) 2010-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/path.h>
42
43#include <iprt/errcore.h>
44#include <iprt/getopt.h>
45#include <iprt/ldr.h>
46#include <iprt/param.h>
47#include <iprt/string.h>
48#include <iprt/test.h>
49#include <iprt/utf16.h>
50
51
52/*********************************************************************************************************************************
53* Global Variables *
54*********************************************************************************************************************************/
55static const struct
56{
57 /** The input string, bourne shell. */
58 const char *pszInBourne;
59 /** The input string, MS CRT. */
60 const char *pszInMsCrt;
61 /** Separators, NULL if default. */
62 const char *pszSeparators;
63 /** The number of arguments. */
64 int cArgs;
65 /** Expected argument vector. */
66 const char *apszArgs[16];
67 /** Expected quoted string, bourne shell. */
68 const char *pszOutBourneSh;
69 /** Expected quoted string, MS CRT. */
70 const char *pszOutMsCrt;
71} g_aTests[] =
72{
73 {
74 "0 1 \"\"2'' '3' 4 5 '''''6' 7 8 9 10 11",
75 "0 1 \"\"2 3 4 5 \"6\" 7 8 \"\"9\"\" 10 11",
76 NULL,
77 12,
78 {
79 "0",
80 "1",
81 "2",
82 "3",
83 "4",
84 "5",
85 "6",
86 "7",
87 "8",
88 "9",
89 "10",
90 "11",
91 NULL, NULL, NULL, NULL,
92 },
93 "0 1 2 3 4 5 6 7 8 9 10 11",
94 "0 1 2 3 4 5 6 7 8 9 10 11"
95 },
96 {
97 "\t\" asdf \" '\"'xyz \"\t\" '\n' '\"' \"'\"\n\r \\\"xyz",
98 /* Note! Two things here to make CommandLineArgW happy. First, it doesn't use IFS including newline/return, so
99 we skip that bit of the test. Second, it uses pre-2008 doubledouble quoting rules, unlike the CRT and IPRT
100 which uses the post-2008 rules. We work around that by putting that test last.
101 See http://www.daviddeley.com/autohotkey/parameters/parameters.htm */
102 "\t\" asdf \" \\\"xyz \"\t\" \"\n\" \"\\\"\" ' \"\"\"xyz\"",
103 NULL,
104 7,
105 {
106 " asdf ",
107 "\"xyz",
108 "\t",
109 "\n",
110 "\"",
111 "\'",
112 "\"xyz",
113 NULL,
114 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
115 },
116 "' asdf ' '\"xyz' '\t' '\n' '\"' ''\"'\"'' '\"xyz'",
117 "\" asdf \" \"\\\"xyz\" \"\t\" \"\n\" \"\\\"\" ' \"\\\"xyz\""
118 },
119 {
120 ":0::1::::2:3:4:5:",
121 ":0::1::::2:3:4:5:",
122 ":",
123 6,
124 {
125 "0",
126 "1",
127 "2",
128 "3",
129 "4",
130 "5",
131 NULL, NULL,
132 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
133 },
134 "0 1 2 3 4 5",
135 "0 1 2 3 4 5"
136 },
137 {
138 "0:1;2:3;4:5",
139 "0:1;2:3;4:5",
140 ";;;;;;;;;;;;;;;;;;;;;;:",
141 6,
142 {
143 "0",
144 "1",
145 "2",
146 "3",
147 "4",
148 "5",
149 NULL, NULL,
150 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
151 },
152 "0 1 2 3 4 5",
153 "0 1 2 3 4 5"
154 },
155 {
156 "abcd 'a ' ' b' ' c '",
157 "abcd \"a \" \" b\" \" c \"",
158 NULL,
159 4,
160 {
161 "abcd",
162 "a ",
163 " b",
164 " c ",
165 NULL, NULL, NULL, NULL,
166 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
167 },
168 "abcd 'a ' ' b' ' c '",
169 "abcd \"a \" \" b\" \" c \""
170 },
171 {
172 "'a\n\\b' 'de'\"'\"'fg' h ''\"'\"''",
173 "\"a\n\\b\" de'fg h \"'\" ",
174 NULL,
175 4,
176 {
177 "a\n\\b",
178 "de'fg",
179 "h",
180 "'",
181 NULL, NULL, NULL, NULL,
182 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
183 },
184 "'a\n\\b' 'de'\"'\"'fg' h ''\"'\"''",
185 "\"a\n\\b\" de'fg h '"
186 },
187 {
188 "arg1 \"arg2=\\\"zyx\\\"\" 'arg3=\\\\\\'",
189 "arg1 arg2=\\\"zyx\\\" arg3=\\\\\\",
190 NULL,
191 3,
192 {
193 "arg1",
194 "arg2=\"zyx\"",
195 "arg3=\\\\\\",
196 NULL, NULL, NULL, NULL, NULL,
197 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
198 },
199 "arg1 'arg2=\"zyx\"' 'arg3=\\\\\\'",
200 "arg1 \"arg2=\\\"zyx\\\"\" arg3=\\\\\\"
201 },
202 {
203 " a\\\\\\\\b d\"e f\"g h ij\t",
204 " a\\\\b d\"e f\"g h ij\t",
205 NULL,
206 4,
207 {
208 "a\\\\b",
209 "de fg",
210 "h",
211 "ij",
212 NULL, NULL, NULL, NULL,
213 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
214 },
215 "'a\\\\b' 'de fg' h ij",
216 "a\\\\b \"de fg\" h ij",
217 }
218};
219
220
221
222static void tstCheckNativeMsCrtToArgv(const char *pszCmdLine, int cExpectedArgs, const char * const *papszExpectedArgs)
223{
224#ifdef RT_OS_WINDOWS
225 /*
226 * Resolve APIs.
227 */
228 static void *(__stdcall * s_pfnLocalFree)(void *pvFree);
229 static PRTUTF16 *(__stdcall * s_pfnCommandLineToArgvW)(PCRTUTF16 pwszCmdLine, int *pcArgs);
230 if (!s_pfnCommandLineToArgvW)
231 {
232 *(void **)&s_pfnLocalFree = RTLdrGetSystemSymbol("kernel32.dll", "LocalFree");
233 RTTESTI_CHECK_RETV(s_pfnLocalFree != NULL);
234 *(void **)&s_pfnCommandLineToArgvW = RTLdrGetSystemSymbol("shell32.dll", "CommandLineToArgvW");
235 RTTESTI_CHECK_RETV(s_pfnCommandLineToArgvW != NULL);
236 }
237
238 /*
239 * Calc expected arguments if needed.
240 */
241 if (cExpectedArgs == -1)
242 for (cExpectedArgs = 0; papszExpectedArgs[cExpectedArgs]; cExpectedArgs++)
243 { /* nothing */ }
244
245 /*
246 * Convert input command line to UTF-16 and call native API.
247 */
248 RTUTF16 wszCmdLine[1024];
249 PRTUTF16 pwszCmdLine = &wszCmdLine[1];
250 RTTESTI_CHECK_RC_RETV(RTStrToUtf16Ex(pszCmdLine, RTSTR_MAX, &pwszCmdLine, 1023, NULL), VINF_SUCCESS);
251 wszCmdLine[0] = ' ';
252
253 int cArgs = -2;
254 PRTUTF16 *papwszArgs = s_pfnCommandLineToArgvW(wszCmdLine, &cArgs);
255
256 /*
257 * Check the result.
258 */
259 if (cArgs - 1 != cExpectedArgs)
260 RTTestIFailed("Native returns cArgs=%d, expected %d (cmdline=|%s|)", cArgs - 1, cExpectedArgs, pszCmdLine);
261 int cArgsCheck = RT_MIN(cArgs - 1, cExpectedArgs);
262 for (int i = 0; i < cArgsCheck; i++)
263 {
264 char *pszArg = NULL;
265 RTTESTI_CHECK_RC_RETV(RTUtf16ToUtf8(papwszArgs[i + 1], &pszArg), VINF_SUCCESS);
266 if (strcmp(pszArg, papszExpectedArgs[i]))
267 RTTestIFailed("Native returns argv[%i]='%s', expected '%s' (cmdline=|%s|)",
268 i, pszArg, papszExpectedArgs[i], pszCmdLine);
269 RTStrFree(pszArg);
270 }
271
272 if (papwszArgs)
273 s_pfnLocalFree(papwszArgs);
274#else
275 NOREF(pszCmdLine);
276 NOREF(cExpectedArgs);
277 NOREF(papszExpectedArgs);
278#endif
279}
280
281
282static void tst4(void)
283{
284 /*
285 * Microsoft CRT round-tripping.
286 */
287 RTTestISub("Round-trips / MS_CRT");
288 for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++)
289 {
290 /* First */
291 char **papszArgs1 = NULL;
292 int cArgs1 = -1;
293 int rc = RTGetOptArgvFromString(&papszArgs1, &cArgs1, g_aTests[i].pszInMsCrt,
294 RTGETOPTARGV_CNV_QUOTE_MS_CRT, g_aTests[i].pszSeparators);
295 if (rc == VINF_SUCCESS)
296 {
297 if (cArgs1 != g_aTests[i].cArgs)
298 RTTestIFailed("g_aTests[%i]: #1=%d, expected %d", i, cArgs1, g_aTests[i].cArgs);
299 for (int iArg = 0; iArg < cArgs1; iArg++)
300 if (strcmp(papszArgs1[iArg], g_aTests[i].apszArgs[iArg]) != 0)
301 RTTestIFailed("g_aTests[%i]/1: argv[%i] differs: got '%s', expected '%s' (RTGetOptArgvFromString(,,'%s', '%s'))",
302 i, iArg, papszArgs1[iArg], g_aTests[i].apszArgs[iArg],
303 g_aTests[i].pszInMsCrt, g_aTests[i].pszSeparators);
304 RTTESTI_CHECK_RETV(papszArgs1[cArgs1] == NULL);
305 if (g_aTests[i].pszSeparators == NULL)
306 tstCheckNativeMsCrtToArgv(g_aTests[i].pszInMsCrt, g_aTests[i].cArgs, g_aTests[i].apszArgs);
307
308 /* Second */
309 char *pszArgs2 = NULL;
310 rc = RTGetOptArgvToString(&pszArgs2, papszArgs1, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
311 if (rc == VINF_SUCCESS)
312 {
313 if (strcmp(pszArgs2, g_aTests[i].pszOutMsCrt))
314 RTTestIFailed("g_aTests[%i]/2: '%s', expected '%s'", i, pszArgs2, g_aTests[i].pszOutMsCrt);
315
316 /*
317 * Third
318 */
319 char **papszArgs3 = NULL;
320 int cArgs3 = -1;
321 rc = RTGetOptArgvFromString(&papszArgs3, &cArgs3, pszArgs2, RTGETOPTARGV_CNV_QUOTE_MS_CRT, NULL);
322 if (rc == VINF_SUCCESS)
323 {
324 if (cArgs3 != g_aTests[i].cArgs)
325 RTTestIFailed("g_aTests[%i]/3: %d, expected %d", i, cArgs3, g_aTests[i].cArgs);
326 for (int iArg = 0; iArg < cArgs3; iArg++)
327 if (strcmp(papszArgs3[iArg], g_aTests[i].apszArgs[iArg]) != 0)
328 RTTestIFailed("g_aTests[%i]/3: argv[%i] differs: got '%s', expected '%s' (RTGetOptArgvFromString(,,'%s',))",
329 i, iArg, papszArgs3[iArg], g_aTests[i].apszArgs[iArg], pszArgs2);
330 RTTESTI_CHECK_RETV(papszArgs3[cArgs3] == NULL);
331 if (g_aTests[i].pszSeparators == NULL)
332 tstCheckNativeMsCrtToArgv(pszArgs2, g_aTests[i].cArgs, g_aTests[i].apszArgs);
333
334 /*
335 * Fourth
336 */
337 char *pszArgs4 = NULL;
338 rc = RTGetOptArgvToString(&pszArgs4, papszArgs3, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
339 if (rc == VINF_SUCCESS)
340 {
341 if (strcmp(pszArgs4, pszArgs2))
342 RTTestIFailed("g_aTests[%i]/4: '%s' does not match #4='%s'", i, pszArgs2, pszArgs4);
343 RTStrFree(pszArgs4);
344 }
345 else
346 RTTestIFailed("g_aTests[%i]/4: RTGetOptArgvToString() -> %Rrc", i, rc);
347 RTGetOptArgvFree(papszArgs3);
348 }
349 else
350 RTTestIFailed("g_aTests[%i]/3: RTGetOptArgvFromString() -> %Rrc", i, rc);
351 RTStrFree(pszArgs2);
352 }
353 else
354 RTTestIFailed("g_aTests[%i]/2: RTGetOptArgvToString() -> %Rrc", i, rc);
355 RTGetOptArgvFree(papszArgs1);
356 }
357 else
358 RTTestIFailed("g_aTests[%i]/1: RTGetOptArgvFromString(,,'%s', '%s') -> %Rrc",
359 i, g_aTests[i].pszInMsCrt, g_aTests[i].pszSeparators, rc);
360 }
361
362}
363
364
365
366static void tst3(void)
367{
368 /*
369 * Bourne shell round-tripping.
370 */
371 RTTestISub("Round-trips / BOURNE_SH");
372 for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++)
373 {
374 /* First */
375 char **papszArgs1 = NULL;
376 int cArgs1 = -1;
377 int rc = RTGetOptArgvFromString(&papszArgs1, &cArgs1, g_aTests[i].pszInBourne,
378 RTGETOPTARGV_CNV_QUOTE_BOURNE_SH, g_aTests[i].pszSeparators);
379 if (rc == VINF_SUCCESS)
380 {
381 if (cArgs1 != g_aTests[i].cArgs)
382 RTTestIFailed("g_aTests[%i]: #1=%d, expected %d", i, cArgs1, g_aTests[i].cArgs);
383 for (int iArg = 0; iArg < cArgs1; iArg++)
384 if (strcmp(papszArgs1[iArg], g_aTests[i].apszArgs[iArg]) != 0)
385 RTTestIFailed("g_aTests[%i]/1: argv[%i] differs: got '%s', expected '%s' (RTGetOptArgvFromString(,,'%s', '%s'))",
386 i, iArg, papszArgs1[iArg], g_aTests[i].apszArgs[iArg],
387 g_aTests[i].pszInBourne, g_aTests[i].pszSeparators);
388 RTTESTI_CHECK_RETV(papszArgs1[cArgs1] == NULL);
389
390 /* Second */
391 char *pszArgs2 = NULL;
392 rc = RTGetOptArgvToString(&pszArgs2, papszArgs1, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);
393 if (rc == VINF_SUCCESS)
394 {
395 if (strcmp(pszArgs2, g_aTests[i].pszOutBourneSh))
396 RTTestIFailed("g_aTests[%i]/2: '%s', expected '%s'", i, pszArgs2, g_aTests[i].pszOutBourneSh);
397
398 /*
399 * Third
400 */
401 char **papszArgs3 = NULL;
402 int cArgs3 = -1;
403 rc = RTGetOptArgvFromString(&papszArgs3, &cArgs3, pszArgs2, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH, NULL);
404 if (rc == VINF_SUCCESS)
405 {
406 if (cArgs3 != g_aTests[i].cArgs)
407 RTTestIFailed("g_aTests[%i]/3: %d, expected %d", i, cArgs3, g_aTests[i].cArgs);
408 for (int iArg = 0; iArg < cArgs3; iArg++)
409 if (strcmp(papszArgs3[iArg], g_aTests[i].apszArgs[iArg]) != 0)
410 RTTestIFailed("g_aTests[%i]/3: argv[%i] differs: got '%s', expected '%s' (RTGetOptArgvFromString(,,'%s',))",
411 i, iArg, papszArgs3[iArg], g_aTests[i].apszArgs[iArg], pszArgs2);
412 RTTESTI_CHECK_RETV(papszArgs3[cArgs3] == NULL);
413
414 /*
415 * Fourth
416 */
417 char *pszArgs4 = NULL;
418 rc = RTGetOptArgvToString(&pszArgs4, papszArgs3, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);
419 if (rc == VINF_SUCCESS)
420 {
421 if (strcmp(pszArgs4, pszArgs2))
422 RTTestIFailed("g_aTests[%i]/4: '%s' does not match #4='%s'", i, pszArgs2, pszArgs4);
423 RTStrFree(pszArgs4);
424 }
425 else
426 RTTestIFailed("g_aTests[%i]/4: RTGetOptArgvToString() -> %Rrc", i, rc);
427 RTGetOptArgvFree(papszArgs3);
428 }
429 else
430 RTTestIFailed("g_aTests[%i]/3: RTGetOptArgvFromString() -> %Rrc", i, rc);
431 RTStrFree(pszArgs2);
432 }
433 else
434 RTTestIFailed("g_aTests[%i]/2: RTGetOptArgvToString() -> %Rrc", i, rc);
435 RTGetOptArgvFree(papszArgs1);
436 }
437 else
438 RTTestIFailed("g_aTests[%i]/1: RTGetOptArgvFromString(,,'%s', '%s') -> %Rrc",
439 i, g_aTests[i].pszInBourne, g_aTests[i].pszSeparators, rc);
440 }
441}
442
443
444/* Global to avoid weird C4640 warning about "construction of local static object is not thread-safe". */
445static const struct
446{
447 const char * const apszArgs[5];
448 const char *pszCmdLine;
449} g_aMscCrtTests[] =
450{
451 {
452 { "abcd", "a ", " b", " c ", NULL },
453 "abcd \"a \" \" b\" \" c \""
454 },
455 {
456 { "a\\\\\\b", "de fg", "h", NULL, NULL },
457 "a\\\\\\b \"de fg\" h"
458 },
459 {
460 { "a\\\"b", "c", "d", "\"", NULL },
461 "\"a\\\\\\\"b\" c d \"\\\"\""
462 },
463 {
464 { "a\\\\b c", "d", "e", " \\", NULL },
465 "\"a\\\\b c\" d e \" \\\\\""
466 },
467};
468
469static void tst2(void)
470{
471 RTTestISub("RTGetOptArgvToString / MS_CRT");
472
473 for (size_t i = 0; i < RT_ELEMENTS(g_aMscCrtTests); i++)
474 {
475 char *pszCmdLine = NULL;
476 int rc = RTGetOptArgvToString(&pszCmdLine, g_aMscCrtTests[i].apszArgs, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
477 RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS);
478 if (!strcmp(g_aMscCrtTests[i].pszCmdLine, pszCmdLine))
479 tstCheckNativeMsCrtToArgv(pszCmdLine, -1, g_aMscCrtTests[i].apszArgs);
480 else
481 RTTestIFailed("g_aTest[%i] failed:\n"
482 " got '%s'\n"
483 " expected '%s'\n",
484 i, pszCmdLine, g_aMscCrtTests[i].pszCmdLine);
485 RTStrFree(pszCmdLine);
486 }
487
488 for (size_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
489 {
490 char *pszCmdLine = NULL;
491 int rc = RTGetOptArgvToString(&pszCmdLine, g_aTests[i].apszArgs, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
492 RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS);
493 if (!strcmp(g_aTests[i].pszOutMsCrt, pszCmdLine))
494 tstCheckNativeMsCrtToArgv(pszCmdLine, g_aTests[i].cArgs, g_aTests[i].apszArgs);
495 else
496 RTTestIFailed("g_aTests[%i] failed:\n"
497 " got |%s|\n"
498 " expected |%s|\n",
499 i, pszCmdLine, g_aTests[i].pszOutMsCrt);
500 RTStrFree(pszCmdLine);
501 }
502
503
504
505 RTTestISub("RTGetOptArgvToString / BOURNE_SH");
506
507 for (size_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
508 {
509 char *pszCmdLine = NULL;
510 int rc = RTGetOptArgvToString(&pszCmdLine, g_aTests[i].apszArgs, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);
511 RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS);
512 if (strcmp(g_aTests[i].pszOutBourneSh, pszCmdLine))
513 RTTestIFailed("g_aTests[%i] failed:\n"
514 " got |%s|\n"
515 " expected |%s|\n",
516 i, pszCmdLine, g_aTests[i].pszOutBourneSh);
517 RTStrFree(pszCmdLine);
518 }
519}
520
521static void tst1(void)
522{
523 RTTestISub("RTGetOptArgvFromString");
524 char **papszArgs = NULL;
525 int cArgs = -1;
526 RTTESTI_CHECK_RC_RETV(RTGetOptArgvFromString(&papszArgs, &cArgs, "", RTGETOPTARGV_CNV_QUOTE_BOURNE_SH, NULL), VINF_SUCCESS);
527 RTTESTI_CHECK_RETV(cArgs == 0);
528 RTTESTI_CHECK_RETV(papszArgs);
529 RTTESTI_CHECK_RETV(!papszArgs[0]);
530 RTGetOptArgvFree(papszArgs);
531
532 RTTESTI_CHECK_RC_RETV(RTGetOptArgvFromString(&papszArgs, &cArgs, "0 1 \"\"2'' '3' 4 5 '''''6' 7 8 9 10 11",
533 RTGETOPTARGV_CNV_QUOTE_BOURNE_SH, NULL), VINF_SUCCESS);
534 RTTESTI_CHECK_RETV(cArgs == 12);
535 RTTESTI_CHECK_RETV(!strcmp(papszArgs[0], "0"));
536 RTTESTI_CHECK_RETV(!strcmp(papszArgs[1], "1"));
537 RTTESTI_CHECK_RETV(!strcmp(papszArgs[2], "2"));
538 RTTESTI_CHECK_RETV(!strcmp(papszArgs[3], "3"));
539 RTTESTI_CHECK_RETV(!strcmp(papszArgs[4], "4"));
540 RTTESTI_CHECK_RETV(!strcmp(papszArgs[5], "5"));
541 RTTESTI_CHECK_RETV(!strcmp(papszArgs[6], "6"));
542 RTTESTI_CHECK_RETV(!strcmp(papszArgs[7], "7"));
543 RTTESTI_CHECK_RETV(!strcmp(papszArgs[8], "8"));
544 RTTESTI_CHECK_RETV(!strcmp(papszArgs[9], "9"));
545 RTTESTI_CHECK_RETV(!strcmp(papszArgs[10], "10"));
546 RTTESTI_CHECK_RETV(!strcmp(papszArgs[11], "11"));
547 RTTESTI_CHECK_RETV(!papszArgs[12]);
548 RTGetOptArgvFree(papszArgs);
549
550 RTTESTI_CHECK_RC_RETV(RTGetOptArgvFromString(&papszArgs, &cArgs, "\t\" asdf \" '\"'xyz \"\t\" '\n' '\"' \"'\"\n\r ",
551 RTGETOPTARGV_CNV_QUOTE_BOURNE_SH, NULL), VINF_SUCCESS);
552 RTTESTI_CHECK_RETV(cArgs == 6);
553 RTTESTI_CHECK_RETV(!strcmp(papszArgs[0], " asdf "));
554 RTTESTI_CHECK_RETV(!strcmp(papszArgs[1], "\"xyz"));
555 RTTESTI_CHECK_RETV(!strcmp(papszArgs[2], "\t"));
556 RTTESTI_CHECK_RETV(!strcmp(papszArgs[3], "\n"));
557 RTTESTI_CHECK_RETV(!strcmp(papszArgs[4], "\""));
558 RTTESTI_CHECK_RETV(!strcmp(papszArgs[5], "\'"));
559 RTTESTI_CHECK_RETV(!papszArgs[6]);
560 RTGetOptArgvFree(papszArgs);
561
562 RTTESTI_CHECK_RC_RETV(RTGetOptArgvFromString(&papszArgs, &cArgs, ":0::1::::2:3:4:5:",
563 RTGETOPTARGV_CNV_QUOTE_BOURNE_SH, ":"), VINF_SUCCESS);
564 RTTESTI_CHECK_RETV(cArgs == 6);
565 RTTESTI_CHECK_RETV(!strcmp(papszArgs[0], "0"));
566 RTTESTI_CHECK_RETV(!strcmp(papszArgs[1], "1"));
567 RTTESTI_CHECK_RETV(!strcmp(papszArgs[2], "2"));
568 RTTESTI_CHECK_RETV(!strcmp(papszArgs[3], "3"));
569 RTTESTI_CHECK_RETV(!strcmp(papszArgs[4], "4"));
570 RTTESTI_CHECK_RETV(!strcmp(papszArgs[5], "5"));
571 RTTESTI_CHECK_RETV(!papszArgs[6]);
572 RTGetOptArgvFree(papszArgs);
573
574 RTTESTI_CHECK_RC_RETV(RTGetOptArgvFromString(&papszArgs, &cArgs, "0:1;2:3;4:5", RTGETOPTARGV_CNV_QUOTE_BOURNE_SH,
575 ";;;;;;;;;;;;;;;;;;;;;;:"), VINF_SUCCESS);
576 RTTESTI_CHECK_RETV(cArgs == 6);
577 RTTESTI_CHECK_RETV(!strcmp(papszArgs[0], "0"));
578 RTTESTI_CHECK_RETV(!strcmp(papszArgs[1], "1"));
579 RTTESTI_CHECK_RETV(!strcmp(papszArgs[2], "2"));
580 RTTESTI_CHECK_RETV(!strcmp(papszArgs[3], "3"));
581 RTTESTI_CHECK_RETV(!strcmp(papszArgs[4], "4"));
582 RTTESTI_CHECK_RETV(!strcmp(papszArgs[5], "5"));
583 RTTESTI_CHECK_RETV(!papszArgs[6]);
584 RTGetOptArgvFree(papszArgs);
585
586 /*
587 * Tests from the list.
588 */
589 for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++)
590 {
591 papszArgs = NULL;
592 cArgs = -1;
593 int rc = RTGetOptArgvFromString(&papszArgs, &cArgs, g_aTests[i].pszInBourne, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH,
594 g_aTests[i].pszSeparators);
595 if (rc == VINF_SUCCESS)
596 {
597 if (cArgs == g_aTests[i].cArgs)
598 {
599 for (int iArg = 0; iArg < cArgs; iArg++)
600 if (strcmp(papszArgs[iArg], g_aTests[i].apszArgs[iArg]) != 0)
601 RTTestIFailed("g_aTests[%i]: argv[%i] differs: got '%s', expected '%s' (RTGetOptArgvFromString(,,'%s', '%s'))",
602 i, iArg, papszArgs[iArg], g_aTests[i].apszArgs[iArg],
603 g_aTests[i].pszInBourne, g_aTests[i].pszSeparators);
604 RTTESTI_CHECK_RETV(papszArgs[cArgs] == NULL);
605 }
606 else
607 RTTestIFailed("g_aTests[%i]: cArgs=%u, expected %u for RTGetOptArgvFromString(,,'%s', '%s')",
608 i, cArgs, g_aTests[i].cArgs, g_aTests[i].pszInBourne, g_aTests[i].pszSeparators);
609 RTGetOptArgvFree(papszArgs);
610 }
611 else
612 RTTestIFailed("g_aTests[%i]: RTGetOptArgvFromString(,,'%s', '%s') -> %Rrc",
613 i, g_aTests[i].pszInBourne, g_aTests[i].pszSeparators, rc);
614 }
615}
616
617
618int main()
619{
620 /*
621 * Init RT+Test.
622 */
623 RTTEST hTest;
624 int rc = RTTestInitAndCreate("tstRTGetOptArgv", &hTest);
625 if (rc)
626 return rc;
627 RTTestBanner(hTest);
628
629 /*
630 * The test.
631 */
632 tst1();
633 tst2();
634 tst4();
635 tst3();
636
637 /*
638 * Summary.
639 */
640 return RTTestSummaryAndDestroy(hTest);
641}
642
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette