feisty meow concerns codebase 2.140
test_string_table.cpp
Go to the documentation of this file.
1/*****************************************************************************\
2* *
3* Name : test_string_table *
4* Author : Chris Koeritz *
5* *
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\*****************************************************************************/
14
15#include <basis/byte_array.h>
16#include <basis/guards.h>
17#include <basis/astring.h>
18#include <structures/matrix.h>
20#include <timely/time_stamp.h>
25#include <unit_test/unit_base.h>
26
27#include <stdio.h>
28#include <stdlib.h>
29
30using namespace application;
31using namespace basis;
33using namespace mathematics;
34using namespace filesystem;
35using namespace loggers;
36using namespace structures;
37using namespace textual;
38using namespace timely;
39using namespace unit_test;
40
41//#define DEBUG_SYMBOL_TABLE
42 // uncomment to get lots of noise out of base class.
43
44//#define DEBUG_STRING_TABLE
45 // uncomment for noisy version.
46
47//#define TEST_SIZE_TABLE
48 // uncomment for testing the size of a string_table.
49
50//#define OLD_TEST
51 // uncomment for the older version of symbol table.
52
53const int test_iterations = 25;
54
55const int FIND_ITERATIONS = 20;
56const int MAXIMUM_RANDOM_ADDS = 50;
57
58const int TEST_SIZE_TABLE_COUNT = 10000;
59 // the number of string_table elements we create for checking how
60 // big one of them is.
61
62#define LOG(to_print) EMERGENCY_LOG(program_wide_logger::get(), astring(to_print))
63
64double time_in_add = 0;
65double time_in_find = 0;
66double time_in_pack = 0;
67double time_in_unpack = 0;
69
70class test_string_table : public virtual application_shell, public virtual unit_base
71{
72public:
73 test_string_table() {}
74 DEFINE_CLASS_NAME("test_string_table");
75
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);
78
79 void test_1();
80
81 virtual int execute();
82};
83
85
86void test_string_table::ADD(string_table &syms, const astring &name, const astring &to_add)
87{
88 FUNCDEF("ADD")
89//LOG(astring("add of ") + name + " => " + to_add);
90 time_stamp start;
91 outcome added = syms.add(name, to_add);
92 operations++;
93 ASSERT_INEQUAL(added.value(), common::EXISTING, "should not already be in table");
94 time_stamp end;
95 time_in_add += end.value() - start.value();
96}
97
98void test_string_table::FIND(const string_table &syms, const astring &name, const astring &to_find)
99{
100 FUNCDEF("FIND")
101 for (int i = 0; i < FIND_ITERATIONS; i++) {
102 time_stamp start;
103 astring *found = syms.find(name);
104 operations++;
105 time_stamp end;
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");
109 }
110}
111
113
114void test_string_table::test_1()
115{
116 FUNCDEF("test_string_table");
117#ifdef TEST_SIZE_TABLE
118 {
120 operations++;
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.",
127 #ifdef _CONSOLE
128 getchar();
129 #elif defined(__UNIX__)
130 getchar();
131 #endif
132 }
133#endif
134
135 string_table syms;
136 string_table new_syms;
137 string_table newer_syms;
138 operations += 3;
139 for (int qq = 0; qq < test_iterations; qq++) {
140 syms.reset(); // still could be costly.
141 operations++;
142#ifdef DEBUG_STRING_TABLE
143 LOG(astring(astring::SPRINTF, "index %d", qq));
144#endif
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.");
153 ADD(syms, xname, x);
154 astring aname("fleeny-brickle");
155 astring a("lallax menick publum.");
156 ADD(syms, aname, a);
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");
168 ADD(syms, zname, z);
169
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);
178
180 astring content;
181 for (int y = 0; y < MAXIMUM_RANDOM_ADDS; y++) {
183 content = string_manipulation::make_random_name(300, 1000);
184 ADD(syms, name, content);
185 FIND(syms, name, content);
186 }
187
188 // test copying of the string tables.
189 string_table chronos = syms;
190 operations++;
191 {
192 string_table mary = syms;
193 operations++;
194 string_table june = mary;
195 operations++;
196 ASSERT_TRUE(mary == syms, "copy test should compare properly");
197 operations++;
198 }
199 ASSERT_TRUE(syms == chronos, "copy test original should not be harmed");
200 operations++;
201
202 {
203 // test the bug we think we found in the operator =.
204 string_table fred;
205 fred.add("urp", "rarp");
206 fred.add("hyurgh", "ralph");
207 string_table med;
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!!!!"));
223#endif
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!!!!"));
230#endif
231 }
232
233#ifdef DEBUG_STRING_TABLE
235 LOG("now packing the symbol table...");
236#endif
237 byte_array packed_form;
238 time_stamp start;
239 syms.pack(packed_form);
240 operations++;
241 time_stamp end;
242 time_in_pack += end.value() - start.value();
243#ifdef DEBUG_STRING_TABLE
244 LOG("now unpacking from packed form");
245#endif
246 start.reset();
247 ASSERT_TRUE(new_syms.unpack(packed_form), "unpack test should succeed in unpacking");
248 operations++;
249 end.reset(); // click, off.
250 time_in_unpack += end.value() - start.value();
251
252#ifdef DEBUG_STRING_TABLE
254#endif
255 ASSERT_FALSE(! (syms == new_syms), "unpacked test symbol tables should be same");
256 operations++;
257
258#ifdef DEBUG_STRING_TABLE
259 LOG("now deleting old symbol table...");
260#endif
261
262#ifdef DEBUG_STRING_TABLE
264 LOG("packing the symbol table again...");
265#endif
266 byte_array packed_again(0);
267 start.reset(); // click, on.
268 new_syms.pack(packed_again);
269 operations++;
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...");
274#endif
275 start = time_stamp();
276 newer_syms.unpack(packed_again);
277 operations++;
278 end = time_stamp();
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()));
283#endif
284 ASSERT_TRUE(new_syms == newer_syms, "unpacked test should not be different symbol tables");
285 operations++;
286
287#ifdef DEBUG_STRING_TABLE
288 LOG("now deleting new and newer symbol table...");
289#endif
290 }
291}
292
294
295int test_string_table::execute()
296{
297#ifdef DEBUG_STRING_TABLE
298 LOG(astring("starting test: ") + time_stamp::notarize(false));
299#endif
300 test_1();
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));
308#endif
309
310 return final_report();
311}
312
313HOOPLE_MAIN(test_string_table, )
314
#define ADD(name, value)
#define FIND(name, value)
The application_shell is a base object for console programs.
virtual int execute()=0
< retrieves the command line from the /proc hierarchy on linux.
Represents a sequential, ordered, contiguous collection of objects.
Definition array.h:54
Provides a dynamically resizable ASCII character string.
Definition astring.h:35
bool t() const
t() is a shortcut for the string being "true", as in non-empty.
Definition astring.h:97
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
Definition astring.h:113
int find(char to_find, int position=0, bool reverse=false) const
Locates "to_find" in "this".
Definition astring.cpp:577
A very common template for a dynamic array of bytes.
Definition byte_array.h:36
the "common" class defines our common_outcomes.
Outcomes describe the state of completion for an operation.
Definition outcome.h:31
Provides a symbol_table that holds strings as the content.
virtual bool unpack(basis::byte_array &packed_form)
Restores the packable from the "packed_form".
basis::astring text_form() const
prints the contents of the table into the returned string.
virtual void pack(basis::byte_array &packed_form) const
Creates a packed form of the packable object in "packed_form".
contents * find(const basis::astring &name) const
returns the contents held for "name" or NULL_POINTER if it wasn't found.
basis::outcome add(const basis::astring &name, const contents &storage)
Enters a symbol name into the table along with some contents.
static basis::astring make_random_name(int min=1, int max=64)
creates a random name, where the letters are between 'a' and 'z'.
Represents a point in time relative to the operating system startup time.
Definition time_stamp.h:38
static basis::astring notarize(bool add_space=true)
a useful method for getting a textual version of the time "right now".
void reset()
sets the stamp time back to now.
time_representation value() const
returns the time_stamp in terms of the lower level type.
Definition time_stamp.h:61
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
Definition enhance_cpp.h:42
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition enhance_cpp.h:54
Provides macros that implement the 'main' program of an application.
#define HOOPLE_MAIN(obj_name, obj_args)
options that should work for most unix and linux apps.
Definition hoople_main.h:61
Implements an application lock to ensure only one is running at once.
The guards collection helps in testing preconditions and reporting errors.
Definition array.h:30
unsigned int un_int
Abbreviated name for unsigned integers.
Definition definitions.h:62
A platform independent way to obtain the timestamp of a file.
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
Definition averager.h:21
A dynamic container class that holds any kind of object via pointers.
Definition amorph.h:55
#include <time.h>
Useful support functions for unit testing, especially within hoople.
Definition unit_base.cpp:35
double time_in_find
double time_in_unpack
double time_in_pack
const int test_iterations
const int MAXIMUM_RANDOM_ADDS
basis::un_int operations
#define LOG(to_print)
double time_in_add
const int TEST_SIZE_TABLE_COUNT
const int FIND_ITERATIONS
#define ASSERT_EQUAL(a, b, test_name)
Definition unit_base.h:38
#define ASSERT_TRUE(a, test_name)
Definition unit_base.h:46
#define ASSERT_FALSE(a, test_name)
Definition unit_base.h:50
#define ASSERT_INEQUAL(a, b, test_name)
Definition unit_base.h:42