xref: /minix3/external/bsd/kyua-testers/dist/cli_test.c (revision 11be35a165022172ed3cea20f2b5df0307540b0e)
1 // Copyright 2012 Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 //   notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 //   notice, this list of conditions and the following disclaimer in the
12 //   documentation and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors
14 //   may be used to endorse or promote products derived from this software
15 //   without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #include "cli.h"
30 
31 #include <assert.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 
36 #include <atf-c.h>
37 
38 #include "defs.h"
39 #include "error.h"
40 #include "run.h"
41 
42 
43 /// Dumps the contents of a run_params object to stdout.
44 ///
45 /// We only print the settings that are relevant for testing purposes.
46 ///
47 /// \param run_params The run parameters to be printed.
48 static void
dump_run_params(const kyua_run_params_t * run_params)49 dump_run_params(const kyua_run_params_t* run_params)
50 {
51     printf("timeout_seconds: %lu\n", run_params->timeout_seconds);
52 
53     if (run_params->unprivileged_user == getuid())
54         printf("unprivileged_user: self\n");
55     else
56         printf("unprivileged_user: %ld\n", (long)run_params->unprivileged_user);
57 
58     if (run_params->unprivileged_group == getgid())
59         printf("unprivileged_group: self\n");
60     else
61         printf("unprivileged_group: %ld\n",
62                (long)run_params->unprivileged_group);
63 }
64 
65 
66 /// Helper to validate argument passing to the list_test_cases method.
67 ///
68 /// This prints the value of all arguments to stdout so that the caller can
69 /// compare the printed output to the expected values.
70 ///
71 /// \param test_program Test program path.
72 /// \param run_params Execution parameters to configure the test process.
73 ///
74 /// \return An error if the test_program is set to the magic keyword 'error'; OK
75 /// otherwise.
76 static kyua_error_t
list_test_cases(const char * test_program,const kyua_run_params_t * run_params)77 list_test_cases(const char* test_program, const kyua_run_params_t* run_params)
78 {
79     if (strcmp(test_program, "error") == 0)
80         return kyua_oom_error_new();
81     else {
82         printf("test_program: %s\n", test_program);
83         dump_run_params(run_params);
84         return kyua_error_ok();
85     }
86 }
87 
88 
89 /// Helper to validate argument passing to the run_test_cases method.
90 ///
91 /// This prints the value of all arguments to stdout so that the caller can
92 /// compare the printed output to the expected values.
93 ///
94 /// \param test_program Test program path.
95 /// \param test_case Test case name.
96 /// \param result_file Path to the result file.
97 /// \param user_variables User configuration variables.
98 /// \param run_params Execution parameters to configure the test process.
99 /// \param [out] success Whether the test case returned with a successful result
100 ///     or not.  Set to true if result_file is the magic word 'pass'.
101 ///
102 /// \return An error if the test_program is set to the magic keyword 'error'; OK
103 /// otherwise.
104 static kyua_error_t
run_test_case(const char * test_program,const char * test_case,const char * result_file,const char * const user_variables[],const kyua_run_params_t * run_params,bool * success)105 run_test_case(const char* test_program, const char* test_case,
106               const char* result_file, const char* const user_variables[],
107               const kyua_run_params_t* run_params, bool* success)
108 {
109     if (strcmp(test_program, "error") == 0)
110         return kyua_oom_error_new();
111     else {
112         printf("test_program: %s\n", test_program);
113         printf("test_case: %s\n", test_case);
114         printf("result_file: %s\n", result_file);
115         const char* const* iter;
116         for (iter = user_variables; *iter != NULL; ++iter)
117             printf("variable: %s\n", *iter);
118         dump_run_params(run_params);
119         *success = strcmp(result_file, "pass") == 0;
120         return kyua_error_ok();
121     }
122 }
123 
124 
125 /// Definition of a mock tester.
126 static kyua_cli_tester_t mock_tester = {
127     .list_test_cases = list_test_cases,
128     .run_test_case = run_test_case,
129 };
130 
131 
132 /// Definition of a tester with invalid values.
133 ///
134 /// This is to be used when the called code is not supposed to invoke any of the
135 /// tester methods.
136 static kyua_cli_tester_t unused_tester = {
137     .list_test_cases = NULL,
138     .run_test_case = NULL,
139 };
140 
141 
142 /// Counts the number of arguments in an argv vector.
143 ///
144 /// \param argv The NULL-terminated arguments vector to be passed to the
145 ///     kyua_cli_main function.
146 ///
147 /// \return The number of arguments in argv.
148 static int
count_argv(char * const * const argv)149 count_argv(char* const* const argv)
150 {
151     int argc = 0;
152     char* const* arg;
153     for (arg = argv; *arg != NULL; arg++)
154         argc++;
155     return argc;
156 }
157 
158 
159 ATF_TC_WITHOUT_HEAD(main__unknown_option);
ATF_TC_BODY(main__unknown_option,tc)160 ATF_TC_BODY(main__unknown_option, tc)
161 {
162     const pid_t pid = atf_utils_fork();
163     if (pid == 0) {
164         char arg0[] = "unused-progname";
165         char arg1[] = "-Z";
166         char* const argv[] = {arg0, arg1, NULL};
167         exit(kyua_cli_main(count_argv(argv), argv, &unused_tester));
168     }
169     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Unknown option -Z\n");
170 }
171 
172 
173 ATF_TC_WITHOUT_HEAD(main__missing_option_argument);
ATF_TC_BODY(main__missing_option_argument,tc)174 ATF_TC_BODY(main__missing_option_argument, tc)
175 {
176     const pid_t pid = atf_utils_fork();
177     if (pid == 0) {
178         char arg0[] = "unused-progname";
179         char arg1[] = "-t";
180         char* const argv[] = {arg0, arg1, NULL};
181         exit(kyua_cli_main(count_argv(argv), argv, &unused_tester));
182     }
183     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: -t requires an "
184                    "argument\n");
185 }
186 
187 
188 ATF_TC_WITHOUT_HEAD(main__unknown_command);
ATF_TC_BODY(main__unknown_command,tc)189 ATF_TC_BODY(main__unknown_command, tc)
190 {
191     const pid_t pid = atf_utils_fork();
192     if (pid == 0) {
193         char arg0[] = "unused-progname";
194         char arg1[] = "foobar";
195         char* const argv[] = {arg0, arg1, NULL};
196         exit(kyua_cli_main(count_argv(argv), argv, &unused_tester));
197     }
198     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Unknown command "
199                    "'foobar'\n");
200 }
201 
202 
203 ATF_TC_WITHOUT_HEAD(main__missing_command);
ATF_TC_BODY(main__missing_command,tc)204 ATF_TC_BODY(main__missing_command, tc)
205 {
206     const pid_t pid = atf_utils_fork();
207     if (pid == 0) {
208         char arg0[] = "unused-progname";
209         char* const argv[] = {arg0, NULL};
210         exit(kyua_cli_main(count_argv(argv), argv, &unused_tester));
211     }
212     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Must provide a "
213                    "command\n");
214 }
215 
216 
217 /// Checks that a textual argument to a numerical flag raises an error.
218 ///
219 /// \param flag The generic flag to test.
220 /// \param error_message The expected error message when the flag is invalid.
221 static void
check_flag_not_a_number(const char flag,const char * error_message)222 check_flag_not_a_number(const char flag, const char *error_message)
223 {
224     const pid_t pid = atf_utils_fork();
225     if (pid == 0) {
226         char arg0[] = "unused-progname";
227         char arg1[] = "-?foo";
228         arg1[1] = flag;
229         char* const argv[] = {arg0, arg1, NULL};
230         exit(kyua_cli_main(count_argv(argv), argv, &unused_tester));
231     }
232     char experr[256];
233     snprintf(experr, sizeof(experr), "cli_test: %s 'foo' (not a number)\n",
234              error_message);
235     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", experr);
236 }
237 
238 
239 /// Checks that an out of range value to a numerical flag raises an error.
240 ///
241 /// \param flag The generic flag to test.
242 /// \param error_message The expected error message when the flag is invalid.
243 static void
check_flag_out_of_range(const char flag,const char * error_message)244 check_flag_out_of_range(const char flag, const char *error_message)
245 {
246     const pid_t pid = atf_utils_fork();
247     if (pid == 0) {
248         char arg0[] = "unused-progname";
249         char arg1[] = "-?99999999999999999999";
250         arg1[1] = flag;
251         char* const argv[] = {arg0, arg1, NULL};
252         exit(kyua_cli_main(count_argv(argv), argv, &unused_tester));
253     }
254     char experr[256];
255     snprintf(experr, sizeof(experr), "cli_test: %s '99999999999999999999' "
256              "(out of range)\n", error_message);
257     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", experr);
258 }
259 
260 
261 ATF_TC_WITHOUT_HEAD(main__gflag__not_a_number);
ATF_TC_BODY(main__gflag__not_a_number,tc)262 ATF_TC_BODY(main__gflag__not_a_number, tc)
263 {
264     check_flag_not_a_number('g', "Invalid GID");
265 }
266 
267 
268 ATF_TC_WITHOUT_HEAD(main__gflag__out_of_range);
ATF_TC_BODY(main__gflag__out_of_range,tc)269 ATF_TC_BODY(main__gflag__out_of_range, tc)
270 {
271     check_flag_out_of_range('g', "Invalid GID");
272 }
273 
274 
275 ATF_TC_WITHOUT_HEAD(main__tflag__not_a_number);
ATF_TC_BODY(main__tflag__not_a_number,tc)276 ATF_TC_BODY(main__tflag__not_a_number, tc)
277 {
278     check_flag_not_a_number('t', "Invalid timeout value");
279 }
280 
281 
282 ATF_TC_WITHOUT_HEAD(main__tflag__out_of_range);
ATF_TC_BODY(main__tflag__out_of_range,tc)283 ATF_TC_BODY(main__tflag__out_of_range, tc)
284 {
285     check_flag_out_of_range('t', "Invalid timeout value");
286 }
287 
288 
289 ATF_TC_WITHOUT_HEAD(main__uflag__not_a_number);
ATF_TC_BODY(main__uflag__not_a_number,tc)290 ATF_TC_BODY(main__uflag__not_a_number, tc)
291 {
292     check_flag_not_a_number('u', "Invalid UID");
293 }
294 
295 
296 ATF_TC_WITHOUT_HEAD(main__uflag__out_of_range);
ATF_TC_BODY(main__uflag__out_of_range,tc)297 ATF_TC_BODY(main__uflag__out_of_range, tc)
298 {
299     check_flag_out_of_range('u', "Invalid UID");
300 }
301 
302 
303 ATF_TC_WITHOUT_HEAD(list__ok);
ATF_TC_BODY(list__ok,tc)304 ATF_TC_BODY(list__ok, tc)
305 {
306     const pid_t pid = atf_utils_fork();
307     if (pid == 0) {
308         char arg0[] = "unused-progname";
309         char arg1[] = "list";
310         char arg2[] = "the-program";
311         char* const argv[] = {arg0, arg1, arg2, NULL};
312         exit(kyua_cli_main(count_argv(argv), argv, &mock_tester));
313     }
314     atf_utils_wait(pid, EXIT_SUCCESS,
315                    "test_program: the-program\n"
316                    "timeout_seconds: 60\n"
317                    "unprivileged_user: self\n"
318                    "unprivileged_group: self\n",
319                    "");
320 }
321 
322 
323 ATF_TC_WITHOUT_HEAD(list__custom_run_params);
ATF_TC_BODY(list__custom_run_params,tc)324 ATF_TC_BODY(list__custom_run_params, tc)
325 {
326     const pid_t pid = atf_utils_fork();
327     if (pid == 0) {
328         char arg0[] = "unused-progname";
329         char arg1[] = "-g987";
330         char arg2[] = "-t123";
331         char arg3[] = "-u45";
332         char arg4[] = "list";
333         char arg5[] = "the-program";
334         char* const argv[] = {arg0, arg1, arg2, arg3, arg4, arg5, NULL};
335         exit(kyua_cli_main(count_argv(argv), argv, &mock_tester));
336     }
337     atf_utils_wait(pid, EXIT_SUCCESS,
338                    "test_program: the-program\n"
339                    "timeout_seconds: 123\n"
340                    "unprivileged_user: 45\n"
341                    "unprivileged_group: 987\n",
342                    "");
343 }
344 
345 
346 ATF_TC_WITHOUT_HEAD(list__error);
ATF_TC_BODY(list__error,tc)347 ATF_TC_BODY(list__error, tc)
348 {
349     const pid_t pid = atf_utils_fork();
350     if (pid == 0) {
351         char arg0[] = "unused-progname";
352         char arg1[] = "list";
353         char arg2[] = "error";
354         char* const argv[] = {arg0, arg1, arg2, NULL};
355         exit(kyua_cli_main(count_argv(argv), argv, &mock_tester));
356     }
357     atf_utils_wait(pid, EXIT_INTERNAL_ERROR, "", "cli_test: Not enough "
358                    "memory\n");
359 }
360 
361 
362 ATF_TC_WITHOUT_HEAD(list__missing_arguments);
ATF_TC_BODY(list__missing_arguments,tc)363 ATF_TC_BODY(list__missing_arguments, tc)
364 {
365     const pid_t pid = atf_utils_fork();
366     if (pid == 0) {
367         char arg0[] = "unused-progname";
368         char arg1[] = "list";
369         char* const argv[] = {arg0, arg1, NULL};
370         exit(kyua_cli_main(count_argv(argv), argv, &unused_tester));
371     }
372     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: No test program "
373                    "provided\n");
374 }
375 
376 
377 ATF_TC_WITHOUT_HEAD(list__too_many_arguments);
ATF_TC_BODY(list__too_many_arguments,tc)378 ATF_TC_BODY(list__too_many_arguments, tc)
379 {
380     const pid_t pid = atf_utils_fork();
381     if (pid == 0) {
382         char arg0[] = "unused-progname";
383         char arg1[] = "list";
384         char arg2[] = "first";
385         char arg3[] = "second";
386         char* const argv[] = {arg0, arg1, arg2, arg3, NULL};
387         exit(kyua_cli_main(count_argv(argv), argv, &unused_tester));
388     }
389     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Only one test program "
390                    "allowed\n");
391 }
392 
393 
394 ATF_TC_WITHOUT_HEAD(test__ok__pass);
ATF_TC_BODY(test__ok__pass,tc)395 ATF_TC_BODY(test__ok__pass, tc)
396 {
397     const pid_t pid = atf_utils_fork();
398     if (pid == 0) {
399         char arg0[] = "unused-progname";
400         char arg1[] = "test";
401         char arg2[] = "the-program";
402         char arg3[] = "the-test-case";
403         char arg4[] = "pass";
404         char* const argv[] = {arg0, arg1, arg2, arg3, arg4, NULL};
405         exit(kyua_cli_main(count_argv(argv), argv, &mock_tester));
406     }
407     atf_utils_wait(pid, EXIT_SUCCESS,
408                    "test_program: the-program\n"
409                    "test_case: the-test-case\n"
410                    "result_file: pass\n"
411                    "timeout_seconds: 60\n"
412                    "unprivileged_user: self\n"
413                    "unprivileged_group: self\n",
414                    "");
415 }
416 
417 
418 ATF_TC_WITHOUT_HEAD(test__ok__fail);
ATF_TC_BODY(test__ok__fail,tc)419 ATF_TC_BODY(test__ok__fail, tc)
420 {
421     const pid_t pid = atf_utils_fork();
422     if (pid == 0) {
423         char arg0[] = "unused-progname";
424         char arg1[] = "test";
425         char arg2[] = "the-program";
426         char arg3[] = "the-test-case";
427         char arg4[] = "fail";
428         char* const argv[] = {arg0, arg1, arg2, arg3, arg4, NULL};
429         exit(kyua_cli_main(count_argv(argv), argv, &mock_tester));
430     }
431     atf_utils_wait(pid, EXIT_FAILURE,
432                    "test_program: the-program\n"
433                    "test_case: the-test-case\n"
434                    "result_file: fail\n"
435                    "timeout_seconds: 60\n"
436                    "unprivileged_user: self\n"
437                    "unprivileged_group: self\n",
438                    "");
439 }
440 
441 
442 ATF_TC_WITHOUT_HEAD(test__custom_run_params);
ATF_TC_BODY(test__custom_run_params,tc)443 ATF_TC_BODY(test__custom_run_params, tc)
444 {
445     const pid_t pid = atf_utils_fork();
446     if (pid == 0) {
447         char arg0[] = "unused-progname";
448         char arg1[] = "-g987";
449         char arg2[] = "-t123";
450         char arg3[] = "-u45";
451         char arg4[] = "test";
452         char arg5[] = "the-program";
453         char arg6[] = "the-test-case";
454         char arg7[] = "pass";
455         char* const argv[] = {arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
456                               NULL};
457         exit(kyua_cli_main(count_argv(argv), argv, &mock_tester));
458     }
459     atf_utils_wait(pid, EXIT_SUCCESS,
460                    "test_program: the-program\n"
461                    "test_case: the-test-case\n"
462                    "result_file: pass\n"
463                    "timeout_seconds: 123\n"
464                    "unprivileged_user: 45\n"
465                    "unprivileged_group: 987\n",
466                    "");
467 }
468 
469 
470 ATF_TC_WITHOUT_HEAD(test__config_variables);
ATF_TC_BODY(test__config_variables,tc)471 ATF_TC_BODY(test__config_variables, tc)
472 {
473     const pid_t pid = atf_utils_fork();
474     if (pid == 0) {
475         char arg0[] = "unused-progname";
476         char arg1[] = "test";
477         char arg2[] = "-vfoo=bar";
478         char arg3[] = "-va=c";
479         char arg4[] = "the-program";
480         char arg5[] = "the-test-case";
481         char arg6[] = "pass";
482         char* const argv[] = {arg0, arg1, arg2, arg3, arg4, arg5, arg6, NULL};
483         exit(kyua_cli_main(count_argv(argv), argv, &mock_tester));
484     }
485     atf_utils_wait(pid, EXIT_SUCCESS,
486                    "test_program: the-program\n"
487                    "test_case: the-test-case\n"
488                    "result_file: pass\n"
489                    "variable: foo=bar\n"
490                    "variable: a=c\n"
491                    "timeout_seconds: 60\n"
492                    "unprivileged_user: self\n"
493                    "unprivileged_group: self\n",
494                    "");
495 }
496 
497 
498 ATF_TC_WITHOUT_HEAD(test__error);
ATF_TC_BODY(test__error,tc)499 ATF_TC_BODY(test__error, tc)
500 {
501     const pid_t pid = atf_utils_fork();
502     if (pid == 0) {
503         char arg0[] = "unused-progname";
504         char arg1[] = "test";
505         char arg2[] = "error";
506         char* const argv[] = {arg0, arg1, arg2, arg2, arg2, NULL};
507         exit(kyua_cli_main(count_argv(argv), argv, &mock_tester));
508     }
509     atf_utils_wait(pid, EXIT_INTERNAL_ERROR, "", "cli_test: Not enough "
510                    "memory\n");
511 }
512 
513 
514 /// Checks that the test command validates the right number of arguments.
515 ///
516 /// \param count Number of arguments to pass to the test command.
517 static void
check_test_invalid_arguments(const unsigned int count)518 check_test_invalid_arguments(const unsigned int count)
519 {
520     printf("Checking with %d arguments\n", count);
521     const pid_t pid = atf_utils_fork();
522     if (pid == 0) {
523         char arg0[] = "unused-progname";
524         char arg1[] = "test";
525         char argX[] = "arg";
526         assert(count <= 4);
527         char* argv[] = {arg0, arg1, argX, argX, argX, argX, NULL};
528         argv[2 + count] = NULL;
529         exit(kyua_cli_main(2 + count, argv, &unused_tester));
530     }
531     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Must provide a test "
532                    "program, a test case name and a result file\n");
533 }
534 
535 
536 ATF_TC_WITHOUT_HEAD(test__invalid_arguments);
ATF_TC_BODY(test__invalid_arguments,tc)537 ATF_TC_BODY(test__invalid_arguments, tc)
538 {
539     check_test_invalid_arguments(0);
540     check_test_invalid_arguments(1);
541     check_test_invalid_arguments(2);
542     check_test_invalid_arguments(4);
543 }
544 
545 
546 ATF_TC_WITHOUT_HEAD(test__unknown_option);
ATF_TC_BODY(test__unknown_option,tc)547 ATF_TC_BODY(test__unknown_option, tc)
548 {
549     const pid_t pid = atf_utils_fork();
550     if (pid == 0) {
551         char arg0[] = "unused-progname";
552         char arg1[] = "test";
553         char arg2[] = "-Z";
554         char* const argv[] = {arg0, arg1, arg2, NULL};
555         exit(kyua_cli_main(count_argv(argv), argv, &unused_tester));
556     }
557     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Unknown test option "
558                    "-Z\n");
559 }
560 
561 
562 ATF_TC_WITHOUT_HEAD(test__missing_option_argument);
ATF_TC_BODY(test__missing_option_argument,tc)563 ATF_TC_BODY(test__missing_option_argument, tc)
564 {
565     const pid_t pid = atf_utils_fork();
566     if (pid == 0) {
567         char arg0[] = "unused-progname";
568         char arg1[] = "test";
569         char arg2[] = "-v";
570         char* const argv[] = {arg0, arg1, arg2, NULL};
571         exit(kyua_cli_main(count_argv(argv), argv, &unused_tester));
572     }
573     atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: test's -v requires an "
574                    "argument\n");
575 }
576 
577 
ATF_TP_ADD_TCS(tp)578 ATF_TP_ADD_TCS(tp)
579 {
580     ATF_TP_ADD_TC(tp, main__unknown_option);
581     ATF_TP_ADD_TC(tp, main__missing_option_argument);
582     ATF_TP_ADD_TC(tp, main__unknown_command);
583     ATF_TP_ADD_TC(tp, main__missing_command);
584     ATF_TP_ADD_TC(tp, main__gflag__not_a_number);
585     ATF_TP_ADD_TC(tp, main__gflag__out_of_range);
586     ATF_TP_ADD_TC(tp, main__tflag__not_a_number);
587     ATF_TP_ADD_TC(tp, main__tflag__out_of_range);
588     ATF_TP_ADD_TC(tp, main__uflag__not_a_number);
589     ATF_TP_ADD_TC(tp, main__uflag__out_of_range);
590 
591     ATF_TP_ADD_TC(tp, list__ok);
592     ATF_TP_ADD_TC(tp, list__custom_run_params);
593     ATF_TP_ADD_TC(tp, list__error);
594     ATF_TP_ADD_TC(tp, list__missing_arguments);
595     ATF_TP_ADD_TC(tp, list__too_many_arguments);
596 
597     ATF_TP_ADD_TC(tp, test__ok__pass);
598     ATF_TP_ADD_TC(tp, test__ok__fail);
599     ATF_TP_ADD_TC(tp, test__custom_run_params);
600     ATF_TP_ADD_TC(tp, test__config_variables);
601     ATF_TP_ADD_TC(tp, test__error);
602     ATF_TP_ADD_TC(tp, test__invalid_arguments);
603     ATF_TP_ADD_TC(tp, test__unknown_option);
604     ATF_TP_ADD_TC(tp, test__missing_option_argument);
605 
606     return atf_no_error();
607 }
608