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>
44 using namespace application;
45 using namespace basis;
46 using namespace filesystem;
47 using namespace loggers;
48 using namespace mathematics;
49 using namespace nodes;
50 using namespace structures;
51 using namespace textual;
52 using namespace timely;
53 using namespace unit_test;
55 //#define DEBUG_PACKABLE_TREE
56 // set this to enable debugging features of the string class.
58 //HOOPLE_STARTUP_CODE;
60 //#define DEBUG_PACKABLE_TREE_TEST
61 // uncomment for testing version.
63 #define LOG(s) EMERGENCY_LOG(program_wide_logger::get(), s)
65 #define WHERE __WHERE__.s()
67 #define FUNKIT(str) basis::a_sprintf("%s: %s", func, basis::astring(str).s())
69 // test: reports an error if the condition evaluates to non-zero.
71 const float TEST_RUNTIME_DEFAULT = .02 * MINUTE_ms;
72 // the test, by default, will run for this long.
76 class test_packable_tree : public application_shell, public unit_base
79 test_packable_tree() {}
80 ~test_packable_tree() {}
82 DEFINE_CLASS_NAME("test_packable_tree");
84 virtual int execute() {
86 return final_report();
92 HOOPLE_MAIN(test_packable_tree, )
96 //! it's not the one tree (c). this is just a derived packable_tree we can test with.
98 class many_tree : public packable_tree
101 many_tree(const file_info &inf) : c_inf(new file_info(inf)) {}
103 virtual ~many_tree() { WHACK(c_inf); }
105 file_info get_info() const { return *c_inf; }
107 virtual int packed_size() const {
108 return c_inf->packed_size();
111 virtual void pack(basis::byte_array &packed_form) const {
112 c_inf->pack(packed_form);
115 virtual bool unpack(basis::byte_array &packed_form) {
116 if (!c_inf->unpack(packed_form)) return false;
127 //! the factory that creates our special type of tree.
129 class tree_defacto : public packable_tree_factory
132 packable_tree *create() { return new many_tree(file_info()); }
137 void test_packable_tree::run_test()
141 const file_info farfle(filename("arf"), 2010);
142 const file_info empty;
143 const file_info snood(filename("wookie"), 8888);
146 // simple creation, packing, unpacking, destruction tests on a blank object.
147 many_tree gruntcake(farfle);
148 byte_array packed_form;
149 int pack_guess = gruntcake.packed_size();
150 gruntcake.pack(packed_form);
151 ASSERT_EQUAL(pack_guess, packed_form.length(), FUNKIT("packed length is incorrect"));
152 many_tree untbake_target(empty);
153 ASSERT_TRUE(untbake_target.unpack(packed_form), FUNKIT("unpack operation failed"));
154 ASSERT_EQUAL(untbake_target.get_info(), gruntcake.get_info(),
155 FUNKIT("unpack had wrong contents"));
159 // recursive packing tests...
161 many_tree *spork = new many_tree(farfle);
162 many_tree *limpet = new many_tree(empty);
163 many_tree *congo = new many_tree(snood);
164 many_tree *dworkin = new many_tree(empty);
165 many_tree *greep = new many_tree(farfle);
167 many_tree *flep = new many_tree(snood);
168 many_tree *glug = new many_tree(empty);
169 many_tree *aptitoot = new many_tree(farfle);
171 many_tree *grog = new many_tree(snood);
172 // connect first to second.
174 flep->attach(limpet);
176 aptitoot->attach(dworkin);
177 aptitoot->attach(greep);
178 // connect second to third.
181 grog->attach(aptitoot);
183 // now recursively pack that bad boy three level tree.
185 int size_guess = grog->recursive_packed_size();
186 grog->recursive_pack(packed);
187 ASSERT_EQUAL(size_guess, packed.length(), "recursive_packed_size failed");
188 tree_defacto factotum;
189 packable_tree *unpacked = many_tree::recursive_unpack(packed, factotum);
190 ASSERT_TRUE(unpacked, "recursive_unpack failed");
191 ASSERT_TRUE(dynamic_cast<many_tree *>(unpacked), "recursive_unpack has wrong type");
192 many_tree *survivor = dynamic_cast<many_tree *>(unpacked);