fs_test.cpp revision 256281
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 30extern "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 48static 49void 50create_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 69ATF_TEST_CASE(path_normalize); 70ATF_TEST_CASE_HEAD(path_normalize) 71{ 72 set_md_var("descr", "Tests the path's normalization"); 73} 74ATF_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 94ATF_TEST_CASE(path_is_absolute); 95ATF_TEST_CASE_HEAD(path_is_absolute) 96{ 97 set_md_var("descr", "Tests the path::is_absolute function"); 98} 99ATF_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 111ATF_TEST_CASE(path_is_root); 112ATF_TEST_CASE_HEAD(path_is_root) 113{ 114 set_md_var("descr", "Tests the path::is_root function"); 115} 116ATF_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 128ATF_TEST_CASE(path_branch_path); 129ATF_TEST_CASE_HEAD(path_branch_path) 130{ 131 set_md_var("descr", "Tests the path::branch_path function"); 132} 133ATF_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 144ATF_TEST_CASE(path_leaf_name); 145ATF_TEST_CASE_HEAD(path_leaf_name) 146{ 147 set_md_var("descr", "Tests the path::leaf_name function"); 148} 149ATF_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 160ATF_TEST_CASE(path_compare_equal); 161ATF_TEST_CASE_HEAD(path_compare_equal) 162{ 163 set_md_var("descr", "Tests the comparison for equality between paths"); 164} 165ATF_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 177ATF_TEST_CASE(path_compare_different); 178ATF_TEST_CASE_HEAD(path_compare_different) 179{ 180 set_md_var("descr", "Tests the comparison for difference between paths"); 181} 182ATF_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 195ATF_TEST_CASE(path_concat); 196ATF_TEST_CASE_HEAD(path_concat) 197{ 198 set_md_var("descr", "Tests the concatenation of multiple paths"); 199} 200ATF_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 210ATF_TEST_CASE(path_to_absolute); 211ATF_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} 216ATF_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 246ATF_TEST_CASE(path_op_less); 247ATF_TEST_CASE_HEAD(path_op_less) 248{ 249 set_md_var("descr", "Tests that the path's less-than operator works"); 250} 251ATF_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 267ATF_TEST_CASE(directory_read); 268ATF_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} 273ATF_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 288ATF_TEST_CASE(directory_file_info); 289ATF_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} 294ATF_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 319ATF_TEST_CASE(directory_names); 320ATF_TEST_CASE_HEAD(directory_names) 321{ 322 set_md_var("descr", "Tests the directory's names method"); 323} 324ATF_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 344ATF_TEST_CASE(file_info_stat); 345ATF_TEST_CASE_HEAD(file_info_stat) 346{ 347 set_md_var("descr", "Tests the file_info creation and its basic contents"); 348} 349ATF_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 369ATF_TEST_CASE(file_info_perms); 370ATF_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} 375ATF_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 445ATF_TEST_CASE(exists); 446ATF_TEST_CASE_HEAD(exists) 447{ 448 set_md_var("descr", "Tests the exists function"); 449} 450ATF_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 468ATF_TEST_CASE(is_executable); 469ATF_TEST_CASE_HEAD(is_executable) 470{ 471 set_md_var("descr", "Tests the is_executable function"); 472} 473ATF_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 492ATF_TEST_CASE(remove); 493ATF_TEST_CASE_HEAD(remove) 494{ 495 set_md_var("descr", "Tests the remove function"); 496} 497ATF_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 518ATF_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