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 43namespace config = utils::config; 44namespace fs = utils::fs; 45namespace passwd = utils::passwd; 46namespace units = utils::units; 47 48 49ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__none); 50ATF_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 58ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__one_ok); 59ATF_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 72ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__one_fail); 73ATF_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 87ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__many_ok); 88ATF_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 103ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__many_fail); 104ATF_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 120ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__one_ok); 121ATF_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 134ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__one_fail); 135ATF_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 149ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__many_ok); 150ATF_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 165ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__many_fail); 166ATF_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 182ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__one_ok); 183ATF_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 198ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__one_fail); 199ATF_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 216ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__many_ok); 217ATF_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 236ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__many_fail); 237ATF_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 255ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__special); 256ATF_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 273ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__root__ok); 274ATF_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 288ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__root__fail); 289ATF_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 302ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__same); 303ATF_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 317ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__ok); 318ATF_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 333ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__fail); 334ATF_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 349ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_disk_space__ok); 350ATF_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 361ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_disk_space__fail); 362ATF_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 374ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_files__ok); 375ATF_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 388ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_files__fail); 389ATF_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 401ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_memory__ok); 402ATF_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 413ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_memory__fail); 414ATF_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 428ATF_TEST_CASE(check_reqs__required_programs__ok); 429ATF_TEST_CASE_HEAD(check_reqs__required_programs__ok) 430{ 431 set_md_var("require.progs", "/bin/ls /bin/mv"); 432} 433ATF_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 450ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_programs__fail_absolute); 451ATF_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 463ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_programs__fail_relative); 464ATF_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 481ATF_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