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