1 /*****************************************************************************\
3 * Name : test_string_table *
4 * Author : Chris Koeritz *
6 *******************************************************************************
7 * Copyright (c) 1994-$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 \*****************************************************************************/
15 #include <basis/byte_array.h>
16 #include <basis/guards.h>
17 #include <basis/astring.h>
18 #include <structures/matrix.h>
19 #include <structures/string_table.h>
20 #include <timely/time_stamp.h>
21 #include <loggers/console_logger.h>
22 #include <structures/static_memory_gremlin.h>
23 #include <textual/string_manipulation.h>
24 #include <application/hoople_main.h>
25 #include <unit_test/unit_base.h>
30 using namespace application;
31 using namespace basis;
32 ///using namespace configuration;
33 using namespace mathematics;
34 using namespace filesystem;
35 using namespace loggers;
36 using namespace structures;
37 using namespace textual;
38 using namespace timely;
39 using namespace unit_test;
41 //#define DEBUG_SYMBOL_TABLE
42 // uncomment to get lots of noise out of base class.
44 //#define DEBUG_STRING_TABLE
45 // uncomment for noisy version.
47 //#define TEST_SIZE_TABLE
48 // uncomment for testing the size of a string_table.
51 // uncomment for the older version of symbol table.
53 const int test_iterations = 25;
55 const int FIND_ITERATIONS = 20;
56 const int MAXIMUM_RANDOM_ADDS = 50;
58 const int TEST_SIZE_TABLE_COUNT = 10000;
59 // the number of string_table elements we create for checking how
60 // big one of them is.
62 #define LOG(to_print) EMERGENCY_LOG(program_wide_logger::get(), astring(to_print))
64 double time_in_add = 0;
65 double time_in_find = 0;
66 double time_in_pack = 0;
67 double time_in_unpack = 0;
68 basis::un_int operations = 0;
70 class test_string_table : public virtual application_shell, public virtual unit_base
73 test_string_table() {}
74 DEFINE_CLASS_NAME("test_string_table");
76 void ADD(string_table &syms, const astring &name, const astring &to_add);
77 void FIND(const string_table &syms, const astring &name, const astring &to_find);
81 virtual int execute();
86 void test_string_table::ADD(string_table &syms, const astring &name, const astring &to_add)
89 //LOG(astring("add of ") + name + " => " + to_add);
91 outcome added = syms.add(name, to_add);
93 ASSERT_INEQUAL(added.value(), common::EXISTING, "should not already be in table");
95 time_in_add += end.value() - start.value();
98 void test_string_table::FIND(const string_table &syms, const astring &name, const astring &to_find)
101 for (int i = 0; i < FIND_ITERATIONS; i++) {
103 astring *found = syms.find(name);
106 time_in_find += end.value() - start.value();
107 ASSERT_TRUE(found, "should be in table");
108 ASSERT_EQUAL(*found, to_find, "string in table should be correct");
114 void test_string_table::test_1()
116 FUNCDEF("test_string_table");
117 #ifdef TEST_SIZE_TABLE
119 array<string_table> symso(TEST_SIZE_TABLE_COUNT);
121 guards::alert_message(astring(astring::SPRINTF, "we should effectively "
122 "have swamped out the size of other code in the program now. the size "
123 "should represent %d string_table instantiations. take the current "
124 "memory size (minus maybe 2 megs) and divide by %d and you will have "
125 "a fairly accurate cost for instantiating a string table. hit a key.",
126 TEST_SIZE_TABLE_COUNT, TEST_SIZE_TABLE_COUNT));
129 #elif defined(__UNIX__)
136 string_table new_syms;
137 string_table newer_syms;
139 for (int qq = 0; qq < test_iterations; qq++) {
140 syms.reset(); // still could be costly.
142 #ifdef DEBUG_STRING_TABLE
143 LOG(astring(astring::SPRINTF, "index %d", qq));
145 astring freudname("blurgh");
146 astring freud("Sigmund Freud was a very freaked dude.");
147 ADD(syms, freudname, freud);
148 astring borgname("borg");
149 astring borg("You will be assimilated.");
150 ADD(syms, borgname, borg);
151 astring xname("X-Men");
152 astring x("The great unknown superhero cartoon.");
154 astring aname("fleeny-brickle");
155 astring a("lallax menick publum.");
157 astring axname("ax");
158 astring ax("Lizzy Borden has a very large hatchet.");
159 ADD(syms, axname, ax);
160 astring bloinkname("urg.");
161 astring bloink("this is a short and stupid string");
162 ADD(syms, bloinkname, bloink);
163 astring faxname("fax");
164 astring fax("alligators in my teacup.");
165 ADD(syms, faxname, fax);
166 astring zname("eagle ovaries");
167 astring z("malfeasors beware");
170 FIND(syms, freudname, freud);
171 FIND(syms, borgname, borg);
172 FIND(syms, xname, x);
173 FIND(syms, aname, a);
174 FIND(syms, axname, ax);
175 FIND(syms, bloinkname, bloink);
176 FIND(syms, faxname, fax);
177 FIND(syms, zname, z);
181 for (int y = 0; y < MAXIMUM_RANDOM_ADDS; y++) {
182 name = string_manipulation::make_random_name(40, 108);
183 content = string_manipulation::make_random_name(300, 1000);
184 ADD(syms, name, content);
185 FIND(syms, name, content);
188 // test copying of the string tables.
189 string_table chronos = syms;
192 string_table mary = syms;
194 string_table june = mary;
196 ASSERT_TRUE(mary == syms, "copy test should compare properly");
199 ASSERT_TRUE(syms == chronos, "copy test original should not be harmed");
203 // test the bug we think we found in the operator =.
205 fred.add("urp", "rarp");
206 fred.add("hyurgh", "ralph");
208 med.add("urp", "rarp");
209 med.add("hyurgh", "ralph");
210 fred = med; // the deadly assignment.
211 fred = med; // the deadly assignment.
212 fred = med; // the deadly assignment.
213 fred = med; // the deadly assignment.
214 fred.add("urp", "rarp");
215 fred.add("gurp", "flaarp"); // a new entry.
216 astring *urp = fred.find("urp");
217 astring *hyurgh = fred.find("hyurgh");
218 ASSERT_TRUE(urp, "urp should not go missing");
219 ASSERT_TRUE(hyurgh, "hyurgh should not go missing");
220 #ifdef DEBUG_STRING_TABLE
221 LOG(astring("got urp as ") + (urp? *urp : "empty!!!!"));
222 LOG(astring("got hyurgh as ") + (hyurgh? *hyurgh : "empty!!!!"));
224 astring urp_val = fred[0];
225 // AH HA! this one finds it. accessing via bracket or other methods
226 // that use the internal get() method will fail.
227 // if there is no outright crash, then the bug is gone.
228 #ifdef DEBUG_STRING_TABLE
229 LOG(astring("got urp_val as ") + (urp_val.t()? urp_val : "empty!!!!"));
233 #ifdef DEBUG_STRING_TABLE
234 //// LOG(astring(astring::SPRINTF,"This is the symbol table before any manipulation\n%s", syms.text_form()));
235 LOG("now packing the symbol table...");
237 byte_array packed_form;
239 syms.pack(packed_form);
242 time_in_pack += end.value() - start.value();
243 #ifdef DEBUG_STRING_TABLE
244 LOG("now unpacking from packed form");
247 ASSERT_TRUE(new_syms.unpack(packed_form), "unpack test should succeed in unpacking");
249 end.reset(); // click, off.
250 time_in_unpack += end.value() - start.value();
252 #ifdef DEBUG_STRING_TABLE
253 /// LOG(astring(astring::SPRINTF, "unpacked form has:\n%s", new_syms->text_form().s()));
255 ASSERT_FALSE(! (syms == new_syms), "unpacked test symbol tables should be same");
258 #ifdef DEBUG_STRING_TABLE
259 LOG("now deleting old symbol table...");
262 #ifdef DEBUG_STRING_TABLE
263 /// LOG(astring(astring::SPRINTF, "got the unpacked form, and dumping it:\n%s", new_syms->text_form().s()));
264 LOG("packing the symbol table again...");
266 byte_array packed_again(0);
267 start.reset(); // click, on.
268 new_syms.pack(packed_again);
270 end.reset(); // click, off.
271 time_in_pack += end.value() - start.value();
272 #ifdef DEBUG_STRING_TABLE
273 LOG("now unpacking from packed form again...");
275 start = time_stamp();
276 newer_syms.unpack(packed_again);
279 time_in_unpack += end.value() - start.value();
280 #ifdef DEBUG_STRING_TABLE
281 LOG(astring(astring::SPRINTF, "got the unpacked form, and dumping "
282 "it:\n%s", newer_syms.text_form().s()));
284 ASSERT_TRUE(new_syms == newer_syms, "unpacked test should not be different symbol tables");
287 #ifdef DEBUG_STRING_TABLE
288 LOG("now deleting new and newer symbol table...");
295 int test_string_table::execute()
297 #ifdef DEBUG_STRING_TABLE
298 LOG(astring("starting test: ") + time_stamp::notarize(false));
301 #ifdef DEBUG_STRING_TABLE
302 LOG(astring("done test: ") + time_stamp::notarize(false));
303 LOG(astring(astring::SPRINTF, "time in add=%f", time_in_add));
304 LOG(astring(astring::SPRINTF, "time in find=%f", time_in_find));
305 LOG(astring(astring::SPRINTF, "time in pack=%f", time_in_pack));
306 LOG(astring(astring::SPRINTF, "time in unpack=%f", time_in_unpack));
307 LOG(astring(astring::SPRINTF, "total operations=%u", operations));
310 return final_report();
313 HOOPLE_MAIN(test_string_table, )