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