Return a non-zero result if some tests failed.
[AROS.git] / test / dos / readargs.c
blob5c059f613fd2ce97736cc5ec07a51446c1b618bb
1 /*
2 * Copyright (C) 2011-2015, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
6 */
8 #include <string.h> /* for memset() */
10 #include <proto/alib.h>
11 #include <proto/exec.h>
12 #include <proto/dos.h>
14 #include <dos/stdio.h>
15 #include <exec/lists.h>
17 /* For compatibility with AOS, our test reference */
18 #ifdef __mc68000
19 static AROS_UFH2(VOID, _SPutC,
20 AROS_UFHA(BYTE, c, D0),
21 AROS_UFHA(BYTE **, ptr, A3))
23 AROS_USERFUNC_INIT
25 **ptr = c;
27 (*ptr)++;
29 AROS_USERFUNC_EXIT
32 VOID SPrintf( char *target, const char *format, ...)
34 RawDoFmt( format, (APTR)&(((ULONG *)&format)[1]), _SPutC, &target);
36 #else
37 #define SPrintf(target,format,args...) __sprintf(target,format ,##args )
38 #endif
40 #define TEST_START(name) do { \
41 CONST_STRPTR test_name = name ; \
42 struct List expr_list; \
43 int failed = 0; \
44 tests++; \
45 NEWLIST(&expr_list);
47 #define VERIFY_EQ(retval, expected) \
48 do { \
49 __typeof__(retval) val = retval; \
50 if (val != (expected)) { \
51 struct Node *expr_node = AllocVec(sizeof(struct Node) + 256, MEMF_ANY); \
52 expr_node->ln_Name = (TEXT *)(&expr_node[1]); \
53 SPrintf(expr_node->ln_Name, "%s: %s (%ld) != %ld", mname, #retval , (LONG)(SIPTR)val, (LONG)(SIPTR)expected); \
54 AddTail(&expr_list, expr_node); \
55 failed |= 1; \
56 } \
57 } while (0)
59 #define VERIFY_STREQ(retval, expected) \
60 do { \
61 CONST_STRPTR val = (CONST_STRPTR)(retval); \
62 if (strcmp(val,(expected)) != 0) { \
63 struct Node *expr_node = AllocVec(sizeof(struct Node) + 256, MEMF_ANY); \
64 expr_node->ln_Name = (TEXT *)(&expr_node[1]); \
65 SPrintf(expr_node->ln_Name, "%s: %s (%s) != %s", mname, #retval, val, expected); \
66 AddTail(&expr_list, expr_node); \
67 failed |= 1; \
68 } \
69 } while (0)
72 #define VERIFY_RET(func, ret, reterr) \
73 do { \
74 SetIoErr(-1); \
75 VERIFY_EQ(func, ret); \
76 VERIFY_EQ(IoErr(), reterr); \
77 } while (0)
79 #define TEST_END() \
80 if (failed) { \
81 struct Node *node; \
82 tests_failed++; \
83 Printf("Test %ld: Failed (%s)\n", (LONG)tests, test_name); \
84 while ((node = RemHead(&expr_list)) != NULL) { \
85 Printf("\t%s\n", node->ln_Name); \
86 FreeVec(node); \
87 } \
88 } \
89 } while (0)
91 static inline SIPTR readargs_buff(CONST_STRPTR format, IPTR *args, CONST_STRPTR input, struct RDArgs **retp)
93 SIPTR retval;
94 struct RDArgs *ret, *in;
96 in = AllocDosObject(DOS_RDARGS, NULL);
97 in->RDA_Source.CS_Buffer = (APTR)input;
98 in->RDA_Source.CS_Length = strlen(input);
99 in->RDA_Source.CS_CurChr = 0;
101 SetIoErr(0);
102 ret = ReadArgs(format, args, in);
104 *retp = ret;
105 retval = (ret != NULL) ? RETURN_OK : IoErr();
107 return retval;
110 static inline SIPTR readargs_file(CONST_STRPTR format, IPTR *args, CONST_STRPTR input, struct RDArgs **retp)
112 SIPTR retval;
113 struct RDArgs *ret;
114 BPTR oldin;
115 BPTR io;
116 CONST_STRPTR tmpfile = "RAM:readargs.test";
117 BPTR oldout;
118 oldout = SelectOutput(Open("NIL:", MODE_NEWFILE));
120 io = Open(tmpfile, MODE_NEWFILE);
121 Write(io, input, strlen(input));
122 Close(io);
124 io = Open(tmpfile, MODE_OLDFILE);
126 oldin = Input();
127 SelectInput(io);
128 SetIoErr(0);
129 ret = ReadArgs(format, args, NULL);
131 *retp = ret;
132 retval = (ret != NULL) ? RETURN_OK : IoErr();
134 Close(SelectInput(oldin));
135 Close(SelectOutput(oldout));
137 DeleteFile(tmpfile);
139 return retval;
142 #define TEST_READARGS(format, input) \
143 TEST_START(format " '" input "'"); \
144 int is_buff;\
145 for (is_buff = 0; is_buff < 2; is_buff++) { \
146 CONST_STRPTR mname = is_buff ? "buff" : "file"; \
147 IPTR args[10] = { (IPTR)"inv1", (IPTR)"inv2", (IPTR)"inv3" }; \
148 SIPTR ioerr; \
149 struct RDArgs *ret = NULL; \
150 if (is_buff) { \
151 ioerr = readargs_buff(format, (IPTR *)&args[0], Need_Implicit_NL ? input "\n" : input, &ret); \
152 } else { \
153 ioerr = readargs_file(format, (IPTR *)&args[0], input, &ret); }
155 #define TEST_ENDARGS() \
156 if (ret) FreeDosObject(DOS_RDARGS, ret); \
158 TEST_END();
160 int main(int argc, char **argv)
162 int tests = 0, tests_failed = 0;
163 BOOL Need_Implicit_NL;
165 /* The following behaviour is versus AOS 3.1,
166 * which should be used as the reference for
167 * the AROS implementation
169 Need_Implicit_NL = FALSE;
171 /* Verify that the buffer version requires a \n
172 * at the end, and the file version does not.
174 TEST_READARGS("KEYA","val1\n");
175 VERIFY_EQ(ioerr, RETURN_OK);
176 VERIFY_STREQ(args[0], "val1");
177 TEST_ENDARGS();
179 TEST_READARGS("KEYA","val1");
180 if (is_buff) {
181 // Succeeds on AROS, fails on AOS.
182 // Ok to not fix.
183 // AOS: VERIFY_EQ(ioerr, ERROR_TOO_MANY_ARGS);
184 // AROS: VERIFY_EQ(ioerr, RETURN_OK);
185 } else
186 VERIFY_EQ(ioerr, RETURN_OK);
187 VERIFY_STREQ(args[0], "val1");
188 TEST_ENDARGS();
190 TEST_READARGS("KEYA","?\n\n");
191 VERIFY_EQ(ioerr, RETURN_OK);
192 VERIFY_STREQ(args[0], "inv1");
193 TEST_ENDARGS();
195 TEST_READARGS("KEYA","?\nval1\n");
196 VERIFY_EQ(ioerr, RETURN_OK);
197 VERIFY_STREQ(args[0], "val1");
198 TEST_ENDARGS();
200 TEST_READARGS("KEYA","?\nval1");
201 if (is_buff) {
202 // Succeeds on AROS, fails on AOS.
203 // Ok to not fix.
204 // AOS: VERIFY_EQ(ioerr, ERROR_TOO_MANY_ARGS);
205 // AROS: VERIFY_EQ(ioerr, RETURN_OK);
206 } else
207 VERIFY_EQ(ioerr, RETURN_OK);
208 VERIFY_STREQ(args[0], "val1");
209 TEST_ENDARGS();
211 TEST_READARGS("KEYA","keya val1\n");
212 VERIFY_EQ(ioerr, RETURN_OK);
213 VERIFY_STREQ(args[0], "val1");
214 TEST_ENDARGS();
216 TEST_READARGS("KEYA","keya val1");
217 if (is_buff) {
218 // Succeeds on AROS, fails on AOS.
219 // Ok to not fix.
220 // AOS: VERIFY_EQ(ioerr, ERROR_TOO_MANY_ARGS);
221 // AROS: VERIFY_EQ(ioerr, RETURN_OK);
222 } else
223 VERIFY_EQ(ioerr, RETURN_OK);
224 VERIFY_STREQ(args[0], "val1");
225 TEST_ENDARGS();
227 TEST_READARGS("KEYA,KEYB","val1 keyb ");
228 VERIFY_EQ(ioerr, ERROR_KEY_NEEDS_ARG);
229 // Acceptable difference:
230 // AOS: VERIFY_STREQ(args[0], "val1");
231 // AROS: VERIFY_STREQ(args[0], "inv1");
232 VERIFY_STREQ(args[1], "inv2");
233 TEST_ENDARGS();
235 TEST_READARGS("KEYA,KEYB","val1 keyb ");
236 VERIFY_EQ(ioerr, ERROR_KEY_NEEDS_ARG);
237 // Acceptable difference:
238 // AOS: VERIFY_STREQ(args[0], "val1");
239 // AROS: VERIFY_STREQ(args[0], "inv1");
240 VERIFY_STREQ(args[1], "inv2");
241 TEST_ENDARGS();
243 Need_Implicit_NL = TRUE;
245 /* Verify that \n is treated as part of the key name,
246 * and is not ignored at the end of the ReadArgs template
248 TEST_READARGS("KEYA\n","keya val1");
249 VERIFY_EQ(ioerr, ERROR_TOO_MANY_ARGS);
250 TEST_ENDARGS();
252 TEST_READARGS("KEYA","keya=val1");
253 VERIFY_EQ(ioerr, RETURN_OK);
254 VERIFY_STREQ(args[0], "val1");
255 TEST_ENDARGS();
257 TEST_READARGS("KEYA,KEYB","val1 val2");
258 VERIFY_EQ(ioerr, RETURN_OK);
259 VERIFY_STREQ(args[0], "val1");
260 VERIFY_STREQ(args[1], "val2");
261 TEST_ENDARGS();
263 TEST_READARGS("KEYA,KEYB","keya=val1 keyb=val2");
264 VERIFY_EQ(ioerr, RETURN_OK);
265 VERIFY_STREQ(args[0], "val1");
266 VERIFY_STREQ(args[1], "val2");
267 TEST_ENDARGS();
269 TEST_READARGS("KEYA,KEYB","keya val1 keyb val2");
270 VERIFY_EQ(ioerr, RETURN_OK);
271 VERIFY_STREQ(args[0], "val1");
272 VERIFY_STREQ(args[1], "val2");
273 TEST_ENDARGS();
275 TEST_READARGS("KEYA,KEYB","keya val1 val2");
276 VERIFY_EQ(ioerr, RETURN_OK);
277 VERIFY_STREQ(args[0], "val1");
278 VERIFY_STREQ(args[1], "val2");
279 TEST_ENDARGS();
281 TEST_READARGS("KEYA,KEYB","keyb val2 val1");
282 VERIFY_EQ(ioerr, RETURN_OK);
283 VERIFY_STREQ(args[0], "val1");
284 VERIFY_STREQ(args[1], "val2");
285 TEST_ENDARGS();
287 TEST_READARGS("KEYA,KEYB","keyb val2 keya val1");
288 VERIFY_EQ(ioerr, RETURN_OK);
289 VERIFY_STREQ(args[0], "val1");
290 VERIFY_STREQ(args[1], "val2");
291 TEST_ENDARGS();
293 TEST_READARGS("KEYA,KEYB/F","val1 val2 val3");
294 VERIFY_EQ(ioerr, RETURN_OK);
295 VERIFY_STREQ(args[0], "val1");
296 VERIFY_STREQ(args[1], "val2 val3");
297 TEST_ENDARGS();
299 TEST_READARGS("KEYA,KEYB/F","val1 val2 val3=val4 \"val5\" keya=val6");
300 VERIFY_EQ(ioerr, RETURN_OK);
301 VERIFY_STREQ(args[0], "val1");
302 VERIFY_STREQ(args[1], "val2 val3=val4 \"val5\" keya=val6");
303 TEST_ENDARGS();
305 TEST_READARGS("KEYA,KEYB/F","val1 val2 val3\n");
306 VERIFY_EQ(ioerr, RETURN_OK);
307 VERIFY_STREQ(args[0], "val1");
308 VERIFY_STREQ(args[1], "val2 val3");
309 TEST_ENDARGS();
311 TEST_READARGS("KEYA,KEYB/F,KEYC","val1 keyc val4 val2 val3\n");
312 VERIFY_EQ(ioerr, RETURN_OK);
313 VERIFY_STREQ(args[0], "val1");
314 VERIFY_STREQ(args[1], "val2 val3");
315 VERIFY_STREQ(args[2], "val4");
316 TEST_ENDARGS();
318 TEST_READARGS("KEYA,KEYB/M","val1 val2 val3");
319 VERIFY_EQ(ioerr, RETURN_OK);
320 VERIFY_STREQ(args[0], "val1");
321 VERIFY_STREQ(((CONST_STRPTR *)args[1])[0], "val2");
322 VERIFY_STREQ(((CONST_STRPTR *)args[1])[1], "val3");
323 VERIFY_EQ(((CONST_STRPTR *)args[1])[2], NULL);
324 TEST_ENDARGS();
326 TEST_READARGS("KEYA,KEYB/M","keyb=val1 keya=val2 keyb=val3");
327 VERIFY_EQ(ioerr, RETURN_OK);
328 VERIFY_STREQ(args[0], "val2");
329 VERIFY_STREQ(((CONST_STRPTR *)args[1])[0], "val1");
330 VERIFY_STREQ(((CONST_STRPTR *)args[1])[1], "val3");
331 VERIFY_EQ(((CONST_STRPTR *)args[1])[2], NULL);
332 TEST_ENDARGS();
334 TEST_READARGS("KEYA,KEYB/M,KEYC","keyb=val1 keya=val2 val3 val4");
335 VERIFY_EQ(ioerr, RETURN_OK);
336 VERIFY_STREQ(args[0], "val2");
337 VERIFY_STREQ(((CONST_STRPTR *)args[1])[0], "val1");
338 VERIFY_STREQ(((CONST_STRPTR *)args[1])[1], "val3");
339 VERIFY_STREQ(((CONST_STRPTR *)args[1])[2], "val4");
340 VERIFY_EQ(((CONST_STRPTR *)args[1])[3], NULL);
341 TEST_ENDARGS();
343 TEST_READARGS("KEYA/S,KEYB,KEYC","keyb=val1 keya val3");
344 VERIFY_EQ(ioerr, RETURN_OK);
345 VERIFY_EQ(args[0], DOSTRUE);
346 VERIFY_STREQ(args[1],"val1");
347 VERIFY_STREQ(args[2],"val3");
348 TEST_ENDARGS();
350 TEST_READARGS("KEYA/K,KEYB,KEYC","val1 keya val2 val3");
351 VERIFY_EQ(ioerr, RETURN_OK);
352 VERIFY_STREQ(args[0],"val2");
353 VERIFY_STREQ(args[1],"val1");
354 VERIFY_STREQ(args[2],"val3");
355 TEST_ENDARGS();
357 TEST_READARGS("KEYA/S,KEYB/F","keya \"val1 val2\"");
358 VERIFY_EQ(ioerr, RETURN_OK);
359 VERIFY_EQ(args[0],DOSTRUE);
360 VERIFY_STREQ(args[1],"val1 val2");
361 TEST_ENDARGS();
363 TEST_READARGS("KEYA/S,KEYB/F","\"val1 val2\"");
364 VERIFY_EQ(ioerr, RETURN_OK);
365 VERIFY_STREQ(args[0],"inv1");
366 VERIFY_STREQ(args[1],"val1 val2");
367 TEST_ENDARGS();
369 TEST_READARGS("KEYA/S,KEYB/F","\"val1\" val2");
370 VERIFY_EQ(ioerr, RETURN_OK);
371 VERIFY_STREQ(args[0],"inv1");
372 VERIFY_STREQ(args[1],"val1 val2");
373 TEST_ENDARGS();
375 TEST_READARGS("KEYA/S,KEYB/F","val1 \"val2\"");
376 VERIFY_EQ(ioerr, RETURN_OK);
377 VERIFY_STREQ(args[0],"inv1");
378 VERIFY_STREQ(args[1],"val1 \"val2\"");
379 TEST_ENDARGS();
381 TEST_READARGS("KEYA/S,KEYB/F","\"va\"l1 \"val2");
382 VERIFY_EQ(ioerr, RETURN_OK);
383 VERIFY_STREQ(args[0],"inv1");
384 VERIFY_STREQ(args[1],"val1 \"val2");
385 TEST_ENDARGS();
387 TEST_READARGS("KEYA/S,KEYB/F","\"va\"l1 \"val2\"");
388 VERIFY_EQ(ioerr, RETURN_OK);
389 VERIFY_STREQ(args[0],"inv1");
390 VERIFY_STREQ(args[1],"val1 \"val2\"");
391 TEST_ENDARGS();
393 if (tests_failed == 0)
394 Printf("All %ld test passed\n", (LONG)tests);
395 else
396 Printf("%ld of %ld tests failed\n", (LONG)tests_failed, (LONG)tests);
398 Flush(Output());
400 return tests_failed == 0 ? RETURN_OK : RETURN_WARN;