FreeRDP
Loading...
Searching...
No Matches
TestCmdLine.c
1#include <errno.h>
2#include <winpr/crt.h>
3#include <winpr/assert.h>
4#include <winpr/tchar.h>
5#include <winpr/cmdline.h>
6#include <winpr/strlst.h>
7
8static const char* testArgv[] = { "mstsc.exe",
9 "+z",
10 "/w:1024",
11 "/h:768",
12 "/bpp:32",
13 "/admin",
14 "/multimon",
15 "+fonts",
16 "-wallpaper",
17 "/v:localhost:3389",
18 "/valuelist:value1,value2",
19 "/valuelist-empty:",
20 nullptr };
21
22static const char testListAppName[] = "test app name";
23static const char* testListArgs[] = {
24 "g:some.gateway.server,u:some\\\"user,p:some\\\"password,d:some\\\"domain,type:auto",
25 "a,b,c,d",
26 "a:,\"b:xxx, yyy\",c",
27 "a:,,,b",
28 "a:,\",b",
29 "\"a,b,c,d d d,fff\"",
30 "",
31 nullptr,
32 "'a,b,\",c'",
33 "\"a,b,',c\"",
34 "', a, ', b,c'",
35 "\"a,b,\",c\"",
36
37};
38
39static const char* testListArgs1[] = { testListAppName, "a", "b", "c", "d" };
40static const char* testListArgs2[] = { testListAppName, "a:", "b:xxx, yyy", "c" };
41// static const char* testListArgs3[] = {};
42// static const char* testListArgs4[] = {};
43static const char* testListArgs5[] = { testListAppName, "a", "b", "c", "d d d", "fff" };
44static const char* testListArgs6[] = { testListAppName };
45static const char* testListArgs7[] = { testListAppName };
46static const char* testListArgs8[] = { testListAppName, "a", "b", "\"", "c" };
47static const char* testListArgs9[] = { testListAppName, "a", "b", "'", "c" };
48// static const char* testListArgs10[] = {};
49// static const char* testListArgs11[] = {};
50static const char* testListArgs12[] = { testListAppName, "g:some.gateway.server",
51 "u:some\\\"user", "p:some\\\"password",
52 "d:some\\\"domain", "type:auto" };
53
54static const char** testListArgsResult[] = {
55 testListArgs12,
56 testListArgs1,
57 testListArgs2,
58 nullptr /* testListArgs3 */,
59 nullptr /* testListArgs4 */,
60 testListArgs5,
61 testListArgs6,
62 testListArgs7,
63 testListArgs8,
64 testListArgs9,
65 nullptr /* testListArgs10 */,
66 nullptr /* testListArgs11 */
67};
68static const size_t testListArgsCount[] = {
69 ARRAYSIZE(testListArgs12), ARRAYSIZE(testListArgs1),
70 ARRAYSIZE(testListArgs2), 0 /* ARRAYSIZE(testListArgs3) */,
71 0 /* ARRAYSIZE(testListArgs4) */, ARRAYSIZE(testListArgs5),
72 ARRAYSIZE(testListArgs6), ARRAYSIZE(testListArgs7),
73 ARRAYSIZE(testListArgs8), ARRAYSIZE(testListArgs9),
74 0 /* ARRAYSIZE(testListArgs10) */, 0 /* ARRAYSIZE(testListArgs11) */
75
76};
77
78static BOOL checkResult(size_t index, char** actual, size_t actualCount)
79{
80 const char** result = testListArgsResult[index];
81 const size_t resultCount = testListArgsCount[index];
82
83 if (resultCount != actualCount)
84 return FALSE;
85
86 if (actualCount == 0)
87 {
88 return (actual == nullptr);
89 }
90 else
91 {
92 if (!actual)
93 return FALSE;
94
95 for (size_t x = 0; x < actualCount; x++)
96 {
97 const char* a = result[x];
98 const char* b = actual[x];
99
100 if (strcmp(a, b) != 0)
101 return FALSE;
102 }
103 }
104
105 return TRUE;
106}
107
108static BOOL TestCommandLineParseCommaSeparatedValuesEx(void)
109{
110 WINPR_ASSERT(ARRAYSIZE(testListArgs) == ARRAYSIZE(testListArgsResult));
111 WINPR_ASSERT(ARRAYSIZE(testListArgs) == ARRAYSIZE(testListArgsCount));
112
113 for (size_t x = 0; x < ARRAYSIZE(testListArgs); x++)
114 {
115 union
116 {
117 char* p;
118 char** pp;
119 const char** ppc;
120 } ptr;
121 const char* list = testListArgs[x];
122 size_t count = 42;
123 ptr.pp = CommandLineParseCommaSeparatedValuesEx(testListAppName, list, &count);
124 BOOL valid = checkResult(x, ptr.pp, count);
125 free(ptr.p);
126 if (!valid)
127 return FALSE;
128 }
129
130 return TRUE;
131}
132
133int TestCmdLine(int argc, char* argv[])
134{
135 int status = 0;
136 int ret = -1;
137 DWORD flags = 0;
138 long width = 0;
139 long height = 0;
140 const COMMAND_LINE_ARGUMENT_A* arg = nullptr;
141 int testArgc = 0;
142 char** command_line = nullptr;
143 COMMAND_LINE_ARGUMENT_A args[] = {
144 { "v", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
145 "destination server" },
146 { "port", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
147 "server port" },
148 { "w", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "width" },
149 { "h", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "height" },
150 { "f", COMMAND_LINE_VALUE_FLAG, nullptr, nullptr, nullptr, -1, nullptr, "fullscreen" },
151 { "bpp", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
152 "session bpp (color depth)" },
153 { "admin", COMMAND_LINE_VALUE_FLAG, nullptr, nullptr, nullptr, -1, "console",
154 "admin (or console) session" },
155 { "multimon", COMMAND_LINE_VALUE_FLAG, nullptr, nullptr, nullptr, -1, nullptr,
156 "multi-monitor" },
157 { "a", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, "addin", "addin" },
158 { "u", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "username" },
159 { "p", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "password" },
160 { "d", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "domain" },
161 { "z", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
162 "compression" },
163 { "audio", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
164 "audio output mode" },
165 { "mic", COMMAND_LINE_VALUE_FLAG, nullptr, nullptr, nullptr, -1, nullptr,
166 "audio input (microphone)" },
167 { "fonts", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
168 "smooth fonts (cleartype)" },
169 { "aero", COMMAND_LINE_VALUE_BOOL, nullptr, nullptr, BoolValueFalse, -1, nullptr,
170 "desktop composition" },
171 { "window-drag", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
172 "full window drag" },
173 { "menu-anims", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
174 "menu animations" },
175 { "themes", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
176 "themes" },
177 { "wallpaper", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
178 "wallpaper" },
179 { "codec", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "codec" },
180 { "nego", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
181 "protocol security negotiation" },
182 { "sec", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
183 "force specific protocol security" },
184#if defined(WITH_FREERDP_DEPRECATED)
185 { "sec-rdp", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
186 "rdp protocol security" },
187 { "sec-tls", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
188 "tls protocol security" },
189 { "sec-nla", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
190 "nla protocol security" },
191 { "sec-ext", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
192 "nla extended protocol security" },
193 { "cert-name", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
194 "certificate name" },
195 { "cert-ignore", COMMAND_LINE_VALUE_FLAG, nullptr, nullptr, nullptr, -1, nullptr,
196 "ignore certificate" },
197#endif
198 { "valuelist", COMMAND_LINE_VALUE_REQUIRED, "<val1>,<val2>", nullptr, nullptr, -1, nullptr,
199 "List of comma separated values." },
200 { "valuelist-empty", COMMAND_LINE_VALUE_REQUIRED, "<val1>,<val2>", nullptr, nullptr, -1,
201 nullptr,
202 "List of comma separated values. Used to test correct behavior if an empty list was "
203 "passed." },
204 { "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, nullptr, nullptr,
205 nullptr, -1, nullptr, "print version" },
206 { "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, nullptr, nullptr, nullptr, -1,
207 "?", "print help" },
208 { nullptr, 0, nullptr, nullptr, nullptr, -1, nullptr, nullptr }
209 };
210
211 WINPR_UNUSED(argc);
212 WINPR_UNUSED(argv);
213
214 flags = COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_SIGIL_PLUS_MINUS;
215 testArgc = string_list_length(testArgv);
216 command_line = string_list_copy(testArgv);
217
218 if (!command_line)
219 {
220 printf("Argument duplication failed (not enough memory?)\n");
221 return ret;
222 }
223
224 status =
225 CommandLineParseArgumentsA(testArgc, command_line, args, flags, nullptr, nullptr, nullptr);
226
227 if (status != 0)
228 {
229 printf("CommandLineParseArgumentsA failure: %d\n", status);
230 goto out;
231 }
232
233 arg = CommandLineFindArgumentA(args, "w");
234
235 if (strcmp("1024", arg->Value) != 0)
236 {
237 printf("CommandLineFindArgumentA: unexpected %s value %s\n", arg->Name, arg->Value);
238 goto out;
239 }
240
241 arg = CommandLineFindArgumentA(args, "h");
242
243 if (strcmp("768", arg->Value) != 0)
244 {
245 printf("CommandLineFindArgumentA: unexpected %s value %s\n", arg->Name, arg->Value);
246 goto out;
247 }
248
249 arg = CommandLineFindArgumentA(args, "f");
250
251 if (arg->Value)
252 {
253 printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
254 goto out;
255 }
256
257 arg = CommandLineFindArgumentA(args, "admin");
258
259 if (!arg->Value)
260 {
261 printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
262 goto out;
263 }
264
265 arg = CommandLineFindArgumentA(args, "multimon");
266
267 if (!arg->Value)
268 {
269 printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
270 goto out;
271 }
272
273 arg = CommandLineFindArgumentA(args, "v");
274
275 if (strcmp("localhost:3389", arg->Value) != 0)
276 {
277 printf("CommandLineFindArgumentA: unexpected %s value %s\n", arg->Name, arg->Value);
278 goto out;
279 }
280
281 arg = CommandLineFindArgumentA(args, "fonts");
282
283 if (!arg->Value)
284 {
285 printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
286 goto out;
287 }
288
289 arg = CommandLineFindArgumentA(args, "wallpaper");
290
291 if (arg->Value)
292 {
293 printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
294 goto out;
295 }
296
297 arg = CommandLineFindArgumentA(args, "help");
298
299 if (arg->Value)
300 {
301 printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
302 goto out;
303 }
304
305 arg = args;
306 errno = 0;
307
308 do
309 {
310 if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
311 continue;
312
313 printf("Argument: %s\n", arg->Name);
314 CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "v")
315 {
316 }
317 CommandLineSwitchCase(arg, "w")
318 {
319 width = strtol(arg->Value, nullptr, 0);
320
321 if (errno != 0)
322 goto out;
323 }
324 CommandLineSwitchCase(arg, "h")
325 {
326 height = strtol(arg->Value, nullptr, 0);
327
328 if (errno != 0)
329 goto out;
330 }
331 CommandLineSwitchCase(arg, "valuelist")
332 {
333 size_t count = 0;
334 char** p = CommandLineParseCommaSeparatedValuesEx(arg->Name, arg->Value, &count);
335 free((void*)p);
336
337 if (!p || count != 3)
338 {
339 printf("CommandLineParseCommaSeparatedValuesEx: invalid p or count (%" PRIuz
340 "!=3)\n",
341 count);
342 goto out;
343 }
344 }
345 CommandLineSwitchCase(arg, "valuelist-empty")
346 {
347 size_t count = 0;
348 char** p = CommandLineParseCommaSeparatedValuesEx(arg->Name, arg->Value, &count);
349 free((void*)p);
350
351 if (!p || count != 1)
352 {
353 printf("CommandLineParseCommaSeparatedValuesEx: invalid p or count (%" PRIuz
354 "!=1)\n",
355 count);
356 goto out;
357 }
358 }
359 CommandLineSwitchDefault(arg)
360 {
361 }
362 CommandLineSwitchEnd(arg)
363 } while ((arg = CommandLineFindNextArgumentA(arg)) != nullptr);
364
365 if ((width != 1024) || (height != 768))
366 {
367 printf("Unexpected width and height: Actual: (%ldx%ld), Expected: (1024x768)\n", width,
368 height);
369 goto out;
370 }
371 ret = 0;
372
373out:
374 string_list_free(command_line);
375
376 if (!TestCommandLineParseCommaSeparatedValuesEx())
377 return -1;
378 return ret;
379}