VirtualBox

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

Last change on this file since 76553 was 76553, checked in by vboxsync, 5 years ago

scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use