2 * Name : test_directory_tree
3 * Author : Chris Koeritz
5 * Tests the directory_tree object on some well-known directories.
7 * Copyright (c) 2001-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
15 #include <basis/functions.h>
16 #include <basis/guards.h>
17 #include <structures/string_array.h>
18 #include <application/hoople_main.h>
19 #include <loggers/critical_events.h>
20 #include <loggers/program_wide_logger.h>
21 #include <filesystem/directory_tree.h>
22 #include <filesystem/filename.h>
23 #include <filesystem/filename_list.h>
24 #include <structures/static_memory_gremlin.h>
25 #include <textual/string_manipulation.h>
26 #include <unit_test/unit_base.h>
28 using namespace application;
29 using namespace basis;
30 using namespace mathematics;
31 using namespace filesystem;
32 using namespace loggers;
33 using namespace structures;
34 using namespace textual;
35 using namespace timely;
36 using namespace unit_test;
38 const bool JUST_SIZES = false;
39 // determines if we'll only compare file size and time.
41 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
43 class test_directory_tree : public virtual unit_base, virtual public application_shell
46 test_directory_tree() : application_shell() {}
47 DEFINE_CLASS_NAME("test_directory_tree");
51 int test_directory_tree::execute()
55 astring path = "/usr/include";
57 // default path for windoze uses an area that should always exist.
58 path = environment::get("COMMONPROGRAMFILES");
61 // process the command line parameters, which are optionally a directory name and
62 // a pattern to use when scanning.
63 if (_global_argc >= 2)
64 path = _global_argv[1];
66 astring pattern = "*";
67 if (_global_argc >= 3)
68 pattern = _global_argv[2];
71 // log(astring("Scanning directory tree at \"") + path + "\"");
72 // log(astring("Using pattern-match \"") + pattern + "\"");
74 directory_tree dir(path, pattern.s());
75 ASSERT_TRUE(dir.good(), "directory_tree construction should succeed and be readable.");
77 dir_tree_iterator *ted = dir.start(directory_tree::prefix);
78 // create our iterator to do a prefix traversal.
80 int depth; // current depth in tree.
81 filename curr; // the current path the iterator is at.
82 string_array files; // the filenames held at the iterator.
84 while (directory_tree::current(*ted, curr, files)) {
85 // we have a good directory to show.
86 directory_tree::depth(*ted, depth);
87 // log(string_manipulation::indentation(depth * 2) + astring("[")
88 // + curr.raw() + "]");
90 for (int i = 0; i < files.length(); i++) names += files[i] + " ";
93 string_manipulation::split_lines(names, split, depth * 2 + 2);
97 // go to the next place.
98 directory_tree::next(*ted);
101 directory_tree::throw_out(ted);
105 // second test group. seek operation.
106 //scan the directory, create some temporary directories and junk filenames
107 //therein, then seek to that location.
112 // third test group. tree comparison operation.
113 // log(astring("Self-comparing directory tree at \"") + path + "\"");
114 // log(astring("Using pattern-match \"") + pattern + "\"");
116 // LOG("reading tree 1.");
117 directory_tree dir(path, pattern.s());
118 ASSERT_TRUE(dir.good(), "the directory should be readable for self-compare");
120 // now read a copy of the tree also.
121 // LOG("reading tree 2.");
122 directory_tree dir2(path, pattern.s());
123 ASSERT_TRUE(dir2.good(), "the directory should read the second time fine too");
125 LOG("comparing the two trees.");
127 directory_tree::compare_trees(dir, dir2, diffs, file_info::EQUAL_CHECKSUM_TIMESTAMP_FILESIZE);
128 LOG(diffs.text_form());
130 ASSERT_FALSE(diffs.elements(), "there should be no differences comparing identical dirs");
134 // fourth test: see if the calculate function works.
135 // log(astring("Calculating sums for tree at \"") + path + "\"");
136 // log(astring("Using pattern-match \"") + pattern + "\"");
138 // LOG("reading tree 1.");
139 directory_tree dir(path, pattern.s());
140 ASSERT_TRUE(dir.good(), "the directory should be readable for checksums");
142 // now read a copy of the tree also.
143 // LOG("reading tree 2.");
144 directory_tree dir2(path, pattern.s());
145 ASSERT_TRUE(dir2.good(), "checksummer should be able to read second time also");
147 // LOG("calculating checksums for tree 1.");
148 ASSERT_TRUE(dir.calculate(JUST_SIZES), "the first checksummer tree can be calculated");
150 // LOG("calculating checksums for tree 2.");
151 ASSERT_TRUE(dir2.calculate(JUST_SIZES), "the second checksummer tree can be calculated");
153 // LOG("comparing the two trees.");
155 directory_tree::compare_trees(dir, dir2, diffs, file_info::EQUAL_CHECKSUM_TIMESTAMP_FILESIZE);
156 //LOG(diffs.text_form());
158 ASSERT_FALSE(diffs.elements(), "no checksummer differences should be seen for identical directories");
162 // fifth test: see if the packing works.
163 // log(astring("Reading tree for packing at \"") + path + "\"");
164 // log(astring("Using pattern-match \"") + pattern + "\"");
166 // LOG("reading tree.");
167 directory_tree dir(path, pattern.s());
168 ASSERT_TRUE(dir.good(), "packer directory should be read");
170 // LOG("calculating checksums for tree.");
171 ASSERT_TRUE(dir.calculate(JUST_SIZES), "the first packer tree can be calculated");
173 byte_array packed_form;
174 int size_packed = dir.packed_size();
175 dir.pack(packed_form);
176 //LOG(a_sprintf("tree became %d abyte array", packed_form.length()));
177 ASSERT_EQUAL(size_packed, packed_form.length(), "packed size should be right");
180 ASSERT_TRUE(dir2.unpack(packed_form), "second tree can be unpacked from the first");
182 // LOG("comparing the two trees.");
184 directory_tree::compare_trees(dir, dir2, diffs, file_info::EQUAL_CHECKSUM_TIMESTAMP_FILESIZE);
185 //LOG(diffs.text_form());
187 ASSERT_FALSE(diffs.elements(), "identical directories should stay same after packing");
189 directory_tree::compare_trees(dir2, dir, diffs, file_info::EQUAL_CHECKSUM_TIMESTAMP_FILESIZE);
190 ASSERT_FALSE(diffs.elements(), "no differences for reverse compare identical dirs");
194 // sixth test: see if the make_directories function works.
195 LOG("reading tree to recreate");
196 directory_tree dir(path, pattern.s());
197 ASSERT_TRUE(dir.good(), "makedirs test directory reading");
198 filename tmpdir(environment::get("TMP") + "/zz_balfazzaral");
199 LOG(astring("will write to tmp in ") + tmpdir);
200 basis::outcome result = dir.make_directories(tmpdir.raw());
201 ASSERT_EQUAL(result.value(), common::OKAY, "makedirs should succeed");
204 LOG("what happened with that? did it work?");
206 //hmmm: compare the directories with what we expect to be made;
207 // do a dirtree iterator on the path, and make sure each of those exists in the target place.
213 // combine the results of the second test with a comparison like in the
214 // third test. delete all of those temporary files that were added.
215 // rescan tree. make sure that a tree containing the temporaries
216 // when compared with the current post-deletion tree produces a list
217 // that contains all the temporary files and directories.
222 return final_report();
225 HOOPLE_MAIN(test_directory_tree, )