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