1 // Copyright (c) 2007 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/fs.hpp" 27 28 extern "C" { 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 } 32 33 #include <fstream> 34 #include <cerrno> 35 #include <cstdio> 36 37 #include <atf-c++.hpp> 38 39 #include "atf-c++/detail/exceptions.hpp" 40 41 // ------------------------------------------------------------------------ 42 // Auxiliary functions. 43 // ------------------------------------------------------------------------ 44 45 static 46 void 47 create_files(void) 48 { 49 ::mkdir("files", 0755); 50 ::mkdir("files/dir", 0755); 51 52 std::ofstream os("files/reg"); 53 os.close(); 54 55 // TODO: Should create all other file types (blk, chr, fifo, lnk, sock) 56 // and test for them... but the underlying file system may not support 57 // most of these. Specially as we are working on /tmp, which can be 58 // mounted with flags such as "nodev". See how to deal with this 59 // situation. 60 } 61 62 // ------------------------------------------------------------------------ 63 // Test cases for the "path" class. 64 // ------------------------------------------------------------------------ 65 66 ATF_TEST_CASE(path_normalize); 67 ATF_TEST_CASE_HEAD(path_normalize) 68 { 69 set_md_var("descr", "Tests the path's normalization"); 70 } 71 ATF_TEST_CASE_BODY(path_normalize) 72 { 73 using atf::fs::path; 74 75 ATF_REQUIRE_EQ(path(".").str(), "."); 76 ATF_REQUIRE_EQ(path("..").str(), ".."); 77 78 ATF_REQUIRE_EQ(path("foo").str(), "foo"); 79 ATF_REQUIRE_EQ(path("foo/bar").str(), "foo/bar"); 80 ATF_REQUIRE_EQ(path("foo/bar/").str(), "foo/bar"); 81 82 ATF_REQUIRE_EQ(path("/foo").str(), "/foo"); 83 ATF_REQUIRE_EQ(path("/foo/bar").str(), "/foo/bar"); 84 ATF_REQUIRE_EQ(path("/foo/bar/").str(), "/foo/bar"); 85 86 ATF_REQUIRE_EQ(path("///foo").str(), "/foo"); 87 ATF_REQUIRE_EQ(path("///foo///bar").str(), "/foo/bar"); 88 ATF_REQUIRE_EQ(path("///foo///bar///").str(), "/foo/bar"); 89 } 90 91 ATF_TEST_CASE(path_is_absolute); 92 ATF_TEST_CASE_HEAD(path_is_absolute) 93 { 94 set_md_var("descr", "Tests the path::is_absolute function"); 95 } 96 ATF_TEST_CASE_BODY(path_is_absolute) 97 { 98 using atf::fs::path; 99 100 ATF_REQUIRE( path("/").is_absolute()); 101 ATF_REQUIRE( path("////").is_absolute()); 102 ATF_REQUIRE( path("////a").is_absolute()); 103 ATF_REQUIRE( path("//a//").is_absolute()); 104 ATF_REQUIRE(!path("a////").is_absolute()); 105 ATF_REQUIRE(!path("../foo").is_absolute()); 106 } 107 108 ATF_TEST_CASE(path_is_root); 109 ATF_TEST_CASE_HEAD(path_is_root) 110 { 111 set_md_var("descr", "Tests the path::is_root function"); 112 } 113 ATF_TEST_CASE_BODY(path_is_root) 114 { 115 using atf::fs::path; 116 117 ATF_REQUIRE( path("/").is_root()); 118 ATF_REQUIRE( path("////").is_root()); 119 ATF_REQUIRE(!path("////a").is_root()); 120 ATF_REQUIRE(!path("//a//").is_root()); 121 ATF_REQUIRE(!path("a////").is_root()); 122 ATF_REQUIRE(!path("../foo").is_root()); 123 } 124 125 ATF_TEST_CASE(path_branch_path); 126 ATF_TEST_CASE_HEAD(path_branch_path) 127 { 128 set_md_var("descr", "Tests the path::branch_path function"); 129 } 130 ATF_TEST_CASE_BODY(path_branch_path) 131 { 132 using atf::fs::path; 133 134 ATF_REQUIRE_EQ(path(".").branch_path().str(), "."); 135 ATF_REQUIRE_EQ(path("foo").branch_path().str(), "."); 136 ATF_REQUIRE_EQ(path("foo/bar").branch_path().str(), "foo"); 137 ATF_REQUIRE_EQ(path("/foo").branch_path().str(), "/"); 138 ATF_REQUIRE_EQ(path("/foo/bar").branch_path().str(), "/foo"); 139 } 140 141 ATF_TEST_CASE(path_leaf_name); 142 ATF_TEST_CASE_HEAD(path_leaf_name) 143 { 144 set_md_var("descr", "Tests the path::leaf_name function"); 145 } 146 ATF_TEST_CASE_BODY(path_leaf_name) 147 { 148 using atf::fs::path; 149 150 ATF_REQUIRE_EQ(path(".").leaf_name(), "."); 151 ATF_REQUIRE_EQ(path("foo").leaf_name(), "foo"); 152 ATF_REQUIRE_EQ(path("foo/bar").leaf_name(), "bar"); 153 ATF_REQUIRE_EQ(path("/foo").leaf_name(), "foo"); 154 ATF_REQUIRE_EQ(path("/foo/bar").leaf_name(), "bar"); 155 } 156 157 ATF_TEST_CASE(path_compare_equal); 158 ATF_TEST_CASE_HEAD(path_compare_equal) 159 { 160 set_md_var("descr", "Tests the comparison for equality between paths"); 161 } 162 ATF_TEST_CASE_BODY(path_compare_equal) 163 { 164 using atf::fs::path; 165 166 ATF_REQUIRE(path("/") == path("///")); 167 ATF_REQUIRE(path("/a") == path("///a")); 168 ATF_REQUIRE(path("/a") == path("///a///")); 169 170 ATF_REQUIRE(path("a/b/c") == path("a//b//c")); 171 ATF_REQUIRE(path("a/b/c") == path("a//b//c///")); 172 } 173 174 ATF_TEST_CASE(path_compare_different); 175 ATF_TEST_CASE_HEAD(path_compare_different) 176 { 177 set_md_var("descr", "Tests the comparison for difference between paths"); 178 } 179 ATF_TEST_CASE_BODY(path_compare_different) 180 { 181 using atf::fs::path; 182 183 ATF_REQUIRE(path("/") != path("//a/")); 184 ATF_REQUIRE(path("/a") != path("a///")); 185 186 ATF_REQUIRE(path("a/b/c") != path("a/b")); 187 ATF_REQUIRE(path("a/b/c") != path("a//b")); 188 ATF_REQUIRE(path("a/b/c") != path("/a/b/c")); 189 ATF_REQUIRE(path("a/b/c") != path("/a//b//c")); 190 } 191 192 ATF_TEST_CASE(path_concat); 193 ATF_TEST_CASE_HEAD(path_concat) 194 { 195 set_md_var("descr", "Tests the concatenation of multiple paths"); 196 } 197 ATF_TEST_CASE_BODY(path_concat) 198 { 199 using atf::fs::path; 200 201 ATF_REQUIRE_EQ((path("foo") / "bar").str(), "foo/bar"); 202 ATF_REQUIRE_EQ((path("foo/") / "/bar").str(), "foo/bar"); 203 ATF_REQUIRE_EQ((path("foo/") / "/bar/baz").str(), "foo/bar/baz"); 204 ATF_REQUIRE_EQ((path("foo/") / "///bar///baz").str(), "foo/bar/baz"); 205 } 206 207 ATF_TEST_CASE(path_to_absolute); 208 ATF_TEST_CASE_HEAD(path_to_absolute) 209 { 210 set_md_var("descr", "Tests the conversion of a relative path to an " 211 "absolute one"); 212 } 213 ATF_TEST_CASE_BODY(path_to_absolute) 214 { 215 using atf::fs::file_info; 216 using atf::fs::path; 217 218 create_files(); 219 220 { 221 const path p("."); 222 path pa = p.to_absolute(); 223 ATF_REQUIRE(pa.is_absolute()); 224 225 file_info fi(p); 226 file_info fia(pa); 227 ATF_REQUIRE_EQ(fi.get_device(), fia.get_device()); 228 ATF_REQUIRE_EQ(fi.get_inode(), fia.get_inode()); 229 } 230 231 { 232 const path p("files/reg"); 233 path pa = p.to_absolute(); 234 ATF_REQUIRE(pa.is_absolute()); 235 236 file_info fi(p); 237 file_info fia(pa); 238 ATF_REQUIRE_EQ(fi.get_device(), fia.get_device()); 239 ATF_REQUIRE_EQ(fi.get_inode(), fia.get_inode()); 240 } 241 } 242 243 ATF_TEST_CASE(path_op_less); 244 ATF_TEST_CASE_HEAD(path_op_less) 245 { 246 set_md_var("descr", "Tests that the path's less-than operator works"); 247 } 248 ATF_TEST_CASE_BODY(path_op_less) 249 { 250 using atf::fs::path; 251 252 create_files(); 253 254 ATF_REQUIRE(!(path("aaa") < path("aaa"))); 255 256 ATF_REQUIRE( path("aab") < path("abc")); 257 ATF_REQUIRE(!(path("abc") < path("aab"))); 258 } 259 260 // ------------------------------------------------------------------------ 261 // Test cases for the "directory" class. 262 // ------------------------------------------------------------------------ 263 264 ATF_TEST_CASE(directory_read); 265 ATF_TEST_CASE_HEAD(directory_read) 266 { 267 set_md_var("descr", "Tests the directory class creation, which reads " 268 "the contents of a directory"); 269 } 270 ATF_TEST_CASE_BODY(directory_read) 271 { 272 using atf::fs::directory; 273 using atf::fs::path; 274 275 create_files(); 276 277 directory d(path("files")); 278 ATF_REQUIRE_EQ(d.size(), 4); 279 ATF_REQUIRE(d.find(".") != d.end()); 280 ATF_REQUIRE(d.find("..") != d.end()); 281 ATF_REQUIRE(d.find("dir") != d.end()); 282 ATF_REQUIRE(d.find("reg") != d.end()); 283 } 284 285 ATF_TEST_CASE(directory_file_info); 286 ATF_TEST_CASE_HEAD(directory_file_info) 287 { 288 set_md_var("descr", "Tests that the file_info objects attached to the " 289 "directory are valid"); 290 } 291 ATF_TEST_CASE_BODY(directory_file_info) 292 { 293 using atf::fs::directory; 294 using atf::fs::file_info; 295 using atf::fs::path; 296 297 create_files(); 298 299 directory d(path("files")); 300 301 { 302 directory::const_iterator iter = d.find("dir"); 303 ATF_REQUIRE(iter != d.end()); 304 const file_info& fi = (*iter).second; 305 ATF_REQUIRE(fi.get_type() == file_info::dir_type); 306 } 307 308 { 309 directory::const_iterator iter = d.find("reg"); 310 ATF_REQUIRE(iter != d.end()); 311 const file_info& fi = (*iter).second; 312 ATF_REQUIRE(fi.get_type() == file_info::reg_type); 313 } 314 } 315 316 ATF_TEST_CASE(directory_names); 317 ATF_TEST_CASE_HEAD(directory_names) 318 { 319 set_md_var("descr", "Tests the directory's names method"); 320 } 321 ATF_TEST_CASE_BODY(directory_names) 322 { 323 using atf::fs::directory; 324 using atf::fs::path; 325 326 create_files(); 327 328 directory d(path("files")); 329 std::set< std::string > ns = d.names(); 330 ATF_REQUIRE_EQ(ns.size(), 4); 331 ATF_REQUIRE(ns.find(".") != ns.end()); 332 ATF_REQUIRE(ns.find("..") != ns.end()); 333 ATF_REQUIRE(ns.find("dir") != ns.end()); 334 ATF_REQUIRE(ns.find("reg") != ns.end()); 335 } 336 337 // ------------------------------------------------------------------------ 338 // Test cases for the "file_info" class. 339 // ------------------------------------------------------------------------ 340 341 ATF_TEST_CASE(file_info_stat); 342 ATF_TEST_CASE_HEAD(file_info_stat) 343 { 344 set_md_var("descr", "Tests the file_info creation and its basic contents"); 345 } 346 ATF_TEST_CASE_BODY(file_info_stat) 347 { 348 using atf::fs::file_info; 349 using atf::fs::path; 350 351 create_files(); 352 353 { 354 path p("files/dir"); 355 file_info fi(p); 356 ATF_REQUIRE(fi.get_type() == file_info::dir_type); 357 } 358 359 { 360 path p("files/reg"); 361 file_info fi(p); 362 ATF_REQUIRE(fi.get_type() == file_info::reg_type); 363 } 364 } 365 366 ATF_TEST_CASE(file_info_perms); 367 ATF_TEST_CASE_HEAD(file_info_perms) 368 { 369 set_md_var("descr", "Tests the file_info methods to get the file's " 370 "permissions"); 371 } 372 ATF_TEST_CASE_BODY(file_info_perms) 373 { 374 using atf::fs::file_info; 375 using atf::fs::path; 376 377 path p("file"); 378 379 std::ofstream os(p.c_str()); 380 os.close(); 381 382 #define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \ 383 { \ 384 file_info fi(p); \ 385 ATF_REQUIRE(fi.is_owner_readable() == ur); \ 386 ATF_REQUIRE(fi.is_owner_writable() == uw); \ 387 ATF_REQUIRE(fi.is_owner_executable() == ux); \ 388 ATF_REQUIRE(fi.is_group_readable() == gr); \ 389 ATF_REQUIRE(fi.is_group_writable() == gw); \ 390 ATF_REQUIRE(fi.is_group_executable() == gx); \ 391 ATF_REQUIRE(fi.is_other_readable() == othr); \ 392 ATF_REQUIRE(fi.is_other_writable() == othw); \ 393 ATF_REQUIRE(fi.is_other_executable() == othx); \ 394 } 395 396 ::chmod(p.c_str(), 0000); 397 perms(false, false, false, false, false, false, false, false, false); 398 399 ::chmod(p.c_str(), 0001); 400 perms(false, false, false, false, false, false, false, false, true); 401 402 ::chmod(p.c_str(), 0010); 403 perms(false, false, false, false, false, true, false, false, false); 404 405 ::chmod(p.c_str(), 0100); 406 perms(false, false, true, false, false, false, false, false, false); 407 408 ::chmod(p.c_str(), 0002); 409 perms(false, false, false, false, false, false, false, true, false); 410 411 ::chmod(p.c_str(), 0020); 412 perms(false, false, false, false, true, false, false, false, false); 413 414 ::chmod(p.c_str(), 0200); 415 perms(false, true, false, false, false, false, false, false, false); 416 417 ::chmod(p.c_str(), 0004); 418 perms(false, false, false, false, false, false, true, false, false); 419 420 ::chmod(p.c_str(), 0040); 421 perms(false, false, false, true, false, false, false, false, false); 422 423 ::chmod(p.c_str(), 0400); 424 perms(true, false, false, false, false, false, false, false, false); 425 426 ::chmod(p.c_str(), 0644); 427 perms(true, true, false, true, false, false, true, false, false); 428 429 ::chmod(p.c_str(), 0755); 430 perms(true, true, true, true, false, true, true, false, true); 431 432 ::chmod(p.c_str(), 0777); 433 perms(true, true, true, true, true, true, true, true, true); 434 435 #undef perms 436 } 437 438 // ------------------------------------------------------------------------ 439 // Test cases for the free functions. 440 // ------------------------------------------------------------------------ 441 442 ATF_TEST_CASE(exists); 443 ATF_TEST_CASE_HEAD(exists) 444 { 445 set_md_var("descr", "Tests the exists function"); 446 } 447 ATF_TEST_CASE_BODY(exists) 448 { 449 using atf::fs::exists; 450 using atf::fs::path; 451 452 create_files(); 453 454 ATF_REQUIRE( exists(path("files"))); 455 ATF_REQUIRE(!exists(path("file"))); 456 ATF_REQUIRE(!exists(path("files2"))); 457 458 ATF_REQUIRE( exists(path("files/."))); 459 ATF_REQUIRE( exists(path("files/.."))); 460 ATF_REQUIRE( exists(path("files/dir"))); 461 ATF_REQUIRE( exists(path("files/reg"))); 462 ATF_REQUIRE(!exists(path("files/foo"))); 463 } 464 465 ATF_TEST_CASE(is_executable); 466 ATF_TEST_CASE_HEAD(is_executable) 467 { 468 set_md_var("descr", "Tests the is_executable function"); 469 } 470 ATF_TEST_CASE_BODY(is_executable) 471 { 472 using atf::fs::is_executable; 473 using atf::fs::path; 474 475 create_files(); 476 477 ATF_REQUIRE( is_executable(path("files"))); 478 ATF_REQUIRE( is_executable(path("files/."))); 479 ATF_REQUIRE( is_executable(path("files/.."))); 480 ATF_REQUIRE( is_executable(path("files/dir"))); 481 482 ATF_REQUIRE(!is_executable(path("non-existent"))); 483 484 ATF_REQUIRE(!is_executable(path("files/reg"))); 485 ATF_REQUIRE(::chmod("files/reg", 0755) != -1); 486 ATF_REQUIRE( is_executable(path("files/reg"))); 487 } 488 489 ATF_TEST_CASE(remove); 490 ATF_TEST_CASE_HEAD(remove) 491 { 492 set_md_var("descr", "Tests the remove function"); 493 } 494 ATF_TEST_CASE_BODY(remove) 495 { 496 using atf::fs::exists; 497 using atf::fs::path; 498 using atf::fs::remove; 499 500 create_files(); 501 502 ATF_REQUIRE( exists(path("files/reg"))); 503 remove(path("files/reg")); 504 ATF_REQUIRE(!exists(path("files/reg"))); 505 506 ATF_REQUIRE( exists(path("files/dir"))); 507 ATF_REQUIRE_THROW(atf::system_error, remove(path("files/dir"))); 508 ATF_REQUIRE( exists(path("files/dir"))); 509 } 510 511 // ------------------------------------------------------------------------ 512 // Main. 513 // ------------------------------------------------------------------------ 514 515 ATF_INIT_TEST_CASES(tcs) 516 { 517 // Add the tests for the "path" class. 518 ATF_ADD_TEST_CASE(tcs, path_normalize); 519 ATF_ADD_TEST_CASE(tcs, path_is_absolute); 520 ATF_ADD_TEST_CASE(tcs, path_is_root); 521 ATF_ADD_TEST_CASE(tcs, path_branch_path); 522 ATF_ADD_TEST_CASE(tcs, path_leaf_name); 523 ATF_ADD_TEST_CASE(tcs, path_compare_equal); 524 ATF_ADD_TEST_CASE(tcs, path_compare_different); 525 ATF_ADD_TEST_CASE(tcs, path_concat); 526 ATF_ADD_TEST_CASE(tcs, path_to_absolute); 527 ATF_ADD_TEST_CASE(tcs, path_op_less); 528 529 // Add the tests for the "file_info" class. 530 ATF_ADD_TEST_CASE(tcs, file_info_stat); 531 ATF_ADD_TEST_CASE(tcs, file_info_perms); 532 533 // Add the tests for the "directory" class. 534 ATF_ADD_TEST_CASE(tcs, directory_read); 535 ATF_ADD_TEST_CASE(tcs, directory_names); 536 ATF_ADD_TEST_CASE(tcs, directory_file_info); 537 538 // Add the tests for the free functions. 539 ATF_ADD_TEST_CASE(tcs, exists); 540 ATF_ADD_TEST_CASE(tcs, is_executable); 541 ATF_ADD_TEST_CASE(tcs, remove); 542 } 543