]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/atf/atf-c++/detail/fs_test.cpp
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / contrib / atf / atf-c++ / detail / fs_test.cpp
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 }