1 // Copyright (c) 2008 The NetBSD Foundation, 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 6 // are met: 7 // 1. Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // 2. Redistributions in binary form must reproduce the above copyright 10 // notice, this list of conditions and the following disclaimer in the 11 // documentation and/or other materials provided with the distribution. 12 // 13 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 14 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 15 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 18 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 20 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26 #include "atf-c++/detail/process.hpp" 27 28 #include <cstdlib> 29 #include <cstring> 30 31 #include <atf-c++.hpp> 32 33 #include "atf-c++/detail/test_helpers.hpp" 34 35 // TODO: Testing the fork function is a huge task and I'm afraid of 36 // copy/pasting tons of stuff from the C version. I'd rather not do that 37 // until some code can be shared, which cannot happen until the C++ binding 38 // is cleaned by a fair amount. Instead... just rely (at the moment) on 39 // the system tests for the tools using this module. 40 41 // ------------------------------------------------------------------------ 42 // Auxiliary functions. 43 // ------------------------------------------------------------------------ 44 45 static 46 std::size_t 47 array_size(const char* const* array) 48 { 49 std::size_t size = 0; 50 51 for (const char* const* ptr = array; *ptr != NULL; ptr++) 52 size++; 53 54 return size; 55 } 56 57 static 58 atf::process::status 59 exec_process_helpers(const atf::tests::tc& tc, const char* helper_name) 60 { 61 using atf::process::exec; 62 63 std::vector< std::string > argv; 64 argv.push_back(get_process_helpers_path(tc, true).leaf_name()); 65 argv.push_back(helper_name); 66 67 return exec(get_process_helpers_path(tc, true), 68 atf::process::argv_array(argv), 69 atf::process::stream_inherit(), 70 atf::process::stream_inherit()); 71 } 72 73 // ------------------------------------------------------------------------ 74 // Tests for the "argv_array" type. 75 // ------------------------------------------------------------------------ 76 77 ATF_TEST_CASE(argv_array_init_carray); 78 ATF_TEST_CASE_HEAD(argv_array_init_carray) 79 { 80 set_md_var("descr", "Tests that argv_array is correctly constructed " 81 "from a C-style array of strings"); 82 } 83 ATF_TEST_CASE_BODY(argv_array_init_carray) 84 { 85 { 86 const char* const carray[] = { NULL }; 87 atf::process::argv_array argv(carray); 88 89 ATF_REQUIRE_EQ(argv.size(), 0); 90 } 91 92 { 93 const char* const carray[] = { "arg0", NULL }; 94 atf::process::argv_array argv(carray); 95 96 ATF_REQUIRE_EQ(argv.size(), 1); 97 ATF_REQUIRE(std::strcmp(argv[0], carray[0]) == 0); 98 } 99 100 { 101 const char* const carray[] = { "arg0", "arg1", "arg2", NULL }; 102 atf::process::argv_array argv(carray); 103 104 ATF_REQUIRE_EQ(argv.size(), 3); 105 ATF_REQUIRE(std::strcmp(argv[0], carray[0]) == 0); 106 ATF_REQUIRE(std::strcmp(argv[1], carray[1]) == 0); 107 ATF_REQUIRE(std::strcmp(argv[2], carray[2]) == 0); 108 } 109 } 110 111 ATF_TEST_CASE(argv_array_init_col); 112 ATF_TEST_CASE_HEAD(argv_array_init_col) 113 { 114 set_md_var("descr", "Tests that argv_array is correctly constructed " 115 "from a string collection"); 116 } 117 ATF_TEST_CASE_BODY(argv_array_init_col) 118 { 119 { 120 std::vector< std::string > col; 121 atf::process::argv_array argv(col); 122 123 ATF_REQUIRE_EQ(argv.size(), 0); 124 } 125 126 { 127 std::vector< std::string > col; 128 col.push_back("arg0"); 129 atf::process::argv_array argv(col); 130 131 ATF_REQUIRE_EQ(argv.size(), 1); 132 ATF_REQUIRE_EQ(argv[0], col[0]); 133 } 134 135 { 136 std::vector< std::string > col; 137 col.push_back("arg0"); 138 col.push_back("arg1"); 139 col.push_back("arg2"); 140 atf::process::argv_array argv(col); 141 142 ATF_REQUIRE_EQ(argv.size(), 3); 143 ATF_REQUIRE_EQ(argv[0], col[0]); 144 ATF_REQUIRE_EQ(argv[1], col[1]); 145 ATF_REQUIRE_EQ(argv[2], col[2]); 146 } 147 } 148 149 ATF_TEST_CASE(argv_array_init_empty); 150 ATF_TEST_CASE_HEAD(argv_array_init_empty) 151 { 152 set_md_var("descr", "Tests that argv_array is correctly constructed " 153 "by the default constructor"); 154 } 155 ATF_TEST_CASE_BODY(argv_array_init_empty) 156 { 157 atf::process::argv_array argv; 158 159 ATF_REQUIRE_EQ(argv.size(), 0); 160 } 161 162 ATF_TEST_CASE(argv_array_init_varargs); 163 ATF_TEST_CASE_HEAD(argv_array_init_varargs) 164 { 165 set_md_var("descr", "Tests that argv_array is correctly constructed " 166 "from a variable list of arguments"); 167 } 168 ATF_TEST_CASE_BODY(argv_array_init_varargs) 169 { 170 { 171 atf::process::argv_array argv("arg0", NULL); 172 173 ATF_REQUIRE_EQ(argv.size(), 1); 174 ATF_REQUIRE_EQ(argv[0], std::string("arg0")); 175 } 176 177 { 178 atf::process::argv_array argv("arg0", "arg1", "arg2", NULL); 179 180 ATF_REQUIRE_EQ(argv.size(), 3); 181 ATF_REQUIRE_EQ(argv[0], std::string("arg0")); 182 ATF_REQUIRE_EQ(argv[1], std::string("arg1")); 183 ATF_REQUIRE_EQ(argv[2], std::string("arg2")); 184 } 185 } 186 187 ATF_TEST_CASE(argv_array_assign); 188 ATF_TEST_CASE_HEAD(argv_array_assign) 189 { 190 set_md_var("descr", "Tests that assigning an argv_array works"); 191 } 192 ATF_TEST_CASE_BODY(argv_array_assign) 193 { 194 using atf::process::argv_array; 195 196 const char* const carray1[] = { "arg1", NULL }; 197 const char* const carray2[] = { "arg1", "arg2", NULL }; 198 199 std::auto_ptr< argv_array > argv1(new argv_array(carray1)); 200 std::auto_ptr< argv_array > argv2(new argv_array(carray2)); 201 202 *argv2 = *argv1; 203 ATF_REQUIRE_EQ(argv2->size(), argv1->size()); 204 ATF_REQUIRE(std::strcmp((*argv2)[0], (*argv1)[0]) == 0); 205 206 ATF_REQUIRE(argv2->exec_argv() != argv1->exec_argv()); 207 argv1.release(); 208 { 209 const char* const* eargv2 = argv2->exec_argv(); 210 ATF_REQUIRE(std::strcmp(eargv2[0], carray1[0]) == 0); 211 ATF_REQUIRE_EQ(eargv2[1], static_cast< const char* >(NULL)); 212 } 213 214 argv2.release(); 215 } 216 217 ATF_TEST_CASE(argv_array_copy); 218 ATF_TEST_CASE_HEAD(argv_array_copy) 219 { 220 set_md_var("descr", "Tests that copying an argv_array constructed from " 221 "a C-style array of strings works"); 222 } 223 ATF_TEST_CASE_BODY(argv_array_copy) 224 { 225 using atf::process::argv_array; 226 227 const char* const carray[] = { "arg0", NULL }; 228 229 std::auto_ptr< argv_array > argv1(new argv_array(carray)); 230 std::auto_ptr< argv_array > argv2(new argv_array(*argv1)); 231 232 ATF_REQUIRE_EQ(argv2->size(), argv1->size()); 233 ATF_REQUIRE(std::strcmp((*argv2)[0], (*argv1)[0]) == 0); 234 235 ATF_REQUIRE(argv2->exec_argv() != argv1->exec_argv()); 236 argv1.release(); 237 { 238 const char* const* eargv2 = argv2->exec_argv(); 239 ATF_REQUIRE(std::strcmp(eargv2[0], carray[0]) == 0); 240 ATF_REQUIRE_EQ(eargv2[1], static_cast< const char* >(NULL)); 241 } 242 243 argv2.release(); 244 } 245 246 ATF_TEST_CASE(argv_array_exec_argv); 247 ATF_TEST_CASE_HEAD(argv_array_exec_argv) 248 { 249 set_md_var("descr", "Tests that the exec argv provided by an argv_array " 250 "is correct"); 251 } 252 ATF_TEST_CASE_BODY(argv_array_exec_argv) 253 { 254 using atf::process::argv_array; 255 256 { 257 argv_array argv; 258 const char* const* eargv = argv.exec_argv(); 259 ATF_REQUIRE_EQ(array_size(eargv), 0); 260 ATF_REQUIRE_EQ(eargv[0], static_cast< const char* >(NULL)); 261 } 262 263 { 264 const char* const carray[] = { "arg0", NULL }; 265 argv_array argv(carray); 266 const char* const* eargv = argv.exec_argv(); 267 ATF_REQUIRE_EQ(array_size(eargv), 1); 268 ATF_REQUIRE(std::strcmp(eargv[0], "arg0") == 0); 269 ATF_REQUIRE_EQ(eargv[1], static_cast< const char* >(NULL)); 270 } 271 272 { 273 std::vector< std::string > col; 274 col.push_back("arg0"); 275 argv_array argv(col); 276 const char* const* eargv = argv.exec_argv(); 277 ATF_REQUIRE_EQ(array_size(eargv), 1); 278 ATF_REQUIRE(std::strcmp(eargv[0], "arg0") == 0); 279 ATF_REQUIRE_EQ(eargv[1], static_cast< const char* >(NULL)); 280 } 281 } 282 283 ATF_TEST_CASE(argv_array_iter); 284 ATF_TEST_CASE_HEAD(argv_array_iter) 285 { 286 set_md_var("descr", "Tests that an argv_array can be iterated"); 287 } 288 ATF_TEST_CASE_BODY(argv_array_iter) 289 { 290 using atf::process::argv_array; 291 292 std::vector< std::string > vector; 293 vector.push_back("arg0"); 294 vector.push_back("arg1"); 295 vector.push_back("arg2"); 296 297 argv_array argv(vector); 298 ATF_REQUIRE_EQ(argv.size(), 3); 299 std::vector< std::string >::size_type pos = 0; 300 for (argv_array::const_iterator iter = argv.begin(); iter != argv.end(); 301 iter++) { 302 ATF_REQUIRE_EQ(*iter, vector[pos]); 303 pos++; 304 } 305 } 306 307 // ------------------------------------------------------------------------ 308 // Tests cases for the free functions. 309 // ------------------------------------------------------------------------ 310 311 ATF_TEST_CASE(exec_failure); 312 ATF_TEST_CASE_HEAD(exec_failure) 313 { 314 set_md_var("descr", "Tests execing a command that reports failure"); 315 } 316 ATF_TEST_CASE_BODY(exec_failure) 317 { 318 const atf::process::status s = exec_process_helpers(*this, "exit-failure"); 319 ATF_REQUIRE(s.exited()); 320 ATF_REQUIRE_EQ(s.exitstatus(), EXIT_FAILURE); 321 } 322 323 ATF_TEST_CASE(exec_success); 324 ATF_TEST_CASE_HEAD(exec_success) 325 { 326 set_md_var("descr", "Tests execing a command that reports success"); 327 } 328 ATF_TEST_CASE_BODY(exec_success) 329 { 330 const atf::process::status s = exec_process_helpers(*this, "exit-success"); 331 ATF_REQUIRE(s.exited()); 332 ATF_REQUIRE_EQ(s.exitstatus(), EXIT_SUCCESS); 333 } 334 335 // ------------------------------------------------------------------------ 336 // Main. 337 // ------------------------------------------------------------------------ 338 339 ATF_INIT_TEST_CASES(tcs) 340 { 341 // Add the test cases for the "argv_array" type. 342 ATF_ADD_TEST_CASE(tcs, argv_array_assign); 343 ATF_ADD_TEST_CASE(tcs, argv_array_copy); 344 ATF_ADD_TEST_CASE(tcs, argv_array_exec_argv); 345 ATF_ADD_TEST_CASE(tcs, argv_array_init_carray); 346 ATF_ADD_TEST_CASE(tcs, argv_array_init_col); 347 ATF_ADD_TEST_CASE(tcs, argv_array_init_empty); 348 ATF_ADD_TEST_CASE(tcs, argv_array_init_varargs); 349 ATF_ADD_TEST_CASE(tcs, argv_array_iter); 350 351 // Add the test cases for the free functions. 352 ATF_ADD_TEST_CASE(tcs, exec_failure); 353 ATF_ADD_TEST_CASE(tcs, exec_success); 354 } 355