Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #include <kdberrors.h>
10 : #include <kdbopts.h>
11 :
12 : #include "tests.h"
13 :
14 : #define PROC_BASE_KEY "proc/tests/opts"
15 : #define SPEC_BASE_KEY "spec/tests/opts"
16 :
17 : // version 6 and 7 of clang-format don't agree whether it is supposed to be *[] or * [] so disable it here
18 : // TODO: re-enable clang-format once version 7 is used on build server
19 : // clang-format off
20 : #define NUMARGS(...) (sizeof ((void *[]){ __VA_ARGS__ }) / sizeof (void *))
21 : #define ARGS(...) NUMARGS ("prog", __VA_ARGS__), ((const char *[]){ "prog", __VA_ARGS__, NULL })
22 : #define NO_ARGS 1, ((const char *[]){ "prog" })
23 :
24 : #define ENVP(...) ((const char *[]){ __VA_ARGS__, NULL })
25 : #define NO_ENVP ((const char *[]){ NULL })
26 : // clang-format on
27 :
28 : #define xstr(a) str (a)
29 : #define str(a) #a
30 :
31 : #define RUN_TEST(ks, args, envp) \
32 : { \
33 : Key * ek = keyNew (SPEC_BASE_KEY, KEY_END); \
34 : if (elektraGetOpts (ks, args, envp, ek) != 0) \
35 : { \
36 : yield_error ("error found"); \
37 : output_error (ek); \
38 : } \
39 : keyDel (ek); \
40 : }
41 :
42 : #define RUN_TEST_ERROR(ks, errorKey, args, envp) \
43 : { \
44 : errorKey = keyNew (SPEC_BASE_KEY, KEY_END); \
45 : if (elektraGetOpts (ks, args, envp, errorKey) >= 0) \
46 : { \
47 : yield_error ("should have failed"); \
48 : } \
49 : }
50 :
51 : #ifdef _WIN32
52 : #define ENV_SEP ";"
53 : #else
54 : #define ENV_SEP ":"
55 : #endif
56 :
57 : #define checkHelpMessage(errorKey, expected) \
58 : { \
59 : char * actual = elektraGetOptsHelpMessage (errorKey, NULL, NULL); \
60 : succeed_if_same_string (actual, expected); \
61 : elektraFree (actual); \
62 : }
63 :
64 36 : static inline Key * keyWithOpt (const char * name, const char shortOpt, const char * longOpt, const char * envVar)
65 : {
66 36 : return keyNew (name, KEY_META, "opt", (const char[]){ shortOpt, '\0' }, KEY_META, "opt/long", longOpt, KEY_META, "env", envVar,
67 : KEY_END);
68 : }
69 :
70 168 : static bool checkValue (KeySet * ks, const char * name, const char * expected)
71 : {
72 168 : Key * key = ksLookupByName (ks, name, 0);
73 168 : if (key == NULL)
74 : {
75 10 : return expected == NULL;
76 : }
77 :
78 158 : const char * actual = keyString (key);
79 158 : return expected == NULL ? strlen (actual) == 0 : strcmp (actual, expected) == 0;
80 : }
81 :
82 10 : static bool checkMeta (KeySet * ks, const char * name, const char * meta, const char * expected)
83 : {
84 10 : Key * key = ksLookupByName (ks, name, 0);
85 10 : if (key == NULL)
86 : {
87 0 : return expected == NULL;
88 : }
89 :
90 10 : const Key * metaKey = keyGetMeta (key, meta);
91 10 : if (metaKey == NULL)
92 : {
93 0 : return expected == NULL;
94 : }
95 :
96 10 : const char * actual = keyString (metaKey);
97 10 : return expected == NULL ? strlen (actual) == 0 : strcmp (actual, expected) == 0;
98 : }
99 :
100 46 : static bool checkError (Key * errorKey, const char * expectedNumber, const char * expectedReason)
101 : {
102 46 : const Key * metaError = keyGetMeta (errorKey, "error");
103 46 : if (metaError == NULL)
104 : {
105 : return false;
106 : }
107 :
108 46 : const char * actualNumber = keyString (keyGetMeta (errorKey, "error/number"));
109 46 : const char * actualReason = keyString (keyGetMeta (errorKey, "error/reason"));
110 :
111 46 : bool result = strcmp (actualNumber, expectedNumber) == 0 && strcmp (actualReason, expectedReason) == 0;
112 :
113 46 : keyDel (errorKey);
114 :
115 46 : return result;
116 : }
117 :
118 166 : static void clearValues (KeySet * ks)
119 : {
120 166 : cursor_t cursor = ksGetCursor (ks);
121 :
122 166 : ksRewind (ks);
123 : Key * cur;
124 716 : while ((cur = ksNext (ks)) != NULL)
125 : {
126 384 : keySetString (cur, NULL);
127 384 : keySetMeta (cur, "array", NULL);
128 : }
129 :
130 166 : ksSetCursor (ks, cursor);
131 166 : }
132 :
133 2 : static void test_simple (void)
134 : {
135 2 : KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", "APPLE"), KS_END);
136 :
137 2 : RUN_TEST (ks, NO_ARGS, NO_ENVP);
138 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", NULL), "no option failed");
139 2 : clearValues (ks);
140 :
141 2 : RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
142 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option failed");
143 2 : clearValues (ks);
144 :
145 2 : RUN_TEST (ks, ARGS ("-ashort"), NO_ENVP);
146 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option (combined) failed");
147 2 : clearValues (ks);
148 :
149 2 : RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
150 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option failed");
151 2 : clearValues (ks);
152 :
153 2 : RUN_TEST (ks, ARGS ("--apple=long"), NO_ENVP);
154 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
155 2 : clearValues (ks);
156 :
157 2 : RUN_TEST (ks, NO_ARGS, ENVP ("APPLE=env"));
158 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "env"), "env-var failed");
159 2 : clearValues (ks);
160 :
161 2 : ksDel (ks);
162 2 : }
163 :
164 2 : static void test_short_only (void)
165 : {
166 2 : KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', NULL, NULL), KS_END);
167 :
168 2 : RUN_TEST (ks, NO_ARGS, NO_ENVP);
169 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", NULL), "no option failed");
170 2 : clearValues (ks);
171 :
172 2 : RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
173 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option failed");
174 2 : clearValues (ks);
175 :
176 2 : RUN_TEST (ks, ARGS ("-ashort"), NO_ENVP);
177 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option (combined) failed");
178 2 : clearValues (ks);
179 :
180 2 : ksDel (ks);
181 2 : }
182 :
183 2 : static void test_long_only (void)
184 : {
185 2 : KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 0, "apple", NULL), KS_END);
186 :
187 2 : RUN_TEST (ks, NO_ARGS, NO_ENVP);
188 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", NULL), "no option failed");
189 2 : clearValues (ks);
190 :
191 2 : RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
192 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option failed");
193 2 : clearValues (ks);
194 :
195 2 : RUN_TEST (ks, ARGS ("--apple=long"), NO_ENVP);
196 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
197 2 : clearValues (ks);
198 :
199 2 : ksDel (ks);
200 2 : }
201 :
202 2 : static void test_env_only (void)
203 : {
204 2 : KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 0, NULL, "APPLE"), KS_END);
205 :
206 2 : RUN_TEST (ks, NO_ARGS, NO_ENVP);
207 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", NULL), "no option failed");
208 2 : clearValues (ks);
209 :
210 2 : RUN_TEST (ks, NO_ARGS, ENVP ("APPLE=env"));
211 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "env"), "env-var failed");
212 2 : clearValues (ks);
213 :
214 2 : ksDel (ks);
215 2 : }
216 :
217 2 : static void test_flag (void)
218 : {
219 2 : Key * k = keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL);
220 2 : keySetMeta (k, "opt/arg", "none");
221 2 : KeySet * ks = ksNew (1, k, KS_END);
222 :
223 2 : RUN_TEST (ks, ARGS ("-a"), NO_ENVP);
224 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "short flag failed");
225 2 : clearValues (ks);
226 :
227 2 : RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
228 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "short flag (with arg) failed");
229 2 : clearValues (ks);
230 :
231 : Key * errorKey;
232 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("-ashort"), NO_ENVP);
233 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Unknown short option: -s"),
234 : "short flag (with arg, combined) should have failed");
235 2 : clearValues (ks);
236 :
237 2 : RUN_TEST (ks, ARGS ("--apple"), NO_ENVP);
238 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "long flag failed");
239 2 : clearValues (ks);
240 :
241 2 : RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
242 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "long flag (with arg) failed");
243 2 : clearValues (ks);
244 :
245 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple=long"), NO_ENVP);
246 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot have an argument: --apple"),
247 : "long flag (with arg, combined) should have failed");
248 2 : clearValues (ks);
249 :
250 2 : ksDel (ks);
251 2 : }
252 :
253 2 : static void test_flag_value (void)
254 : {
255 2 : Key * k = keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL);
256 2 : keySetMeta (k, "opt/arg", "none");
257 2 : keySetMeta (k, "opt/flagvalue", "set");
258 2 : KeySet * ks = ksNew (1, k, KS_END);
259 :
260 2 : RUN_TEST (ks, ARGS ("-a"), NO_ENVP);
261 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "short flag with value failed");
262 2 : clearValues (ks);
263 :
264 2 : RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
265 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "short flag with value (with arg) failed");
266 2 : clearValues (ks);
267 :
268 : Key * errorKey;
269 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("-ashort"), NO_ENVP);
270 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Unknown short option: -s"),
271 : "short flag with value (with arg, combined) should have failed");
272 2 : clearValues (ks);
273 :
274 2 : RUN_TEST (ks, ARGS ("--apple"), NO_ENVP);
275 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "long flag with value failed");
276 2 : clearValues (ks);
277 :
278 2 : RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
279 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "long flag with value (with arg) failed");
280 2 : clearValues (ks);
281 :
282 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple=long"), NO_ENVP);
283 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot have an argument: --apple"),
284 : "long flag with value (with arg, combined) should have failed");
285 2 : clearValues (ks);
286 :
287 2 : ksDel (ks);
288 2 : }
289 :
290 2 : static void test_optional (void)
291 : {
292 2 : Key * k = keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL);
293 2 : keySetMeta (k, "opt/arg", "optional");
294 2 : KeySet * ks = ksNew (1, k, KS_END);
295 :
296 2 : RUN_TEST (ks, ARGS ("-a"), NO_ENVP);
297 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "short flag failed");
298 2 : clearValues (ks);
299 :
300 2 : RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
301 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "short flag (with arg) failed");
302 2 : clearValues (ks);
303 :
304 : Key * errorKey;
305 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("-ashort"), NO_ENVP);
306 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Unknown short option: -s"),
307 : "short flag (with arg, combined) should have failed");
308 2 : clearValues (ks);
309 :
310 2 : RUN_TEST (ks, ARGS ("--apple"), NO_ENVP);
311 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "long flag failed");
312 2 : clearValues (ks);
313 :
314 2 : RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
315 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "long flag (with arg) failed");
316 2 : clearValues (ks);
317 :
318 2 : RUN_TEST (ks, ARGS ("--apple=long"), NO_ENVP);
319 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
320 2 : clearValues (ks);
321 :
322 2 : ksDel (ks);
323 2 : }
324 :
325 2 : static void test_optional_value (void)
326 : {
327 2 : Key * k = keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL);
328 2 : keySetMeta (k, "opt/arg", "optional");
329 2 : keySetMeta (k, "opt/flagvalue", "set");
330 2 : KeySet * ks = ksNew (1, k, KS_END);
331 :
332 2 : RUN_TEST (ks, ARGS ("-a"), NO_ENVP);
333 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "short flag with value failed");
334 2 : clearValues (ks);
335 :
336 2 : RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
337 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "short flag with value (with arg) failed");
338 2 : clearValues (ks);
339 :
340 : Key * errorKey;
341 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("-ashort"), NO_ENVP);
342 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Unknown short option: -s"),
343 : "short flag with value (with arg, combined) should have failed");
344 2 : clearValues (ks);
345 :
346 2 : RUN_TEST (ks, ARGS ("--apple"), NO_ENVP);
347 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "long flag with value failed");
348 2 : clearValues (ks);
349 :
350 2 : RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
351 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "set"), "long flag with value (with arg) failed");
352 2 : clearValues (ks);
353 :
354 2 : RUN_TEST (ks, ARGS ("--apple=long"), NO_ENVP);
355 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
356 2 : clearValues (ks);
357 :
358 2 : ksDel (ks);
359 2 : }
360 :
361 2 : static void test_precedence (void)
362 : {
363 2 : KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", "APPLE"), KS_END);
364 :
365 2 : RUN_TEST (ks, ARGS ("--apple=long", "-ashort"), ENVP ("APPLE=env"));
366 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option didn't take precedence");
367 2 : clearValues (ks);
368 :
369 2 : RUN_TEST (ks, ARGS ("--apple=long"), ENVP ("APPLE=env"));
370 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option didn't take precedence");
371 2 : clearValues (ks);
372 :
373 2 : ksDel (ks);
374 2 : }
375 :
376 2 : static void test_repeated (void)
377 : {
378 2 : KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple/#", 'a', "apple", "APPLE"), KS_END);
379 :
380 2 : RUN_TEST (ks, ARGS ("-a", "short0", "-ashort1", "-a", "short2"), NO_ENVP);
381 2 : succeed_if (checkMeta (ks, PROC_BASE_KEY "/apple", "array", "#2"), "short repeated failed (wrong count)");
382 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#0", "short0"), "short repeated failed (#0)");
383 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#1", "short1"), "short repeated failed (#1)");
384 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#2", "short2"), "short repeated failed (#2)");
385 2 : clearValues (ks);
386 :
387 2 : RUN_TEST (ks, ARGS ("--apple", "long0", "--apple=long1", "--apple", "long2"), NO_ENVP);
388 2 : succeed_if (checkMeta (ks, PROC_BASE_KEY "/apple", "array", "#2"), "long repeated failed (wrong count)");
389 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#0", "long0"), "long repeated failed (#0)");
390 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#1", "long1"), "long repeated failed (#1)");
391 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#2", "long2"), "long repeated failed (#2)");
392 2 : clearValues (ks);
393 :
394 2 : RUN_TEST (ks, NO_ARGS, ENVP ("APPLE=env0" ENV_SEP "env1" ENV_SEP "env2"));
395 2 : succeed_if (checkMeta (ks, PROC_BASE_KEY "/apple", "array", "#2"), "env-var repeated failed (wrong count)");
396 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#0", "env0"), "env-var repeated failed (#0)");
397 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#1", "env1"), "env-var repeated failed (#1)");
398 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#2", "env2"), "env-var repeated failed (#2)");
399 2 : clearValues (ks);
400 :
401 2 : ksDel (ks);
402 2 : }
403 :
404 2 : static void test_multiple (void)
405 : {
406 2 : Key * k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
407 2 : keySetMeta (k, "opt", "#1");
408 2 : keySetMeta (k, "opt/#0", "a");
409 2 : keySetMeta (k, "opt/#0/long", "apple");
410 2 : keySetMeta (k, "opt/#1", "b");
411 2 : keySetMeta (k, "opt/#1/long", "banana");
412 2 : keySetMeta (k, "env", "#1");
413 2 : keySetMeta (k, "env/#0", "APPLE");
414 2 : keySetMeta (k, "env/#1", "BANANA");
415 2 : KeySet * ks = ksNew (1, k, KS_END);
416 :
417 2 : RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
418 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option failed");
419 2 : clearValues (ks);
420 :
421 2 : RUN_TEST (ks, ARGS ("-ashort"), NO_ENVP);
422 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option (combined) failed");
423 2 : clearValues (ks);
424 :
425 2 : RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
426 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option failed");
427 2 : clearValues (ks);
428 :
429 2 : RUN_TEST (ks, ARGS ("--apple=long"), NO_ENVP);
430 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
431 2 : clearValues (ks);
432 :
433 2 : RUN_TEST (ks, NO_ARGS, ENVP ("APPLE=env"));
434 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "env"), "env-var failed");
435 2 : clearValues (ks);
436 :
437 2 : RUN_TEST (ks, ARGS ("-b", "short"), NO_ENVP);
438 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option failed");
439 2 : clearValues (ks);
440 :
441 2 : RUN_TEST (ks, ARGS ("-bshort"), NO_ENVP);
442 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "short option (combined) failed");
443 2 : clearValues (ks);
444 :
445 2 : RUN_TEST (ks, ARGS ("--banana", "long"), NO_ENVP);
446 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option failed");
447 2 : clearValues (ks);
448 :
449 2 : RUN_TEST (ks, ARGS ("--banana=long"), NO_ENVP);
450 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "long option (combined) failed");
451 2 : clearValues (ks);
452 :
453 2 : RUN_TEST (ks, NO_ARGS, ENVP ("BANANA=env"));
454 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "env"), "env-var failed");
455 2 : clearValues (ks);
456 :
457 2 : ksDel (ks);
458 2 : }
459 :
460 2 : static void test_precedence_repeated (void)
461 : {
462 2 : KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple/#", 'a', "apple", "APPLE"), KS_END);
463 :
464 2 : RUN_TEST (ks, ARGS ("--apple=long1", "-a", "short0", "-a", "short1", "--apple", "long0", "--apple", "long2", "-ashort2"),
465 : ENVP ("APPLE=env0" ENV_SEP "env1" ENV_SEP "env2"));
466 2 : succeed_if (checkMeta (ks, PROC_BASE_KEY "/apple", "array", "#2"), "short repeated failed (wrong count), should take precedence");
467 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#0", "short0"), "short repeated failed (#0), should take precedence");
468 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#1", "short1"), "short repeated failed (#1), should take precedence");
469 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#2", "short2"), "short repeated failed (#2), should take precedence");
470 2 : clearValues (ks);
471 :
472 2 : RUN_TEST (ks, ARGS ("--apple", "long0", "--apple=long1", "--apple", "long2"), ENVP ("APPLE=env0" ENV_SEP "env1" ENV_SEP "env2"));
473 2 : succeed_if (checkMeta (ks, PROC_BASE_KEY "/apple", "array", "#2"), "long repeated failed (wrong count), should take precedence");
474 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#0", "long0"), "long repeated failed (#0), should take precedence");
475 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#1", "long1"), "long repeated failed (#1), should take precedence");
476 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple/#2", "long2"), "long repeated failed (#2), should take precedence");
477 2 : clearValues (ks);
478 :
479 2 : ksDel (ks);
480 2 : }
481 :
482 2 : static void test_illegal_spec (void)
483 : {
484 : // ---
485 : // illegal flagvalue
486 : // ---
487 :
488 2 : Key * k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
489 2 : keySetMeta (k, "opt", "a");
490 2 : keySetMeta (k, "opt/flagvalue", "set");
491 2 : KeySet * ks = ksNew (1, k, KS_END);
492 :
493 : Key * errorKey;
494 2 : RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
495 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
496 : "The flagvalue metadata can only be used, if the opt/arg metadata is set to 'none' or 'optional'. "
497 : "(key: " SPEC_BASE_KEY "/apple)"),
498 : "flagvalue should be illegal");
499 2 : clearValues (ks);
500 :
501 2 : ksDel (ks);
502 :
503 : // ---
504 : // duplicate option (short)
505 : // ---
506 :
507 2 : ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', NULL, NULL), keyWithOpt (SPEC_BASE_KEY "/banana", 'a', NULL, NULL), KS_END);
508 :
509 2 : RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
510 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
511 : "The option '-a' has already been specified for the key '" SPEC_BASE_KEY
512 : "/apple'. Additional key: " SPEC_BASE_KEY "/banana"),
513 : "duplicate short option should be illegal");
514 2 : clearValues (ks);
515 :
516 2 : ksDel (ks);
517 :
518 : // ---
519 : // duplicate option (long)
520 : // ---
521 :
522 2 : ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 0, "apple", NULL), keyWithOpt (SPEC_BASE_KEY "/banana", 0, "apple", NULL),
523 : KS_END);
524 :
525 2 : RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
526 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
527 : "The option '--apple' has already been specified for the key '" SPEC_BASE_KEY
528 : "/apple'. Additional key: " SPEC_BASE_KEY "/banana"),
529 : "duplicate long option should be illegal");
530 2 : clearValues (ks);
531 :
532 2 : ksDel (ks);
533 :
534 : // ---
535 : // args remaining not array
536 : // ---
537 :
538 2 : k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
539 2 : keySetMeta (k, "args", "remaining");
540 2 : ks = ksNew (1, k, KS_END);
541 :
542 2 : RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
543 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
544 : "'args=remaining' can only be set on array keys (basename = '#'). Offending key: " SPEC_BASE_KEY "/apple"),
545 : "non-array remaining args should be illegal");
546 2 : clearValues (ks);
547 :
548 2 : ksDel (ks);
549 :
550 : // ---
551 : // '-' option
552 : // ---
553 :
554 2 : k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
555 2 : keySetMeta (k, "opt", "-");
556 2 : ks = ksNew (1, k, KS_END);
557 :
558 2 : RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
559 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
560 : "Character '-' cannot be used as a short option. It would collide with the "
561 : "special string '--'. Offending key: " SPEC_BASE_KEY "/apple"),
562 : "'-' option should be illegal");
563 2 : clearValues (ks);
564 :
565 2 : ksDel (ks);
566 :
567 : // ---
568 : // 'h' option
569 : // ---
570 :
571 2 : k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
572 2 : keySetMeta (k, "opt", "h");
573 2 : ks = ksNew (1, k, KS_END);
574 :
575 2 : RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
576 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
577 : "Character 'h' cannot be used as a short option. It would collide with the "
578 : "help option '-h'. Offending key: " SPEC_BASE_KEY "/apple"),
579 : "'h' option should be illegal");
580 2 : clearValues (ks);
581 :
582 2 : ksDel (ks);
583 :
584 : // ---
585 : // 'help' option
586 : // ---
587 :
588 2 : k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
589 2 : keySetMeta (k, "opt/long", "help");
590 2 : ks = ksNew (1, k, KS_END);
591 :
592 2 : RUN_TEST_ERROR (ks, errorKey, NO_ARGS, NO_ENVP);
593 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
594 : "Option 'help' cannot be used as a long option. It would collide with the "
595 : "help option '--help'. Offending key: " SPEC_BASE_KEY "/apple"),
596 : "'help' option should be illegal");
597 2 : clearValues (ks);
598 :
599 2 : ksDel (ks);
600 2 : }
601 :
602 2 : static void test_illegal_use (void)
603 : {
604 : // ---
605 : // illegal repeat
606 : // ---
607 :
608 2 : KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL), KS_END);
609 :
610 : Key * errorKey;
611 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("-ashort0", "-ashort1"), NO_ENVP);
612 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot be repeated: -a"),
613 : "repeat should be illegal (short)");
614 2 : clearValues (ks);
615 :
616 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple", "long0", "--apple", "long1"), NO_ENVP);
617 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot be repeated: --apple"),
618 : "repeat should be illegal (long)");
619 2 : clearValues (ks);
620 :
621 2 : ksDel (ks);
622 :
623 : // ---
624 : // missing argument
625 : // ---
626 :
627 2 : ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", NULL), KS_END);
628 :
629 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("-a"), NO_ENVP);
630 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Missing argument for short option: -a"),
631 : "missing argument (short) failed");
632 2 : clearValues (ks);
633 :
634 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple"), NO_ENVP);
635 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Missing argument for long option: --apple"),
636 : "missing argument (long) failed");
637 2 : clearValues (ks);
638 :
639 2 : ksDel (ks);
640 :
641 : // ---
642 : // argument not allowed
643 : // ---
644 :
645 2 : Key * k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
646 2 : keySetMeta (k, "opt", "a");
647 2 : keySetMeta (k, "opt/long", "apple");
648 2 : keySetMeta (k, "opt/arg", "none");
649 2 : ks = ksNew (1, k, KS_END);
650 :
651 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple=short"), NO_ENVP);
652 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot have an argument: --apple"),
653 : "argument should not be allowed");
654 2 : clearValues (ks);
655 :
656 2 : ksDel (ks);
657 :
658 : // ---
659 : // multiple repeated
660 : // ---
661 :
662 2 : k = keyNew (SPEC_BASE_KEY "/apple/#", KEY_END);
663 2 : keySetMeta (k, "opt", "#1");
664 2 : keySetMeta (k, "opt/#0", "a");
665 2 : keySetMeta (k, "opt/#0/long", "apple");
666 2 : keySetMeta (k, "opt/#1", "b");
667 2 : keySetMeta (k, "opt/#1/long", "banana");
668 2 : keySetMeta (k, "env", "#1");
669 2 : keySetMeta (k, "env/#0", "APPLE");
670 2 : keySetMeta (k, "env/#1", "BANANA");
671 2 : ks = ksNew (1, k, KS_END);
672 :
673 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("-a", "short0", "-ashort1", "-a", "short2", "-b", "short3", "-bshort4"), NO_ENVP);
674 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
675 : "The option '-b' cannot be used, because another option has already been used for the key "
676 : "'" SPEC_BASE_KEY "/apple/#'"),
677 : "multiple repeated short options should have failed");
678 2 : clearValues (ks);
679 :
680 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("--apple", "long0", "--apple=long1", "--apple", "long2", "--banana=long3", "--banana", "long4"),
681 : NO_ENVP);
682 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
683 : "The option '--banana' cannot be used, because another option has already been used for the key "
684 : "'" SPEC_BASE_KEY "/apple/#'"),
685 : "multiple repeated long options should have failed");
686 2 : clearValues (ks);
687 :
688 2 : RUN_TEST_ERROR (ks, errorKey, NO_ARGS, ENVP ("APPLE=env0" ENV_SEP "env1" ENV_SEP "env2", "BANANA=env3" ENV_SEP "env4"));
689 2 : succeed_if (
690 : checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC,
691 : "The environment variable 'BANANA' cannot be used, because another variable has already been used for the key "
692 : "'" SPEC_BASE_KEY "/apple/#'."),
693 : "multiple repeated env-vars should have failed");
694 2 : clearValues (ks);
695 :
696 2 : ksDel (ks);
697 2 : }
698 :
699 2 : static void test_help (void)
700 : {
701 : // ---
702 : // no options
703 : // ---
704 :
705 2 : KeySet * ks = ksNew (0, KS_END);
706 :
707 2 : Key * errorKey = keyNew (SPEC_BASE_KEY, KEY_END);
708 :
709 2 : succeed_if (elektraGetOpts (ks, ARGS ("-h"), NO_ENVP, errorKey) == 1, "help not generated");
710 2 : checkHelpMessage (errorKey, "Usage: prog\n");
711 2 : succeed_if (elektraGetOpts (ks, ARGS ("-h", "short"), NO_ENVP, errorKey) == 1, "help not generated");
712 2 : checkHelpMessage (errorKey, "Usage: prog\n");
713 2 : succeed_if (elektraGetOpts (ks, ARGS ("--help"), NO_ENVP, errorKey) == 1, "help not generated");
714 2 : checkHelpMessage (errorKey, "Usage: prog\n");
715 2 : succeed_if (elektraGetOpts (ks, ARGS ("--help", "long"), NO_ENVP, errorKey) == 1, "help not generated");
716 2 : checkHelpMessage (errorKey, "Usage: prog\n");
717 :
718 2 : keyDel (errorKey);
719 :
720 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("-hshort"), NO_ENVP);
721 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "Unknown short option: -s"),
722 : "short help with value (with arg, combined) should have failed");
723 2 : clearValues (ks);
724 :
725 2 : RUN_TEST_ERROR (ks, errorKey, ARGS ("--help=long"), NO_ENVP);
726 2 : succeed_if (checkError (errorKey, ELEKTRA_ERROR_VALIDATION_SEMANTIC, "This option cannot have an argument: --help"),
727 : "long help with value (with arg, combined) should have failed");
728 2 : clearValues (ks);
729 :
730 2 : ksDel (ks);
731 :
732 : // ---
733 : // with options
734 : // ---
735 :
736 2 : const char * expectedHelp =
737 : "Usage: prog [OPTION]... [ARG]...\n"
738 : "OPTIONS\n"
739 : " -a, -b BANANA, -C, --apple, --banana=BANANA, --cherry=[ARG]\n"
740 : " Apple/Banana/Cherry description\n"
741 : " -p ARG A pear is not an apple, nor a banana, nor a cherry.\n";
742 :
743 2 : Key * k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
744 2 : keySetMeta (k, "opt", "#3");
745 2 : keySetMeta (k, "opt/#0", "a");
746 2 : keySetMeta (k, "opt/#0/long", "apple");
747 2 : keySetMeta (k, "opt/#0/arg", "none");
748 2 : keySetMeta (k, "opt/#1", "b");
749 2 : keySetMeta (k, "opt/#1/long", "banana");
750 2 : keySetMeta (k, "opt/#1/arg/help", "BANANA");
751 2 : keySetMeta (k, "opt/#2", "C");
752 2 : keySetMeta (k, "opt/#2/long", "cherry");
753 2 : keySetMeta (k, "opt/#2/arg", "optional");
754 2 : keySetMeta (k, "opt/#3", "d");
755 2 : keySetMeta (k, "opt/#3/hidden", "1");
756 2 : keySetMeta (k, "description", "Apple/Banana/Cherry description");
757 2 : ks = ksNew (4, k,
758 : keyNew (SPEC_BASE_KEY "/pear", KEY_META, "opt", "p", KEY_META, "description",
759 : "A pear is not an apple, nor a banana, nor a cherry.", KEY_END),
760 : keyNew (SPEC_BASE_KEY "/args/#", KEY_META, "args", "remaining", KEY_END),
761 : keyNew (SPEC_BASE_KEY "/none", KEY_META, "opt", "n", KEY_META, "opt/hidden", "1", KEY_END), KS_END);
762 2 : errorKey = keyNew (SPEC_BASE_KEY, KEY_END);
763 :
764 2 : succeed_if (elektraGetOpts (ks, ARGS ("-h"), NO_ENVP, errorKey) == 1, "help not generated");
765 2 : checkHelpMessage (errorKey, expectedHelp);
766 2 : succeed_if (elektraGetOpts (ks, ARGS ("-h", "short"), NO_ENVP, errorKey) == 1, "help not generated");
767 2 : checkHelpMessage (errorKey, expectedHelp);
768 2 : succeed_if (elektraGetOpts (ks, ARGS ("--help"), NO_ENVP, errorKey) == 1, "help not generated");
769 2 : checkHelpMessage (errorKey, expectedHelp);
770 2 : succeed_if (elektraGetOpts (ks, ARGS ("--help", "long"), NO_ENVP, errorKey) == 1, "help not generated");
771 2 : checkHelpMessage (errorKey, expectedHelp);
772 :
773 2 : keyDel (errorKey);
774 :
775 2 : ksDel (ks);
776 2 : }
777 :
778 2 : static void test_stop (void)
779 : {
780 2 : KeySet * ks = ksNew (1, keyWithOpt (SPEC_BASE_KEY "/apple", 'a', "apple", "APPLE"),
781 : keyNew (SPEC_BASE_KEY "/rest/#", KEY_META, "args", "remaining", KEY_END), KS_END);
782 :
783 2 : RUN_TEST (ks, ARGS ("--", "-a", "short"), NO_ENVP);
784 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", NULL), "should have stopped");
785 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest", "#1"), "rest has wrong count");
786 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#0", "-a"), "rest has wrong value (#0)");
787 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#1", "short"), "rest has wrong value (#1)");
788 2 : clearValues (ks);
789 :
790 2 : RUN_TEST (ks, ARGS ("-ashort", "--", "-a", "short2"), NO_ENVP);
791 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "should have stopped after short option");
792 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest", "#1"), "rest has wrong count");
793 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#0", "-a"), "rest has wrong value (#0)");
794 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#1", "short2"), "rest has wrong value (#1)");
795 2 : clearValues (ks);
796 :
797 2 : RUN_TEST (ks, ARGS ("--apple", "long", "--", "-a", "short2"), NO_ENVP);
798 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "hould have stopped after long option");
799 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest", "#1"), "rest has wrong count");
800 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#0", "-a"), "rest has wrong value (#0)");
801 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#1", "short2"), "rest has wrong value (#1)");
802 2 : clearValues (ks);
803 :
804 2 : RUN_TEST (ks, ARGS ("--"), ENVP ("APPLE=env"));
805 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "env"), "env-var failed (stopped options)");
806 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest", "#"), "rest has wrong count");
807 2 : clearValues (ks);
808 :
809 :
810 2 : Key * errorKey = keyNew ("spec/tests/opts", KEY_META, "posixly", "1", KEY_END);
811 2 : if (elektraGetOpts (ks, ARGS ("-ashort", "other", "-a", "short2"), NO_ENVP, errorKey) != 0)
812 : {
813 0 : yield_error ("error found");
814 0 : output_error (errorKey);
815 : }
816 2 : keyDel (errorKey);
817 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "should have stopped after short option");
818 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest", "#2"), "rest has wrong count");
819 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#0", "other"), "rest has wrong value (#0)");
820 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#1", "-a"), "rest has wrong value (#1)");
821 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/rest/#2", "short2"), "rest has wrong value (#2)");
822 2 : clearValues (ks);
823 :
824 2 : ksDel (ks);
825 2 : }
826 :
827 2 : static void test_mixed_config (void)
828 : {
829 2 : Key * k = keyNew (SPEC_BASE_KEY "/apple", KEY_END);
830 2 : keySetMeta (k, "opt", "#1");
831 2 : keySetMeta (k, "opt/#0", "a");
832 2 : keySetMeta (k, "opt/#0/long", "apple");
833 2 : keySetMeta (k, "opt/#0/arg", "none");
834 2 : keySetMeta (k, "opt/#1", "b");
835 2 : keySetMeta (k, "opt/#1/long", "banana");
836 2 : KeySet * ks = ksNew (1, k, KS_END);
837 :
838 2 : RUN_TEST (ks, ARGS ("-a", "short"), NO_ENVP);
839 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "mixed config failed");
840 2 : clearValues (ks);
841 :
842 2 : RUN_TEST (ks, ARGS ("--apple", "long"), NO_ENVP);
843 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "1"), "mixed config failed");
844 2 : clearValues (ks);
845 :
846 2 : RUN_TEST (ks, ARGS ("-b", "short"), NO_ENVP);
847 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "mixed config failed");
848 2 : clearValues (ks);
849 :
850 2 : RUN_TEST (ks, ARGS ("-bshort"), NO_ENVP);
851 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "short"), "mixed config failed");
852 2 : clearValues (ks);
853 :
854 2 : RUN_TEST (ks, ARGS ("--banana", "long"), NO_ENVP);
855 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "mixed config failed");
856 2 : clearValues (ks);
857 :
858 2 : RUN_TEST (ks, ARGS ("--banana=long"), NO_ENVP);
859 2 : succeed_if (checkValue (ks, PROC_BASE_KEY "/apple", "long"), "mixed config failed");
860 2 : clearValues (ks);
861 :
862 2 : ksDel (ks);
863 2 : }
864 :
865 2 : int main (int argc, char ** argv)
866 : {
867 2 : printf (" OPTS TESTS\n");
868 2 : printf ("==================\n\n");
869 :
870 2 : init (argc, argv);
871 :
872 2 : test_simple ();
873 2 : test_short_only ();
874 2 : test_long_only ();
875 2 : test_env_only ();
876 2 : test_flag ();
877 2 : test_flag_value ();
878 2 : test_optional ();
879 2 : test_optional_value ();
880 2 : test_precedence ();
881 2 : test_repeated ();
882 2 : test_multiple ();
883 2 : test_precedence_repeated ();
884 2 : test_illegal_spec ();
885 2 : test_illegal_use ();
886 2 : test_help ();
887 2 : test_stop ();
888 2 : test_mixed_config ();
889 :
890 2 : print_result ("test_opts");
891 :
892 2 : return nbError;
893 : }
|