2 // Name : test_packable_tree
3 // Author : Chris Koeritz
5 // Copyright (c) 1992-$now By Author. This program is free software; you can
6 // redistribute it and/or modify it under the terms of the GNU General Public
7 // License as published by the Free Software Foundation:
8 // http://www.gnu.org/licenses/gpl.html
9 // or under the terms of the GNU Library license:
10 // http://www.gnu.org/licenses/lgpl.html
11 // at your preference. Those licenses describe your legal rights to this
12 // software, and no other rights or warranties apply.
13 // Please send updates for this code to: fred@gruntose.com -- Thanks, fred.
16 //! tests some critical properties for the packable tree.
18 #include <application/hoople_main.h>
19 #include <basis/astring.h>
20 #include <basis/enhance_cpp.h>
21 #include <basis/functions.h>
22 #include <basis/guards.h>
23 #include <filesystem/file_info.h>
24 #include <loggers/critical_events.h>
25 #include <loggers/file_logger.h>
26 #include <mathematics/chaos.h>
27 #include <nodes/packable_tree.h>
28 #include <structures/object_packers.h>
29 #include <structures/string_array.h>
30 #include <structures/static_memory_gremlin.h>
31 #include <textual/byte_formatter.h>
32 #include <textual/string_manipulation.h>
33 #include <timely/earth_time.h>
34 #include <timely/time_stamp.h>
35 #include <unit_test/unit_base.h>
41 using namespace application;
42 using namespace basis;
43 using namespace filesystem;
44 using namespace loggers;
45 using namespace mathematics;
46 using namespace nodes;
47 using namespace structures;
48 using namespace textual;
49 using namespace timely;
50 using namespace unit_test;
52 //#define DEBUG_PACKABLE_TREE
53 // set this to enable debugging features of the string class.
55 //HOOPLE_STARTUP_CODE;
57 //#define DEBUG_PACKABLE_TREE_TEST
58 // uncomment for testing version.
60 #define LOG(s) EMERGENCY_LOG(program_wide_logger::get(), s)
62 #define WHERE __WHERE__.s()
64 #define FUNKIT(str) basis::a_sprintf("%s: %s", func, basis::astring(str).s())
66 // test: reports an error if the condition evaluates to non-zero.
68 const float TEST_RUNTIME_DEFAULT = .02 * MINUTE_ms;
69 // the test, by default, will run for this long.
73 class test_packable_tree : public application_shell, public unit_base
76 test_packable_tree() {}
77 ~test_packable_tree() {}
79 DEFINE_CLASS_NAME("test_packable_tree");
81 virtual int execute() {
83 return final_report();
89 HOOPLE_MAIN(test_packable_tree, )
93 //! it's not the one tree (c). this is just a derived packable_tree we can test with.
95 class many_tree : public packable_tree
98 many_tree(const file_info &inf) : c_inf(new file_info(inf)) {}
100 virtual ~many_tree() { WHACK(c_inf); }
102 file_info get_info() const { return *c_inf; }
104 virtual int packed_size() const {
105 return c_inf->packed_size();
108 virtual void pack(basis::byte_array &packed_form) const {
109 c_inf->pack(packed_form);
112 virtual bool unpack(basis::byte_array &packed_form) {
113 if (!c_inf->unpack(packed_form)) return false;
124 //! the factory that creates our special type of tree.
126 class tree_defacto : public packable_tree_factory
129 packable_tree *create() { return new many_tree(file_info()); }
134 void test_packable_tree::run_test()
138 const file_info farfle(filename("arf"), 2010);
139 const file_info empty;
140 const file_info snood(filename("wookie"), 8888);
143 // simple creation, packing, unpacking, destruction tests on a blank object.
144 many_tree gruntcake(farfle);
145 byte_array packed_form;
146 int pack_guess = gruntcake.packed_size();
147 gruntcake.pack(packed_form);
148 ASSERT_EQUAL(pack_guess, packed_form.length(), FUNKIT("packed length is incorrect"));
149 many_tree untbake_target(empty);
150 ASSERT_TRUE(untbake_target.unpack(packed_form), FUNKIT("unpack operation failed"));
151 ASSERT_EQUAL(untbake_target.get_info(), gruntcake.get_info(),
152 FUNKIT("unpack had wrong contents"));
156 // recursive packing tests...
158 many_tree *spork = new many_tree(farfle);
159 many_tree *limpet = new many_tree(empty);
160 many_tree *congo = new many_tree(snood);
161 many_tree *dworkin = new many_tree(empty);
162 many_tree *greep = new many_tree(farfle);
164 many_tree *flep = new many_tree(snood);
165 many_tree *glug = new many_tree(empty);
166 many_tree *aptitoot = new many_tree(farfle);
168 many_tree *grog = new many_tree(snood);
169 // connect first to second.
171 flep->attach(limpet);
173 aptitoot->attach(dworkin);
174 aptitoot->attach(greep);
175 // connect second to third.
178 grog->attach(aptitoot);
180 // now recursively pack that bad boy three level tree.
182 int size_guess = grog->recursive_packed_size();
183 grog->recursive_pack(packed);
184 ASSERT_EQUAL(size_guess, packed.length(), "recursive_packed_size failed");
185 tree_defacto factotum;
186 packable_tree *unpacked = many_tree::recursive_unpack(packed, factotum);
187 ASSERT_TRUE(unpacked, "recursive_unpack failed");
188 ASSERT_TRUE(dynamic_cast<many_tree *>(unpacked), "recursive_unpack has wrong type");
189 many_tree *survivor = dynamic_cast<many_tree *>(unpacked);