FreeRDP
Loading...
Searching...
No Matches
TestClientCmdLine.c
1#include <freerdp/config.h>
2
3#include <freerdp/client.h>
4#include <freerdp/client/cmdline.h>
5#include <freerdp/settings.h>
6#include <winpr/cmdline.h>
7#include <winpr/spec.h>
8#include <winpr/strlst.h>
9#include <winpr/collections.h>
10
11typedef BOOL (*validate_settings_pr)(rdpSettings* settings);
12typedef void (*setup_settings_pr)(rdpSettings* settings);
13
14#define printref() printf("%s:%d: in function %-40s:", __FILE__, __LINE__, __func__)
15
16#define TEST_ERROR(format, ...) \
17 do \
18 { \
19 (void)fprintf(stderr, format, ##__VA_ARGS__); \
20 printref(); \
21 (void)printf(format, ##__VA_ARGS__); \
22 (void)fflush(stdout); \
23 } while (0)
24
25#define TEST_FAILURE(format, ...) \
26 do \
27 { \
28 printref(); \
29 (void)printf(" FAILURE "); \
30 (void)printf(format, ##__VA_ARGS__); \
31 (void)fflush(stdout); \
32 } while (0)
33
34static void print_test_title(int argc, char** argv)
35{
36 printf("Running test:");
37
38 for (int i = 0; i < argc; i++)
39 {
40 printf(" %s", argv[i]);
41 }
42
43 printf("\n");
44}
45
46static inline BOOL testcase(const char* name, char** argv, size_t argc, int expected_return,
47 validate_settings_pr validate_settings,
48 setup_settings_pr setup_settings)
49{
50 int status = 0;
51 BOOL valid_settings = TRUE;
52 rdpSettings* settings = freerdp_settings_new(0);
53
54 WINPR_ASSERT(argc <= INT_MAX);
55
56 print_test_title((int)argc, argv);
57
58 if (!settings)
59 {
60 TEST_ERROR("Test %s could not allocate settings!\n", name);
61 return FALSE;
62 }
63
64 if (setup_settings)
65 setup_settings(settings);
66
67 status = freerdp_client_settings_parse_command_line(settings, (int)argc, argv, FALSE);
68
69 if (validate_settings)
70 {
71 valid_settings = validate_settings(settings);
72 }
73
74 freerdp_settings_free(settings);
75
76 if (status == expected_return)
77 {
78 if (!valid_settings)
79 {
80 return FALSE;
81 }
82 }
83 else
84 {
85 TEST_FAILURE("Expected status %d, got status %d\n", expected_return, status);
86 return FALSE;
87 }
88
89 return TRUE;
90}
91
92#if defined(_WIN32)
93#define DRIVE_REDIRECT_PATH "c:\\Windows"
94#else
95#define DRIVE_REDIRECT_PATH "/tmp"
96#endif
97
98static BOOL check_settings_gateway_response_timeout(rdpSettings* settings, UINT32 expected)
99{
100 const UINT32 val = freerdp_settings_get_uint32(settings, FreeRDP_GatewayResponseTimeout);
101
102 if (val != expected)
103 {
104 TEST_FAILURE("Expected GatewayResponseTimeout = %" PRIu32 ", but got %" PRIu32 "!\n",
105 expected, val);
106 return FALSE;
107 }
108
109 return TRUE;
110}
111
112static BOOL check_settings_gateway_response_timeout_default(rdpSettings* settings)
113{
114 return check_settings_gateway_response_timeout(settings, 15000);
115}
116
117static BOOL check_settings_gateway_response_timeout_custom(rdpSettings* settings)
118{
119 return check_settings_gateway_response_timeout(settings, 120000);
120}
121
122static const char test_aad_user_agent[] = "TestAgent/1.0 (KHTML, like Gecko)";
123
124static BOOL check_settings_aad_user_agent(rdpSettings* settings)
125{
126 const char* ua = freerdp_settings_get_string(settings, FreeRDP_AadAuthUserAgent);
127 if (!ua || (strcmp(ua, test_aad_user_agent) != 0))
128 {
129 TEST_FAILURE("Expected AadAuthUserAgent = \"%s\", but got %s!\n", test_aad_user_agent,
130 ua ? ua : "(null)");
131 return FALSE;
132 }
133 return TRUE;
134}
135
136static BOOL check_settings_smartcard_no_redirection(rdpSettings* settings)
137{
138 BOOL result = TRUE;
139
140 if (freerdp_settings_get_bool(settings, FreeRDP_RedirectSmartCards))
141 {
142 TEST_FAILURE("Expected RedirectSmartCards = FALSE, but RedirectSmartCards = TRUE!\n");
143 result = FALSE;
144 }
145
146 if (freerdp_device_collection_find_type(settings, RDPDR_DTYP_SMARTCARD))
147 {
148 TEST_FAILURE("Expected no SMARTCARD device, but found at least one!\n");
149 result = FALSE;
150 }
151
152 return result;
153}
154
155#ifndef TEST_SOURCE_DIR
156#error "TEST_SOURCE_DIR must be defined to the test source directory"
157#endif
158#define DISABLED_DISPLAY_OPTIONS_RDP TEST_SOURCE_DIR "/rdp-cmdline/disabled-display-options.rdp"
159
160static BOOL check_settings_multimon_disabled(rdpSettings* settings)
161{
162 BOOL result = TRUE;
163
164 if (freerdp_settings_get_bool(settings, FreeRDP_UseMultimon))
165 {
166 TEST_FAILURE("Expected UseMultimon = FALSE, but UseMultimon = TRUE!\n");
167 result = FALSE;
168 }
169
170 if (freerdp_settings_get_bool(settings, FreeRDP_ForceMultimon))
171 {
172 TEST_FAILURE("Expected ForceMultimon = FALSE, but ForceMultimon = TRUE!\n");
173 result = FALSE;
174 }
175
176 if (!freerdp_settings_get_bool(settings, FreeRDP_SmartSizing))
177 {
178 TEST_FAILURE("Expected SmartSizing = TRUE, but SmartSizing = FALSE!\n");
179 result = FALSE;
180 }
181
182 return result;
183}
184
185static BOOL check_settings_smart_sizing_disabled(rdpSettings* settings)
186{
187 BOOL result = TRUE;
188
189 if (freerdp_settings_get_bool(settings, FreeRDP_SmartSizing))
190 {
191 TEST_FAILURE("Expected SmartSizing = FALSE, but SmartSizing = TRUE!\n");
192 result = FALSE;
193 }
194
195 if (!freerdp_settings_get_bool(settings, FreeRDP_DynamicResolutionUpdate))
196 {
197 TEST_FAILURE(
198 "Expected DynamicResolutionUpdate = TRUE, but DynamicResolutionUpdate = FALSE!\n");
199 result = FALSE;
200 }
201
202 if (!freerdp_settings_get_bool(settings, FreeRDP_UseMultimon))
203 {
204 TEST_FAILURE("Expected UseMultimon = TRUE, but UseMultimon = FALSE!\n");
205 result = FALSE;
206 }
207
208 return result;
209}
210
211static BOOL check_settings_multimon_enabled(rdpSettings* settings)
212{
213 BOOL result = TRUE;
214
215 if (!freerdp_settings_get_bool(settings, FreeRDP_UseMultimon))
216 {
217 TEST_FAILURE("Expected UseMultimon = TRUE, but UseMultimon = FALSE!\n");
218 result = FALSE;
219 }
220
221 return result;
222}
223
224static void setup_settings_multimon_force(rdpSettings* settings)
225{
226 (void)freerdp_settings_set_bool(settings, FreeRDP_ForceMultimon, TRUE);
227}
228
229static BOOL check_settings_multimon_force(rdpSettings* settings)
230{
231 BOOL result = TRUE;
232
233 if (!freerdp_settings_get_bool(settings, FreeRDP_UseMultimon))
234 {
235 TEST_FAILURE("Expected UseMultimon = TRUE, but UseMultimon = FALSE!\n");
236 result = FALSE;
237 }
238
239 if (!freerdp_settings_get_bool(settings, FreeRDP_ForceMultimon))
240 {
241 TEST_FAILURE("Expected ForceMultimon = TRUE, but ForceMultimon = FALSE!\n");
242 result = FALSE;
243 }
244
245 return result;
246}
247
248static BOOL check_settings_smart_sizing_size(rdpSettings* settings)
249{
250 BOOL result = TRUE;
251
252 if (!freerdp_settings_get_bool(settings, FreeRDP_SmartSizing))
253 {
254 TEST_FAILURE("Expected SmartSizing = TRUE, but SmartSizing = FALSE!\n");
255 result = FALSE;
256 }
257
258 if (freerdp_settings_get_uint32(settings, FreeRDP_SmartSizingWidth) != 1024)
259 {
260 TEST_FAILURE("Expected SmartSizingWidth = 1024, but SmartSizingWidth = %u!\n",
261 (unsigned)freerdp_settings_get_uint32(settings, FreeRDP_SmartSizingWidth));
262 result = FALSE;
263 }
264
265 if (freerdp_settings_get_uint32(settings, FreeRDP_SmartSizingHeight) != 768)
266 {
267 TEST_FAILURE("Expected SmartSizingHeight = 768, but SmartSizingHeight = %u!\n",
268 (unsigned)freerdp_settings_get_uint32(settings, FreeRDP_SmartSizingHeight));
269 result = FALSE;
270 }
271
272 return result;
273}
274
275static BOOL check_settings_gfx_without_h264(rdpSettings* settings)
276{
277 BOOL result = TRUE;
278
279 if (freerdp_settings_get_uint32(settings, FreeRDP_ConnectionType) != CONNECTION_TYPE_AUTODETECT)
280 {
281 TEST_FAILURE("Expected ConnectionType = AUTODETECT, but ConnectionType = %u!\n",
282 (unsigned)freerdp_settings_get_uint32(settings, FreeRDP_ConnectionType));
283 result = FALSE;
284 }
285
286 if (freerdp_settings_get_bool(settings, FreeRDP_GfxH264) ||
287 freerdp_settings_get_bool(settings, FreeRDP_GfxAVC444) ||
288 freerdp_settings_get_bool(settings, FreeRDP_GfxAVC444v2))
289 {
290 TEST_FAILURE(
291 "Expected the H.264 codecs off as /gfx asked, but /network:auto turned them on!\n");
292 result = FALSE;
293 }
294
295 if (!freerdp_settings_get_bool(settings, FreeRDP_GfxProgressive))
296 {
297 TEST_FAILURE("Expected GfxProgressive = TRUE, but GfxProgressive = FALSE!\n");
298 result = FALSE;
299 }
300
301 return result;
302}
303
304static BOOL check_settings_network_auto_h264(rdpSettings* settings)
305{
306 BOOL result = TRUE;
307
308 if (!freerdp_settings_get_bool(settings, FreeRDP_GfxH264) ||
309 !freerdp_settings_get_bool(settings, FreeRDP_GfxAVC444))
310 {
311 TEST_FAILURE("Expected /network:auto alone to turn the H.264 codecs on!\n");
312 result = FALSE;
313 }
314
315 return result;
316}
317
318static BOOL check_settings_modem_with_fonts(rdpSettings* settings)
319{
320 BOOL result = TRUE;
321
322 if (freerdp_settings_get_uint32(settings, FreeRDP_ConnectionType) != CONNECTION_TYPE_MODEM)
323 {
324 TEST_FAILURE("Expected ConnectionType = MODEM, but ConnectionType = %u!\n",
325 (unsigned)freerdp_settings_get_uint32(settings, FreeRDP_ConnectionType));
326 result = FALSE;
327 }
328
329 if (!freerdp_settings_get_bool(settings, FreeRDP_AllowFontSmoothing))
330 {
331 TEST_FAILURE("Expected AllowFontSmoothing = TRUE as +fonts asked, but /network:modem "
332 "turned it off!\n");
333 result = FALSE;
334 }
335
336 if (!freerdp_settings_get_bool(settings, FreeRDP_DisableWallpaper))
337 {
338 TEST_FAILURE("Expected DisableWallpaper = TRUE, the default of /network:modem!\n");
339 result = FALSE;
340 }
341
342 return result;
343}
344
345typedef struct
346{
347 int expected_status;
348 validate_settings_pr validate_settings;
349 const char* command_line[128];
350 struct
351 {
352 int index;
353 const char* expected_value;
354 } modified_arguments[8];
355 setup_settings_pr setup_settings;
356} test;
357
358// NOLINTBEGIN(bugprone-suspicious-missing-comma)
359static const test tests[] = {
360 { COMMAND_LINE_STATUS_PRINT_HELP,
361 check_settings_smartcard_no_redirection,
362 { "testfreerdp", "--help", nullptr },
363 { WINPR_C_ARRAY_INIT } },
364 { COMMAND_LINE_STATUS_PRINT_HELP,
365 check_settings_smartcard_no_redirection,
366 { "testfreerdp", "/help", nullptr },
367 { WINPR_C_ARRAY_INIT } },
368 { COMMAND_LINE_STATUS_PRINT_HELP,
369 check_settings_smartcard_no_redirection,
370 { "testfreerdp", "-help", nullptr },
371 { WINPR_C_ARRAY_INIT } },
372 { COMMAND_LINE_STATUS_PRINT_VERSION,
373 check_settings_smartcard_no_redirection,
374 { "testfreerdp", "--version", nullptr },
375 { WINPR_C_ARRAY_INIT } },
376 { COMMAND_LINE_STATUS_PRINT_VERSION,
377 check_settings_smartcard_no_redirection,
378 { "testfreerdp", "/version", nullptr },
379 { WINPR_C_ARRAY_INIT } },
380 { COMMAND_LINE_STATUS_PRINT_VERSION,
381 check_settings_smartcard_no_redirection,
382 { "testfreerdp", "-version", nullptr },
383 { WINPR_C_ARRAY_INIT } },
384 { 0,
385 check_settings_smartcard_no_redirection,
386 { "testfreerdp", "-v", "test.freerdp.com", nullptr },
387 { WINPR_C_ARRAY_INIT } },
388 { 0,
389 check_settings_smartcard_no_redirection,
390 { "testfreerdp", "--v", "test.freerdp.com", nullptr },
391 { WINPR_C_ARRAY_INIT } },
392 { 0,
393 check_settings_smartcard_no_redirection,
394 { "testfreerdp", "/v:test.freerdp.com", nullptr },
395 { WINPR_C_ARRAY_INIT } },
396 { 0,
397 check_settings_smartcard_no_redirection,
398 { "testfreerdp", "/sound", "/drive:media," DRIVE_REDIRECT_PATH, "/v:test.freerdp.com",
399 nullptr },
400 { WINPR_C_ARRAY_INIT } },
401 { 0,
402 check_settings_smartcard_no_redirection,
403 { "testfreerdp", "-u", "test", "-p", "test", "-v", "test.freerdp.com", nullptr },
404 { { 4, "****" }, WINPR_C_ARRAY_INIT } },
405 { 0,
406 check_settings_smartcard_no_redirection,
407 { "testfreerdp", "/u:test", "/p:test", "/v:test.freerdp.com", nullptr },
408 { { 2, "/p:****" }, WINPR_C_ARRAY_INIT } },
409 { COMMAND_LINE_ERROR_NO_KEYWORD,
410 check_settings_smartcard_no_redirection,
411 { "testfreerdp", "-invalid", nullptr },
412 { WINPR_C_ARRAY_INIT } },
413 { COMMAND_LINE_ERROR_NO_KEYWORD,
414 check_settings_smartcard_no_redirection,
415 { "testfreerdp", "--invalid", nullptr },
416 { WINPR_C_ARRAY_INIT } },
417#if defined(WITH_FREERDP_DEPRECATED_CMDLINE)
418 { COMMAND_LINE_STATUS_PRINT,
419 check_settings_smartcard_no_redirection,
420 { "testfreerdp", "/kbd-list", 0 },
421 { WINPR_C_ARRAY_INIT } },
422 { COMMAND_LINE_STATUS_PRINT,
423 check_settings_smartcard_no_redirection,
424 { "testfreerdp", "/monitor-list", 0 },
425 { WINPR_C_ARRAY_INIT } },
426#endif
427 { COMMAND_LINE_STATUS_PRINT,
428 check_settings_smartcard_no_redirection,
429 { "testfreerdp", "/list:kbd", nullptr },
430 { WINPR_C_ARRAY_INIT } },
431 { COMMAND_LINE_STATUS_PRINT,
432 check_settings_smartcard_no_redirection,
433 { "testfreerdp", "/list:monitor", nullptr },
434 { WINPR_C_ARRAY_INIT } },
435 { 0,
436 check_settings_smartcard_no_redirection,
437 { "testfreerdp", "/sound", "/drive:media:" DRIVE_REDIRECT_PATH, "/v:test.freerdp.com",
438 nullptr },
439 { WINPR_C_ARRAY_INIT } },
440 { 0,
441 check_settings_smartcard_no_redirection,
442 { "testfreerdp", "/sound", "/drive:media,/foo/bar/blabla", "/v:test.freerdp.com", nullptr },
443 { WINPR_C_ARRAY_INIT } },
444 { 0,
445 check_settings_gateway_response_timeout_default,
446 { "testfreerdp", "/gateway:type:arm,g:gw.contoso.com", "/v:test.freerdp.com", nullptr },
447 { WINPR_C_ARRAY_INIT } },
448 { 0,
449 check_settings_gateway_response_timeout_custom,
450 { "testfreerdp", "/gateway:type:arm,g:gw.contoso.com,timeout:120000", "/v:test.freerdp.com",
451 nullptr },
452 { WINPR_C_ARRAY_INIT } },
453 { 0,
454 check_settings_gateway_response_timeout_custom,
455 { "testfreerdp", "/gateway:type:http,g:gw.contoso.com,timeout:120000", "/v:test.freerdp.com",
456 nullptr },
457 { WINPR_C_ARRAY_INIT } },
458 { COMMAND_LINE_ERROR,
459 check_settings_gateway_response_timeout_default,
460 { "testfreerdp", "/gateway:type:arm,g:gw.contoso.com,timeout:0", "/v:test.freerdp.com",
461 nullptr },
462 { WINPR_C_ARRAY_INIT } },
463 { COMMAND_LINE_ERROR,
464 check_settings_gateway_response_timeout_default,
465 { "testfreerdp", "/gateway:type:arm,g:gw.contoso.com,timeout:abc", "/v:test.freerdp.com",
466 nullptr },
467 { WINPR_C_ARRAY_INIT } },
468 { 0,
469 check_settings_aad_user_agent,
470 { "testfreerdp", "/azure:tenantid:common,\"user-agent:TestAgent/1.0 (KHTML, like Gecko)\"",
471 "/v:test.freerdp.com", nullptr },
472 { WINPR_C_ARRAY_INIT } },
473 { 0,
474 check_settings_multimon_disabled,
475 { "testfreerdp", DISABLED_DISPLAY_OPTIONS_RDP, "/multimon:off", nullptr },
476 { WINPR_C_ARRAY_INIT },
477 setup_settings_multimon_force },
478 { 0,
479 check_settings_multimon_disabled,
480 { "testfreerdp", DISABLED_DISPLAY_OPTIONS_RDP, "-multimon", nullptr },
481 { WINPR_C_ARRAY_INIT },
482 setup_settings_multimon_force },
483 { 0,
484 check_settings_smart_sizing_disabled,
485 { "testfreerdp", DISABLED_DISPLAY_OPTIONS_RDP, "-smart-sizing", nullptr },
486 { WINPR_C_ARRAY_INIT } },
487 { 0,
488 check_settings_smart_sizing_disabled,
489 { "testfreerdp", DISABLED_DISPLAY_OPTIONS_RDP, "/smart-sizing:off", nullptr },
490 { WINPR_C_ARRAY_INIT } },
491 { 0,
492 check_settings_multimon_force,
493 { "testfreerdp", "--multimon", "force", nullptr },
494 { WINPR_C_ARRAY_INIT } },
495 { 0,
496 check_settings_smart_sizing_size,
497 { "testfreerdp", "--smart-sizing", "1024x768", nullptr },
498 { WINPR_C_ARRAY_INIT } },
499 { COMMAND_LINE_ERROR_UNEXPECTED_VALUE,
500 check_settings_smartcard_no_redirection,
501 { "testfreerdp", "/multimon:garbage", nullptr },
502 { WINPR_C_ARRAY_INIT } },
503 { COMMAND_LINE_ERROR_UNEXPECTED_VALUE,
504 check_settings_smartcard_no_redirection,
505 { "testfreerdp", "/smart-sizing:garbage", nullptr },
506 { WINPR_C_ARRAY_INIT } },
507 { COMMAND_LINE_ERROR_UNEXPECTED_VALUE,
508 check_settings_smartcard_no_redirection,
509 { "testfreerdp", "/multimon:", nullptr },
510 { WINPR_C_ARRAY_INIT } },
511 { COMMAND_LINE_ERROR_UNEXPECTED_VALUE,
512 check_settings_smartcard_no_redirection,
513 { "testfreerdp", "/smart-sizing:", nullptr },
514 { WINPR_C_ARRAY_INIT } },
515 { 0,
516 check_settings_multimon_enabled,
517 { "testfreerdp", "+multimon", nullptr },
518 { WINPR_C_ARRAY_INIT } },
519#if defined(WITH_GFX_H264)
520 { 0,
521 check_settings_gfx_without_h264,
522 { "testfreerdp", "/gfx:progressive,AVC420:off,AVC444:off", "/network:auto",
523 "/v:test.freerdp.com", nullptr },
524 { WINPR_C_ARRAY_INIT } },
525 { 0,
526 check_settings_gfx_without_h264,
527 { "testfreerdp", "/network:auto", "/gfx:progressive,AVC420:off,AVC444:off",
528 "/v:test.freerdp.com", nullptr },
529 { WINPR_C_ARRAY_INIT } },
530 { 0,
531 check_settings_network_auto_h264,
532 { "testfreerdp", "/network:auto", "/v:test.freerdp.com", nullptr },
533 { WINPR_C_ARRAY_INIT } },
534#endif
535 { 0,
536 check_settings_modem_with_fonts,
537 { "testfreerdp", "+fonts", "/network:modem", "/v:test.freerdp.com", nullptr },
538 { WINPR_C_ARRAY_INIT } },
539};
540// NOLINTEND(bugprone-suspicious-missing-comma)
541
542static void check_modified_arguments(const test* test, char** command_line, int* rc)
543{
544 const char* expected_argument = nullptr;
545
546 for (int k = 0; (expected_argument = test->modified_arguments[k].expected_value); k++)
547 {
548 int index = test->modified_arguments[k].index;
549 char* actual_argument = command_line[index];
550
551 if (0 != strcmp(actual_argument, expected_argument))
552 {
553 printref();
554 printf("Failure: overridden argument %d is %s but it should be %s\n", index,
555 actual_argument, expected_argument);
556 (void)fflush(stdout);
557 *rc = -1;
558 }
559 }
560}
561
562int TestClientCmdLine(int argc, char* argv[])
563{
564 int rc = 0;
565
566 WINPR_UNUSED(argc);
567 WINPR_UNUSED(argv);
568 for (size_t i = 0; i < ARRAYSIZE(tests); i++)
569 {
570 const test* current = &tests[i];
571 int failure = 0;
572 char** command_line = string_list_copy(current->command_line);
573
574 const int len = string_list_length((const char* const*)command_line);
575 if (!testcase(__func__, command_line, WINPR_ASSERTING_INT_CAST(size_t, len),
576 current->expected_status, current->validate_settings,
577 current->setup_settings))
578 {
579 TEST_FAILURE("parsing arguments.\n");
580 failure = 1;
581 }
582
583 check_modified_arguments(current, command_line, &failure);
584
585 if (failure)
586 {
587 string_list_print(stdout, (const char* const*)command_line);
588 rc = -1;
589 }
590
591 string_list_free(command_line);
592 }
593
594 return rc;
595}
FREERDP_API rdpSettings * freerdp_settings_new(DWORD flags)
creates a new setting struct
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
FREERDP_API void freerdp_settings_free(rdpSettings *settings)
Free a settings struct with all data in it.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.