1 // Copyright 2012 The Kyua Authors. 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 are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // * Neither the name of Google Inc. nor the names of its contributors 14 // may be used to endorse or promote products derived from this software 15 // without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 #include "model/metadata.hpp" 30 31 #include <atf-c++.hpp> 32 33 #include "engine/config.hpp" 34 #include "engine/requirements.hpp" 35 #include "utils/config/tree.ipp" 36 #include "utils/env.hpp" 37 #include "utils/fs/operations.hpp" 38 #include "utils/fs/path.hpp" 39 #include "utils/memory.hpp" 40 #include "utils/passwd.hpp" 41 #include "utils/units.hpp" 42 43 namespace config = utils::config; 44 namespace fs = utils::fs; 45 namespace passwd = utils::passwd; 46 namespace units = utils::units; 47 48 49 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__none); 50 ATF_TEST_CASE_BODY(check_reqs__none) 51 { 52 const model::metadata md = model::metadata_builder().build(); 53 ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "", 54 fs::path(".")).empty()); 55 } 56 57 58 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__one_ok); 59 ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__one_ok) 60 { 61 const model::metadata md = model::metadata_builder() 62 .add_allowed_architecture("x86_64") 63 .build(); 64 65 config::tree user_config = engine::default_config(); 66 user_config.set_string("architecture", "x86_64"); 67 user_config.set_string("platform", ""); 68 ATF_REQUIRE(engine::check_reqs(md, user_config, "", fs::path(".")).empty()); 69 } 70 71 72 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__one_fail); 73 ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__one_fail) 74 { 75 const model::metadata md = model::metadata_builder() 76 .add_allowed_architecture("x86_64") 77 .build(); 78 79 config::tree user_config = engine::default_config(); 80 user_config.set_string("architecture", "i386"); 81 user_config.set_string("platform", ""); 82 ATF_REQUIRE_MATCH("Current architecture 'i386' not supported", 83 engine::check_reqs(md, user_config, "", fs::path("."))); 84 } 85 86 87 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__many_ok); 88 ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__many_ok) 89 { 90 const model::metadata md = model::metadata_builder() 91 .add_allowed_architecture("x86_64") 92 .add_allowed_architecture("i386") 93 .add_allowed_architecture("powerpc") 94 .build(); 95 96 config::tree user_config = engine::default_config(); 97 user_config.set_string("architecture", "i386"); 98 user_config.set_string("platform", ""); 99 ATF_REQUIRE(engine::check_reqs(md, user_config, "", fs::path(".")).empty()); 100 } 101 102 103 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__many_fail); 104 ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__many_fail) 105 { 106 const model::metadata md = model::metadata_builder() 107 .add_allowed_architecture("x86_64") 108 .add_allowed_architecture("i386") 109 .add_allowed_architecture("powerpc") 110 .build(); 111 112 config::tree user_config = engine::default_config(); 113 user_config.set_string("architecture", "arm"); 114 user_config.set_string("platform", ""); 115 ATF_REQUIRE_MATCH("Current architecture 'arm' not supported", 116 engine::check_reqs(md, user_config, "", fs::path("."))); 117 } 118 119 120 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__one_ok); 121 ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__one_ok) 122 { 123 const model::metadata md = model::metadata_builder() 124 .add_allowed_platform("amd64") 125 .build(); 126 127 config::tree user_config = engine::default_config(); 128 user_config.set_string("architecture", ""); 129 user_config.set_string("platform", "amd64"); 130 ATF_REQUIRE(engine::check_reqs(md, user_config, "", fs::path(".")).empty()); 131 } 132 133 134 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__one_fail); 135 ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__one_fail) 136 { 137 const model::metadata md = model::metadata_builder() 138 .add_allowed_platform("amd64") 139 .build(); 140 141 config::tree user_config = engine::default_config(); 142 user_config.set_string("architecture", ""); 143 user_config.set_string("platform", "i386"); 144 ATF_REQUIRE_MATCH("Current platform 'i386' not supported", 145 engine::check_reqs(md, user_config, "", fs::path("."))); 146 } 147 148 149 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__many_ok); 150 ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__many_ok) 151 { 152 const model::metadata md = model::metadata_builder() 153 .add_allowed_platform("amd64") 154 .add_allowed_platform("i386") 155 .add_allowed_platform("macppc") 156 .build(); 157 158 config::tree user_config = engine::default_config(); 159 user_config.set_string("architecture", ""); 160 user_config.set_string("platform", "i386"); 161 ATF_REQUIRE(engine::check_reqs(md, user_config, "", fs::path(".")).empty()); 162 } 163 164 165 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__many_fail); 166 ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__many_fail) 167 { 168 const model::metadata md = model::metadata_builder() 169 .add_allowed_platform("amd64") 170 .add_allowed_platform("i386") 171 .add_allowed_platform("macppc") 172 .build(); 173 174 config::tree user_config = engine::default_config(); 175 user_config.set_string("architecture", ""); 176 user_config.set_string("platform", "shark"); 177 ATF_REQUIRE_MATCH("Current platform 'shark' not supported", 178 engine::check_reqs(md, user_config, "", fs::path("."))); 179 } 180 181 182 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__one_ok); 183 ATF_TEST_CASE_BODY(check_reqs__required_configs__one_ok) 184 { 185 const model::metadata md = model::metadata_builder() 186 .add_required_config("my-var") 187 .build(); 188 189 config::tree user_config = engine::default_config(); 190 user_config.set_string("test_suites.suite.aaa", "value1"); 191 user_config.set_string("test_suites.suite.my-var", "value2"); 192 user_config.set_string("test_suites.suite.zzz", "value3"); 193 ATF_REQUIRE(engine::check_reqs(md, user_config, "suite", 194 fs::path(".")).empty()); 195 } 196 197 198 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__one_fail); 199 ATF_TEST_CASE_BODY(check_reqs__required_configs__one_fail) 200 { 201 const model::metadata md = model::metadata_builder() 202 .add_required_config("unprivileged_user") 203 .build(); 204 205 config::tree user_config = engine::default_config(); 206 user_config.set_string("test_suites.suite.aaa", "value1"); 207 user_config.set_string("test_suites.suite.my-var", "value2"); 208 user_config.set_string("test_suites.suite.zzz", "value3"); 209 ATF_REQUIRE_MATCH("Required configuration property 'unprivileged_user' not " 210 "defined", 211 engine::check_reqs(md, user_config, "suite", 212 fs::path("."))); 213 } 214 215 216 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__many_ok); 217 ATF_TEST_CASE_BODY(check_reqs__required_configs__many_ok) 218 { 219 const model::metadata md = model::metadata_builder() 220 .add_required_config("foo") 221 .add_required_config("bar") 222 .add_required_config("baz") 223 .build(); 224 225 config::tree user_config = engine::default_config(); 226 user_config.set_string("test_suites.suite.aaa", "value1"); 227 user_config.set_string("test_suites.suite.foo", "value2"); 228 user_config.set_string("test_suites.suite.bar", "value3"); 229 user_config.set_string("test_suites.suite.baz", "value4"); 230 user_config.set_string("test_suites.suite.zzz", "value5"); 231 ATF_REQUIRE(engine::check_reqs(md, user_config, "suite", 232 fs::path(".")).empty()); 233 } 234 235 236 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__many_fail); 237 ATF_TEST_CASE_BODY(check_reqs__required_configs__many_fail) 238 { 239 const model::metadata md = model::metadata_builder() 240 .add_required_config("foo") 241 .add_required_config("bar") 242 .add_required_config("baz") 243 .build(); 244 245 config::tree user_config = engine::default_config(); 246 user_config.set_string("test_suites.suite.aaa", "value1"); 247 user_config.set_string("test_suites.suite.foo", "value2"); 248 user_config.set_string("test_suites.suite.zzz", "value3"); 249 ATF_REQUIRE_MATCH("Required configuration property 'bar' not defined", 250 engine::check_reqs(md, user_config, "suite", 251 fs::path("."))); 252 } 253 254 255 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__special); 256 ATF_TEST_CASE_BODY(check_reqs__required_configs__special) 257 { 258 const model::metadata md = model::metadata_builder() 259 .add_required_config("unprivileged-user") 260 .build(); 261 262 config::tree user_config = engine::default_config(); 263 ATF_REQUIRE_MATCH("Required configuration property 'unprivileged-user' " 264 "not defined", 265 engine::check_reqs(md, user_config, "", fs::path("."))); 266 user_config.set< engine::user_node >( 267 "unprivileged_user", passwd::user("foo", 1, 2)); 268 ATF_REQUIRE(engine::check_reqs(md, user_config, "foo", 269 fs::path(".")).empty()); 270 } 271 272 273 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__root__ok); 274 ATF_TEST_CASE_BODY(check_reqs__required_user__root__ok) 275 { 276 const model::metadata md = model::metadata_builder() 277 .set_required_user("root") 278 .build(); 279 280 config::tree user_config = engine::default_config(); 281 ATF_REQUIRE(!user_config.is_set("unprivileged_user")); 282 283 passwd::set_current_user_for_testing(passwd::user("", 0, 1)); 284 ATF_REQUIRE(engine::check_reqs(md, user_config, "", fs::path(".")).empty()); 285 } 286 287 288 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__root__fail); 289 ATF_TEST_CASE_BODY(check_reqs__required_user__root__fail) 290 { 291 const model::metadata md = model::metadata_builder() 292 .set_required_user("root") 293 .build(); 294 295 passwd::set_current_user_for_testing(passwd::user("", 123, 1)); 296 ATF_REQUIRE_MATCH("Requires root privileges", 297 engine::check_reqs(md, engine::empty_config(), "", 298 fs::path("."))); 299 } 300 301 302 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__same); 303 ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__same) 304 { 305 const model::metadata md = model::metadata_builder() 306 .set_required_user("unprivileged") 307 .build(); 308 309 config::tree user_config = engine::default_config(); 310 ATF_REQUIRE(!user_config.is_set("unprivileged_user")); 311 312 passwd::set_current_user_for_testing(passwd::user("", 123, 1)); 313 ATF_REQUIRE(engine::check_reqs(md, user_config, "", fs::path(".")).empty()); 314 } 315 316 317 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__ok); 318 ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__ok) 319 { 320 const model::metadata md = model::metadata_builder() 321 .set_required_user("unprivileged") 322 .build(); 323 324 config::tree user_config = engine::default_config(); 325 user_config.set< engine::user_node >( 326 "unprivileged_user", passwd::user("", 123, 1)); 327 328 passwd::set_current_user_for_testing(passwd::user("", 0, 1)); 329 ATF_REQUIRE(engine::check_reqs(md, user_config, "", fs::path(".")).empty()); 330 } 331 332 333 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__fail); 334 ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__fail) 335 { 336 const model::metadata md = model::metadata_builder() 337 .set_required_user("unprivileged") 338 .build(); 339 340 config::tree user_config = engine::default_config(); 341 ATF_REQUIRE(!user_config.is_set("unprivileged_user")); 342 343 passwd::set_current_user_for_testing(passwd::user("", 0, 1)); 344 ATF_REQUIRE_MATCH("Requires.*unprivileged.*unprivileged-user", 345 engine::check_reqs(md, user_config, "", fs::path("."))); 346 } 347 348 349 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_disk_space__ok); 350 ATF_TEST_CASE_BODY(check_reqs__required_disk_space__ok) 351 { 352 const model::metadata md = model::metadata_builder() 353 .set_required_disk_space(units::bytes::parse("1m")) 354 .build(); 355 356 ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "", 357 fs::path(".")).empty()); 358 } 359 360 361 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_disk_space__fail); 362 ATF_TEST_CASE_BODY(check_reqs__required_disk_space__fail) 363 { 364 const model::metadata md = model::metadata_builder() 365 .set_required_disk_space(units::bytes::parse("1000t")) 366 .build(); 367 368 ATF_REQUIRE_MATCH("Requires 1000.00T .*disk space", 369 engine::check_reqs(md, engine::empty_config(), "", 370 fs::path("."))); 371 } 372 373 374 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_files__ok); 375 ATF_TEST_CASE_BODY(check_reqs__required_files__ok) 376 { 377 const model::metadata md = model::metadata_builder() 378 .add_required_file(fs::current_path() / "test-file") 379 .build(); 380 381 atf::utils::create_file("test-file", ""); 382 383 ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "", 384 fs::path(".")).empty()); 385 } 386 387 388 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_files__fail); 389 ATF_TEST_CASE_BODY(check_reqs__required_files__fail) 390 { 391 const model::metadata md = model::metadata_builder() 392 .add_required_file(fs::path("/non-existent/file")) 393 .build(); 394 395 ATF_REQUIRE_MATCH("'/non-existent/file' not found$", 396 engine::check_reqs(md, engine::empty_config(), "", 397 fs::path("."))); 398 } 399 400 401 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_memory__ok); 402 ATF_TEST_CASE_BODY(check_reqs__required_memory__ok) 403 { 404 const model::metadata md = model::metadata_builder() 405 .set_required_memory(units::bytes::parse("1m")) 406 .build(); 407 408 ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "", 409 fs::path(".")).empty()); 410 } 411 412 413 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_memory__fail); 414 ATF_TEST_CASE_BODY(check_reqs__required_memory__fail) 415 { 416 const model::metadata md = model::metadata_builder() 417 .set_required_memory(units::bytes::parse("100t")) 418 .build(); 419 420 if (utils::physical_memory() == 0) 421 skip("Don't know how to query the amount of physical memory"); 422 ATF_REQUIRE_MATCH("Requires 100.00T .*memory", 423 engine::check_reqs(md, engine::empty_config(), "", 424 fs::path("."))); 425 } 426 427 428 ATF_TEST_CASE(check_reqs__required_programs__ok); 429 ATF_TEST_CASE_HEAD(check_reqs__required_programs__ok) 430 { 431 set_md_var("require.progs", "/bin/ls /bin/mv"); 432 } 433 ATF_TEST_CASE_BODY(check_reqs__required_programs__ok) 434 { 435 const model::metadata md = model::metadata_builder() 436 .add_required_program(fs::path("/bin/ls")) 437 .add_required_program(fs::path("foo")) 438 .add_required_program(fs::path("/bin/mv")) 439 .build(); 440 441 fs::mkdir(fs::path("bin"), 0755); 442 atf::utils::create_file("bin/foo", ""); 443 utils::setenv("PATH", (fs::current_path() / "bin").str()); 444 445 ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "", 446 fs::path(".")).empty()); 447 } 448 449 450 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_programs__fail_absolute); 451 ATF_TEST_CASE_BODY(check_reqs__required_programs__fail_absolute) 452 { 453 const model::metadata md = model::metadata_builder() 454 .add_required_program(fs::path("/non-existent/program")) 455 .build(); 456 457 ATF_REQUIRE_MATCH("'/non-existent/program' not found$", 458 engine::check_reqs(md, engine::empty_config(), "", 459 fs::path("."))); 460 } 461 462 463 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_programs__fail_relative); 464 ATF_TEST_CASE_BODY(check_reqs__required_programs__fail_relative) 465 { 466 const model::metadata md = model::metadata_builder() 467 .add_required_program(fs::path("foo")) 468 .add_required_program(fs::path("bar")) 469 .build(); 470 471 fs::mkdir(fs::path("bin"), 0755); 472 atf::utils::create_file("bin/foo", ""); 473 utils::setenv("PATH", (fs::current_path() / "bin").str()); 474 475 ATF_REQUIRE_MATCH("'bar' not found in PATH$", 476 engine::check_reqs(md, engine::empty_config(), "", 477 fs::path("."))); 478 } 479 480 481 ATF_INIT_TEST_CASES(tcs) 482 { 483 ATF_ADD_TEST_CASE(tcs, check_reqs__none); 484 ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__one_ok); 485 ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__one_fail); 486 ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__many_ok); 487 ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__many_fail); 488 ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__one_ok); 489 ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__one_fail); 490 ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__many_ok); 491 ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__many_fail); 492 ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__one_ok); 493 ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__one_fail); 494 ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__many_ok); 495 ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__many_fail); 496 ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__special); 497 ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__root__ok); 498 ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__root__fail); 499 ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__unprivileged__same); 500 ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__unprivileged__ok); 501 ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__unprivileged__fail); 502 ATF_ADD_TEST_CASE(tcs, check_reqs__required_disk_space__ok); 503 ATF_ADD_TEST_CASE(tcs, check_reqs__required_disk_space__fail); 504 ATF_ADD_TEST_CASE(tcs, check_reqs__required_files__ok); 505 ATF_ADD_TEST_CASE(tcs, check_reqs__required_files__fail); 506 ATF_ADD_TEST_CASE(tcs, check_reqs__required_memory__ok); 507 ATF_ADD_TEST_CASE(tcs, check_reqs__required_memory__fail); 508 ATF_ADD_TEST_CASE(tcs, check_reqs__required_programs__ok); 509 ATF_ADD_TEST_CASE(tcs, check_reqs__required_programs__fail_absolute); 510 ATF_ADD_TEST_CASE(tcs, check_reqs__required_programs__fail_relative); 511 } 512