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>
21 #include <loggers/console_logger.h>
25 #include <unit_test/unit_base.h>
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 
30 using namespace application;
31 using namespace basis;
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;
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 
53 const int test_iterations = 25;
54 
55 const int FIND_ITERATIONS = 20;
56 const int MAXIMUM_RANDOM_ADDS = 50;
57 
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.
61 
62 #define LOG(to_print) EMERGENCY_LOG(program_wide_logger::get(), astring(to_print))
63 
64 double time_in_add = 0;
65 double time_in_find = 0;
66 double time_in_pack = 0;
67 double time_in_unpack = 0;
69 
70 class test_string_table : public virtual application_shell, public virtual unit_base
71 {
72 public:
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 
86 void 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 
98 void 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 
114 void 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 
179  astring name;
180  astring content;
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);
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 
295 int 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 
313 HOOPLE_MAIN(test_string_table, )
314 
#define ADD(name, value)
Definition: base_address.h:94
#define FIND(name, value)
Definition: base_address.h:80
The application_shell is a base object for console programs.
Represents a sequential, ordered, contiguous collection of objects.
Definition: array.h:54
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
Definition: astring.h:113
bool t() const
t() is a shortcut for the string being "true", as in non-empty.
Definition: astring.h:97
int find(char to_find, int position=0, bool reverse=false) const
Locates "to_find" in "this".
Definition: astring.cpp:574
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.
Definition: string_table.h:32
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.
Definition: symbol_table.h:313
basis::outcome add(const basis::astring &name, const contents &storage)
Enters a symbol name into the table along with some contents.
Definition: symbol_table.h:383
Represents a point in time relative to the operating system startup time.
Definition: time_stamp.h:38
void reset()
sets the stamp time back to now.
Definition: time_stamp.cpp:59
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:45
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:57
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.
Definition: byte_filer.cpp:37
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>
Definition: earth_time.cpp:37
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