fs_test.cpp revision 275988
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 28extern "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 45static 46void 47create_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 66ATF_TEST_CASE(path_normalize); 67ATF_TEST_CASE_HEAD(path_normalize) 68{ 69 set_md_var("descr", "Tests the path's normalization"); 70} 71ATF_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 91ATF_TEST_CASE(path_is_absolute); 92ATF_TEST_CASE_HEAD(path_is_absolute) 93{ 94 set_md_var("descr", "Tests the path::is_absolute function"); 95} 96ATF_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 108ATF_TEST_CASE(path_is_root); 109ATF_TEST_CASE_HEAD(path_is_root) 110{ 111 set_md_var("descr", "Tests the path::is_root function"); 112} 113ATF_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 125ATF_TEST_CASE(path_branch_path); 126ATF_TEST_CASE_HEAD(path_branch_path) 127{ 128 set_md_var("descr", "Tests the path::branch_path function"); 129} 130ATF_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 141ATF_TEST_CASE(path_leaf_name); 142ATF_TEST_CASE_HEAD(path_leaf_name) 143{ 144 set_md_var("descr", "Tests the path::leaf_name function"); 145} 146ATF_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 157ATF_TEST_CASE(path_compare_equal); 158ATF_TEST_CASE_HEAD(path_compare_equal) 159{ 160 set_md_var("descr", "Tests the comparison for equality between paths"); 161} 162ATF_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 174ATF_TEST_CASE(path_compare_different); 175ATF_TEST_CASE_HEAD(path_compare_different) 176{ 177 set_md_var("descr", "Tests the comparison for difference between paths"); 178} 179ATF_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 192ATF_TEST_CASE(path_concat); 193ATF_TEST_CASE_HEAD(path_concat) 194{ 195 set_md_var("descr", "Tests the concatenation of multiple paths"); 196} 197ATF_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 207ATF_TEST_CASE(path_to_absolute); 208ATF_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} 213ATF_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 243ATF_TEST_CASE(path_op_less); 244ATF_TEST_CASE_HEAD(path_op_less) 245{ 246 set_md_var("descr", "Tests that the path's less-than operator works"); 247} 248ATF_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 264ATF_TEST_CASE(directory_read); 265ATF_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} 270ATF_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 285ATF_TEST_CASE(directory_file_info); 286ATF_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} 291ATF_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 316ATF_TEST_CASE(directory_names); 317ATF_TEST_CASE_HEAD(directory_names) 318{ 319 set_md_var("descr", "Tests the directory's names method"); 320} 321ATF_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 341ATF_TEST_CASE(file_info_stat); 342ATF_TEST_CASE_HEAD(file_info_stat) 343{ 344 set_md_var("descr", "Tests the file_info creation and its basic contents"); 345} 346ATF_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 366ATF_TEST_CASE(file_info_perms); 367ATF_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} 372ATF_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 442ATF_TEST_CASE(exists); 443ATF_TEST_CASE_HEAD(exists) 444{ 445 set_md_var("descr", "Tests the exists function"); 446} 447ATF_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 465ATF_TEST_CASE(is_executable); 466ATF_TEST_CASE_HEAD(is_executable) 467{ 468 set_md_var("descr", "Tests the is_executable function"); 469} 470ATF_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 489ATF_TEST_CASE(remove); 490ATF_TEST_CASE_HEAD(remove) 491{ 492 set_md_var("descr", "Tests the remove function"); 493} 494ATF_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 515ATF_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