VirtualBox

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

Last change on this file since 73299 was 69111, checked in by vboxsync, 7 years ago

(C) year

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