first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / core / library / tests_filesystem / test_directory_tree.cpp
1 /*
2 *  Name   : test_directory_tree
3 *  Author : Chris Koeritz
4 *  Purpose:
5 *    Tests the directory_tree object on some well-known directories.
6 **
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                               *
13 */
14
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>
27
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;
37
38 const bool JUST_SIZES = false;
39   // determines if we'll only compare file size and time.
40
41 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
42
43 class test_directory_tree : public virtual unit_base, virtual public application_shell
44 {
45 public:
46   test_directory_tree() : application_shell() {}
47   DEFINE_CLASS_NAME("test_directory_tree");
48   int execute();
49 };
50
51 int test_directory_tree::execute()
52 {
53   FUNCDEF("execute");
54
55   astring path = "/usr/include";
56 #ifdef __WIN32__
57   // default path for windoze uses an area that should always exist.
58   path = environment::get("COMMONPROGRAMFILES");
59 #endif
60
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];
65
66   astring pattern = "*";
67   if (_global_argc >= 3)
68     pattern = _global_argv[2];
69
70   {
71 //    log(astring("Scanning directory tree at \"") + path + "\"");
72 //    log(astring("Using pattern-match \"") + pattern + "\"");
73
74     directory_tree dir(path, pattern.s());
75     ASSERT_TRUE(dir.good(), "directory_tree construction should succeed and be readable.");
76
77     dir_tree_iterator *ted = dir.start(directory_tree::prefix);
78       // create our iterator to do a prefix traversal.
79
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.
83
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() + "]");
89       astring names;
90       for (int i = 0; i < files.length(); i++) names += files[i] + " ";
91       if (names.length()) {
92         astring split;
93         string_manipulation::split_lines(names, split, depth * 2 + 2);
94 //        log(split);
95       }
96
97       // go to the next place.
98       directory_tree::next(*ted);
99     }
100
101     directory_tree::throw_out(ted);
102   }
103
104   {
105     // second test group.  seek operation.
106 //scan the directory, create some temporary directories and junk filenames
107 //therein, then seek to that location.
108
109   }
110
111   {
112     // third test group.  tree comparison operation.
113 //    log(astring("Self-comparing directory tree at \"") + path + "\"");
114 //    log(astring("Using pattern-match \"") + pattern + "\"");
115
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");
119
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");
124
125 //    LOG("comparing the two trees.");
126     filename_list diffs;
127     directory_tree::compare_trees(dir, dir2, diffs, file_info::EQUAL_CHECKSUM_TIMESTAMP_FILESIZE);
128 //LOG(diffs.text_form());
129
130     ASSERT_FALSE(diffs.elements(), "there should be no differences comparing identical dirs");
131   }
132
133   {
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 + "\"");
137
138 //    LOG("reading tree 1.");
139     directory_tree dir(path, pattern.s());
140     ASSERT_TRUE(dir.good(), "the directory should be readable for checksums");
141
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");
146
147 //    LOG("calculating checksums for tree 1.");
148     ASSERT_TRUE(dir.calculate(JUST_SIZES), "the first checksummer tree can be calculated");
149
150 //    LOG("calculating checksums for tree 2.");
151     ASSERT_TRUE(dir2.calculate(JUST_SIZES), "the second checksummer tree can be calculated");
152
153 //    LOG("comparing the two trees.");
154     filename_list diffs;
155     directory_tree::compare_trees(dir, dir2, diffs, file_info::EQUAL_CHECKSUM_TIMESTAMP_FILESIZE);
156 //LOG(diffs.text_form());
157
158     ASSERT_FALSE(diffs.elements(), "no checksummer differences should be seen for identical directories");
159   }
160
161   {
162     // fifth test: see if the packing works.
163 //    log(astring("Reading tree for packing at \"") + path + "\"");
164 //    log(astring("Using pattern-match \"") + pattern + "\"");
165
166 //    LOG("reading tree.");
167     directory_tree dir(path, pattern.s());
168     ASSERT_TRUE(dir.good(), "packer directory should be read");
169
170 //    LOG("calculating checksums for tree.");
171     ASSERT_TRUE(dir.calculate(JUST_SIZES), "the first packer tree can be calculated");
172
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");
178
179     directory_tree dir2;
180     ASSERT_TRUE(dir2.unpack(packed_form), "second tree can be unpacked from the first");
181
182 //    LOG("comparing the two trees.");
183     filename_list diffs;
184     directory_tree::compare_trees(dir, dir2, diffs, file_info::EQUAL_CHECKSUM_TIMESTAMP_FILESIZE);
185 //LOG(diffs.text_form());
186
187     ASSERT_FALSE(diffs.elements(), "identical directories should stay same after packing");
188
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");
191   }
192
193 // nth test:
194 // combine the results of the second test with a comparison like in the
195 // third test.  delete all of those temporary files that were added.
196 // rescan tree. make sure that a tree containing the temporaries
197 // when compared with the current post-deletion tree produces a list
198 // that contains all the temporary files and directories.
199
200
201 //hmmm: more tests!
202
203   return final_report();
204 }
205
206 HOOPLE_MAIN(test_directory_tree, )
207