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 48static 49std::size_t 50array_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 60static 61tools::process::status 62exec_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 83ATF_TEST_CASE(argv_array_init_carray); 84ATF_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} 89ATF_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 117ATF_TEST_CASE(argv_array_init_col); 118ATF_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} 123ATF_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 155ATF_TEST_CASE(argv_array_init_empty); 156ATF_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} 161ATF_TEST_CASE_BODY(argv_array_init_empty) 162{ 163 tools::process::argv_array argv; 164 165 ATF_REQUIRE_EQ(argv.size(), 0); 166} 167 168ATF_TEST_CASE(argv_array_init_varargs); 169ATF_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} 174ATF_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 193ATF_TEST_CASE(argv_array_assign); 194ATF_TEST_CASE_HEAD(argv_array_assign) 195{ 196 set_md_var("descr", "Tests that assigning an argv_array works"); 197} 198ATF_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 223ATF_TEST_CASE(argv_array_copy); 224ATF_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} 229ATF_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 252ATF_TEST_CASE(argv_array_exec_argv); 253ATF_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} 258ATF_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 289ATF_TEST_CASE(argv_array_iter); 290ATF_TEST_CASE_HEAD(argv_array_iter) 291{ 292 set_md_var("descr", "Tests that an argv_array can be iterated"); 293} 294ATF_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 317ATF_TEST_CASE(exec_failure); 318ATF_TEST_CASE_HEAD(exec_failure) 319{ 320 set_md_var("descr", "Tests execing a command that reports failure"); 321} 322ATF_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 329ATF_TEST_CASE(exec_success); 330ATF_TEST_CASE_HEAD(exec_success) 331{ 332 set_md_var("descr", "Tests execing a command that reports success"); 333} 334ATF_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 345ATF_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