FreeRDP
Loading...
Searching...
No Matches
TestCommandLineToCommaSeparatedValues.c
1
2#include <stdlib.h>
3#include <string.h>
4
5#include <winpr/wtypes.h>
6#include <winpr/cmdline.h>
7#include <winpr/path.h>
8#include <winpr/file.h>
9#include <winpr/json.h>
10
11static bool run(const char* name, int argc, char* argv[], bool expectSuccess, const char* compare)
12{
13 size_t count = 0;
14
15 printf("[%s] running test...\n", name);
16
17 char* res = CommandLineToCommaSeparatedValues(argc, argv);
18 if (!res)
19 {
20 if (expectSuccess)
21 (void)fprintf(stderr, "[%s] CSV expected success, but failed\n", name);
22 return !expectSuccess;
23 }
24
25 if (compare)
26 {
27 if (strcmp(compare, res) != 0)
28 {
29 (void)fprintf(stderr, "[%s] CSV compare fail:\ngot : %s\nexpect: %s\n", name, res,
30 compare);
31 free(res);
32 return !expectSuccess;
33 }
34 }
35
36 bool rc = false;
37 if (argc >= 0)
38 {
39 char** ares = CommandLineParseCommaSeparatedValues(res, &count);
40
41 if (count == WINPR_ASSERTING_INT_CAST(size_t, argc))
42 {
43 rc = true;
44
45 for (size_t x = 0; x < count; x++)
46 {
47 const char* argvx = argv[x];
48 const char* aresx = ares[x];
49
50 if (strcmp(argvx, aresx) != 0)
51 {
52 (void)fprintf(stderr, "[%s] ARGV compare fail:\ngot : %s\nexpect: %s\n", name,
53 argvx, aresx);
54 rc = false;
55 }
56 }
57 }
58
59 CommandLineParserFree(ares);
60 }
61 free(res);
62 return rc == expectSuccess;
63}
64
65static void TestCaseFree(int argc, char** argv)
66{
67 if (!argv)
68 return;
69
70 for (int i = 0; i < argc; i++)
71 {
72 free(argv[i]);
73 }
74 free((void*)argv);
75}
76
77static void usage(const char* file)
78{
79 WINPR_ASSERT(file);
80 (void)fprintf(stderr, "Failed to parse test case '%s'\n", file);
81 (void)fprintf(stderr,
82 "Test cases for TestCommandLineToCommaSeparatedValues should be JSON files\n");
83 (void)fprintf(stderr, "placed in the folder '%s'\n", TEST_SOURCE_DIR);
84 (void)fprintf(stderr, "with '.json' (case sensitive) as extension.\n");
85 (void)fprintf(stderr, "\n");
86 (void)fprintf(stderr, "The JSON should be of the following format:\n");
87 (void)fprintf(stderr, "\n");
88 (void)fprintf(stderr, "{\n");
89 (void)fprintf(stderr, "\t\"expectSuccess\": true,\n");
90 (void)fprintf(stderr, "{\t\"csv\": \"\\\"string1\\\",\\\"string2\\\",...\"\n");
91 (void)fprintf(stderr, "\t\"argv\": [ \"string1\", \"string2\", null, \"string3\" ]\n");
92 (void)fprintf(stderr, "}\n");
93}
94
95WINPR_ATTR_MALLOC(TestCaseFree, 2)
96static char** getTestcase(const char* path, const char* filename, int* pargc, bool* pexpectSuccess,
97 char** compare)
98{
99 WINPR_ASSERT(path);
100 WINPR_ASSERT(filename);
101 WINPR_ASSERT(pargc);
102 WINPR_ASSERT(pexpectSuccess);
103
104 BOOL success = FALSE;
105 int argc = 0;
106 char** argv = nullptr;
107 char* fpath = GetCombinedPath(path, filename);
108 if (!fpath)
109 {
110 (void)fprintf(stderr, "GetCombinedPath(%s, %s) failed\n", path, filename);
111 usage(filename);
112 return nullptr;
113 }
114
115 WINPR_JSON* json = WINPR_JSON_ParseFromFile(fpath);
116 if (!json)
117 {
118 (void)fprintf(stderr, "WINPR_JSON_ParseFromFile(%s) failed\n", fpath);
119 usage(filename);
120 free(fpath);
121 return nullptr;
122 }
123 free(fpath);
124
125 if (!WINPR_JSON_IsObject(json))
126 {
127 (void)fprintf(stderr, "WINPR_JSON_IsObject() failed\n");
128 goto fail;
129 }
130
131 /* optional compare string for CSV version */
132 {
133 WINPR_JSON* jexpect = WINPR_JSON_GetObjectItem(json, "csv");
134 if (WINPR_JSON_IsString(jexpect))
135 {
136 const char* str = WINPR_JSON_GetStringValue(jexpect);
137 if (!str)
138 {
139 (void)fprintf(stderr, "WINPR_JSON_GetStringValue(csv) failed\n");
140 goto fail;
141 }
142 *compare = _strdup(str);
143 if (!*compare)
144 {
145 (void)fprintf(stderr, "_strdup(csv[%s]) failed\n", str);
146 goto fail;
147 }
148 }
149 *pexpectSuccess = WINPR_JSON_IsTrue(jexpect);
150 }
151
152 {
153 WINPR_JSON* jexpect = WINPR_JSON_GetObjectItem(json, "expectSuccess");
154 if (!WINPR_JSON_IsBool(jexpect))
155 {
156 (void)fprintf(stderr, "WINPR_JSON_GetObjectItem(expectSuccess) failed\n");
157 goto fail;
158 }
159 *pexpectSuccess = WINPR_JSON_IsTrue(jexpect);
160 }
161
162 {
163 WINPR_JSON* jargv = WINPR_JSON_GetObjectItem(json, "argv");
164 if (!WINPR_JSON_IsArray(jargv))
165 {
166 (void)fprintf(stderr, "WINPR_JSON_IsArray(argv) failed\n");
167 goto fail;
168 }
169
170 const size_t len = WINPR_JSON_GetArraySize(jargv);
171 if (len == 0)
172 {
173 (void)fprintf(stderr, "WINPR_JSON_GetArraySize(argv) == 0\n");
174 goto fail;
175 }
176
177 argv = (char**)calloc(len, sizeof(char*));
178 if (!argv)
179 {
180 (void)fprintf(stderr, "calloc(%" PRIuz ", sizeof(char*)) failed\n", len);
181 goto fail;
182 }
183
184 argc = WINPR_ASSERTING_INT_CAST(int, len);
185 for (size_t x = 0; x < len; x++)
186 {
187 WINPR_JSON* jstr = WINPR_JSON_GetArrayItem(jargv, x);
188 if (WINPR_JSON_IsNull(jstr))
189 continue;
190
191 if (!WINPR_JSON_IsString(jstr))
192 {
193 (void)fprintf(stderr, "WINPR_JSON_IsString(%" PRIuz ") failed", x);
194 goto fail;
195 }
196 const char* str = WINPR_JSON_GetStringValue(jstr);
197 if (str)
198 {
199 argv[x] = _strdup(str);
200 if (!argv[x])
201 {
202 (void)fprintf(stderr, "WINPR_JSON_GetStringValue(%s) _strdup() failed", str);
203 goto fail;
204 }
205 }
206 }
207 }
208 *pargc = argc;
209 success = true;
210
211fail:
212 WINPR_JSON_Delete(json);
213 if (success)
214 return argv;
215
216 usage(filename);
217 TestCaseFree(argc, argv);
218 return nullptr;
219}
220
221static int runJsonTests(void)
222{
223 char testdir[MAX_PATH] = WINPR_C_ARRAY_INIT;
224 (void)_snprintf(testdir, sizeof(testdir), "cmdline-tests%c*.json",
225 PathGetSeparatorA(PATH_STYLE_NATIVE));
226 int rc = -1;
227 char* path = GetCombinedPath(TEST_SOURCE_DIR, testdir);
228 if (!path)
229 return 0; /* No tests, ignore */
230
231 WIN32_FIND_DATAA FindData = { 0 };
232 HANDLE hFind = FindFirstFileA(path, &FindData);
233 free(path);
234 path = GetCombinedPath(TEST_SOURCE_DIR, "cmdline-tests");
235 if (!path)
236 goto fail;
237
238 if (hFind == INVALID_HANDLE_VALUE)
239 {
240 printf("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", path);
241 goto fail;
242 }
243
244 do
245 {
246 char* compare = nullptr;
247 int argc = 0;
248 bool expectSuccess = false;
249 char** argv = getTestcase(path, FindData.cFileName, &argc, &expectSuccess, &compare);
250 if (!argv)
251 {
252 free(compare);
253 (void)fprintf(stderr, "Test case '%s/%s': could not be parsed, aborting!\n", path,
254 FindData.cFileName);
255 goto fail;
256 }
257
258 rc = run(FindData.cFileName, argc, argv, expectSuccess, compare);
259 TestCaseFree(argc, argv);
260 free(compare);
261 if (rc < 0)
262 {
263 (void)fprintf(stderr, "Test case '%s/%s': test run failed, aborting!\n", path,
264 FindData.cFileName);
265 goto fail;
266 }
267 } while (FindNextFileA(hFind, &FindData));
268
269 rc = 0;
270
271fail:
272 FindClose(hFind);
273 free(path);
274 return rc;
275}
276
277int TestCommandLineToCommaSeparatedValues(int argc, char* argv[])
278{
279 if (argc > 1)
280 return run("from-commandline", argc, argv, true, nullptr);
281
282 return runJsonTests();
283}
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsNull(const WINPR_JSON *item)
Check if JSON item is Null.
Definition c-json.c:172
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsBool(const WINPR_JSON *item)
Check if JSON item is of type BOOL.
Definition c-json.c:167
WINPR_ATTR_NODISCARD WINPR_API size_t WINPR_JSON_GetArraySize(const WINPR_JSON *array)
Get the number of arrayitems from an array.
Definition c-json.c:114
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsTrue(const WINPR_JSON *item)
Check if JSON item is BOOL value True.
Definition c-json.c:162
WINPR_API WINPR_JSON * WINPR_JSON_ParseFromFile(const char *filename)
Parse a JSON string read from a file filename.
Definition json.c:27
WINPR_ATTR_NODISCARD WINPR_API WINPR_JSON * WINPR_JSON_GetObjectItem(const WINPR_JSON *object, const char *string)
Return a pointer to an JSON object item.
Definition c-json.c:122
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsString(const WINPR_JSON *item)
Check if JSON item is of type String.
Definition c-json.c:182
WINPR_ATTR_NODISCARD WINPR_API WINPR_JSON * WINPR_JSON_GetArrayItem(const WINPR_JSON *array, size_t index)
Return a pointer to an item in the array.
Definition c-json.c:108
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsArray(const WINPR_JSON *item)
Check if JSON item is of type Array.
Definition c-json.c:187
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsObject(const WINPR_JSON *item)
Check if JSON item is of type Object.
Definition c-json.c:192
WINPR_API void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.
Definition c-json.c:103
WINPR_ATTR_NODISCARD WINPR_API const char * WINPR_JSON_GetStringValue(WINPR_JSON *item)
Return the String value of a JSON item.
Definition c-json.c:142