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