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