t_symtab.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : test_symbol_table                                                 *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *******************************************************************************
00007 * Copyright (c) 1994-$now By Author.  This program is free software; you can  *
00008 * redistribute it and/or modify it under the terms of the GNU General Public  *
00009 * License as published by the Free Software Foundation; either version 2 of   *
00010 * the License or (at your option) any later version.  This is online at:      *
00011 *     http://www.fsf.org/copyleft/gpl.html                                    *
00012 * Please send any updates to: fred@gruntose.com                               *
00013 \*****************************************************************************/
00014 
00015 #include <basis/byte_array.h>
00016 #include <basis/guards.h>
00017 #include <basis/istring.h>
00018 #include <data_struct/matrix.cpp>
00019 #include <data_struct/symbol_table.cpp>
00020 #include <mechanisms/time_stamp.h>
00021 #include <loggers/console_logger.h>
00022 #include <data_struct/static_memory_gremlin.h>
00023 #include <textual/string_manipulation.h>
00024 
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 
00028 //#define DEBUG_SYMBOL_TABLE
00029   // uncomment for noisy version.
00030 
00031 using namespace basis;  // pull in the auto compare functions.
00032 
00033 //const int test_iterations = 1000;
00034 const int test_iterations = 20;
00035 
00036 const int FIND_ITERATIONS = 100;
00037 const int MAXIMUM_RANDOM_ADDS = 200;
00038 
00039 console_logger out;
00040 
00041 #ifdef DEBUG_SYMBOL_TABLE
00042   #define LOG(to_print) { out.log(to_print); fflush(0); }
00043 #endif
00044 
00045 HOOPLE_STARTUP_CODE;
00046 
00047 #define WHERE __WHERE__.s()
00048 
00049 //#define OLD_TEST
00050   // uncomment for the older version of symbol table.
00051 
00052 double time_in_add = 0;
00053 double time_in_dep_find = 0;
00054 double time_in_new_find = 0;
00055 double time_in_pack = 0;
00056 double time_in_unpack = 0;
00057 double time_in_copy = 0;
00058 
00059 class my_table_def : public symbol_table<byte_array>
00060 {
00061 public:
00062   bool operator == (const my_table_def &to_compare) const {
00063     if (symbols() != to_compare.symbols()) return false;
00064     for (int i = 0; i < symbols(); i++) {
00065       if (name(i) != to_compare.name(i)) return false;
00066       if (operator [](i) != to_compare[i]) return false;
00067     }
00068     return true;
00069   }
00070 };
00071 
00072 void ADD(my_table_def &syms, const istring &name, const istring &to_add)
00073 {
00074   byte_array to_stuff(to_add.length() + 1, (byte *)to_add.s());
00075   time_stamp start;
00076   outcome added = syms.add(name, to_stuff);
00077   if (added == common::EXISTING)
00078     deadly_error(WHERE, "ADD", "already in table");
00079   time_stamp end;
00080   time_in_add += end.value() - start.value();
00081   start.reset();
00082 #ifdef OLD_TEST
00083   int indy = syms.find(name);
00084   if (negative(indy))
00085     deadly_error(WHERE, "ADD", "not in table after add");
00086   end.reset();
00087   time_in_dep_find += end.value() - start.value();
00088   const byte_array *found = &syms[indy];
00089 #else
00090   byte_array *found = syms.find(name);
00091   if (!found)
00092     deadly_error(WHERE, "ADD", "not in table after add");
00093   end.reset();
00094   time_in_new_find += end.value() - start.value();
00095 #endif
00096   if (*found != to_stuff)
00097     deadly_error(WHERE, "ADD", "wrong value in table after add");
00098 }
00099 
00100 void FIND(my_table_def &syms, const istring &name, const istring &to_add)
00101 {
00102   byte_array to_stuff(to_add.length() + 1, (byte *)to_add.s());
00103   for (int i = 0; i < FIND_ITERATIONS; i++) {
00104     time_stamp start;
00105 #ifdef OLD_TEST
00106     // double the calls so we roughly match the other test.
00107     int indy = syms.find(name);
00108     if (negative(indy)) deadly_error(WHERE, "FIND", "not in table");
00109     indy = syms.find(name);
00110     if (negative(indy)) deadly_error(WHERE, "FIND", "not in table");
00111     byte_array *found = &syms[indy];
00112     time_stamp end;
00113     time_in_dep_find += end.value() - start.value();
00114 #else
00115     int indy = syms.dep_find(name);
00116     if (negative(indy)) deadly_error(WHERE, "FIND", "not in table (dep_find)");
00117     time_stamp end;
00118     time_in_dep_find += end.value() - start.value();
00119     start.reset();
00120     byte_array *found = syms.find(name);
00121     if (!found) deadly_error(WHERE, "FIND", "not in table (new_find)");
00122     end.reset();
00123     time_in_new_find += end.value() - start.value();
00124 #endif
00125   }
00126 }
00127 
00128 void pack(byte_array &packed_form, const my_table_def &to_pack)
00129 {
00130   attach(packed_form, to_pack.symbols());
00131   istring name;
00132   byte_array content;
00133   for (int i = 0; i < to_pack.symbols(); i++) {
00134     to_pack.retrieve(i, name, content);
00135     name.pack(packed_form);
00136     attach(packed_form, content);
00137   }
00138 }
00139 
00140 bool unpack(byte_array &packed_form, my_table_def &to_unpack)
00141 {
00142   to_unpack.reset();
00143   int syms = 0;
00144   if (!detach(packed_form, syms)) return false;
00145   istring name;
00146   byte_array chunk;
00147   for (int i = 0; i < syms; i++) {
00148     if (!name.unpack(packed_form)) return false;
00149     if (!detach(packed_form, chunk)) return false;
00150     ADD(to_unpack, name, (char *)chunk.observe());
00151   }
00152   return true;
00153 }
00154 
00156 
00157 my_table_def creatapose()
00158 {
00159   my_table_def to_return;
00160   istring name;
00161   istring content;
00162   for (int y = 0; y < MAXIMUM_RANDOM_ADDS; y++) {
00163     name = string_manipulation::make_random_name(40, 108);
00164     content = string_manipulation::make_random_name(300, 1000);
00165     byte_array to_stuff(content.length() + 1, (byte *)content.s());
00166     to_return.add(name, to_stuff);
00167   }
00168   return to_return;
00169 }
00170 
00172 
00173 void test_byte_table()
00174 {
00175   my_table_def syms;
00176   my_table_def new_syms;
00177   my_table_def newer_syms;
00178   for (int qq = 0; qq < test_iterations; qq++) {
00179     syms.reset();  // still could be costly.
00180 #ifdef DEBUG_SYMBOL_TABLE
00181     LOG(istring(istring::SPRINTF, "index %d", qq));
00182 #endif
00183     istring freudname("blurgh");
00184     istring freud("Sigmund Freud was a very freaked dude.");
00185     ADD(syms, freudname, freud);
00186     istring borgname("borg");
00187     istring borg("You will be assimilated.");
00188     ADD(syms, borgname, borg);
00189     istring xname("X-Men");
00190     istring x("The great unknown superhero cartoon.");
00191     ADD(syms, xname, x);
00192     istring aname("fleeny-brickle");
00193     istring a("lallax menick publum.");
00194     ADD(syms, aname, a);
00195     istring axname("ax");
00196     istring ax("Lizzy Borden has a very large hatchet.");
00197     ADD(syms, axname, ax);
00198     istring bloinkname("urg.");
00199     istring bloink("this is a short and stupid string");
00200     ADD(syms, bloinkname, bloink);
00201     istring faxname("fax");
00202     istring fax("alligators in my teacup.");
00203     ADD(syms, faxname, fax);
00204     istring zname("eagle ovaries");
00205     istring z("malfeasors beware");
00206     ADD(syms, zname, z);
00207 
00208     FIND(syms, freudname, freud);
00209     FIND(syms, borgname, borg);
00210     FIND(syms, xname, x);
00211     FIND(syms, aname, a);
00212     FIND(syms, axname, ax);
00213     FIND(syms, bloinkname, bloink);
00214     FIND(syms, faxname, fax);
00215     FIND(syms, zname, z);
00216 
00217     istring name;
00218     istring content;
00219     for (int y = 0; y < MAXIMUM_RANDOM_ADDS; y++) {
00220       name = string_manipulation::make_random_name(40, 108);
00221       content = string_manipulation::make_random_name(300, 1000);
00222       ADD(syms, name, content);
00223       FIND(syms, name, content);
00224     }
00225 
00226     // test copying the table.
00227     time_stamp start;  // click, on.
00228     my_table_def copy1(syms);
00229     {
00230       my_table_def joe(copy1);
00231       my_table_def joe2 = joe;
00232       if (joe2 != joe)
00233         deadly_error(WHERE, "copy test A", "different symbol tables");
00234       my_table_def joe3 = creatapose();  // on stack.
00235       my_table_def joe4 = joe3;
00236       my_table_def joe5 = joe4;
00237       if (joe5 != joe3) 
00238         deadly_error(WHERE, "copy test A2", "different symbol tables");
00239     }
00240     if (! (syms == copy1) )
00241       deadly_error(WHERE, "copy test B", "different symbol tables");
00242     time_stamp end;
00243     time_in_copy += end.value() - start.value();
00244 
00245 #ifdef DEBUG_SYMBOL_TABLE
00247     LOG("now packing the symbol table...");
00248 #endif
00249 
00250 #ifdef DEBUG_SYMBOL_TABLE
00251     LOG("now unpacking from packed form");
00252 #endif
00253     byte_array packed_form;
00254     pack(packed_form, syms);
00255     if (!unpack(packed_form, new_syms))
00256       deadly_error(WHERE, "unpack test", "failed to unpack");
00257 
00258 #ifdef DEBUG_SYMBOL_TABLE
00260 #endif
00261     if (! (syms == new_syms) )
00262       deadly_error(WHERE, "unpacked test", "different symbol tables");
00263 
00264 #ifdef DEBUG_SYMBOL_TABLE
00265     LOG("now deleting old symbol table...");
00266 #endif
00268 
00269 #ifdef DEBUG_SYMBOL_TABLE
00271     LOG("packing the symbol table again...");
00272 #endif
00273     byte_array packed_again(0);
00274     start.reset();  // click, on.
00275     pack(packed_again, new_syms);
00276     end.reset();  // click, off.
00277     time_in_pack += end.value() - start.value();
00278 #ifdef DEBUG_SYMBOL_TABLE
00279     LOG("now unpacking from packed form again...");
00280 #endif
00281     start = time_stamp();
00282     unpack(packed_again, newer_syms);
00283     end = time_stamp();
00284     time_in_unpack += end.value() - start.value();
00285 #ifdef DEBUG_SYMBOL_TABLE
00287 #endif
00288     if (new_syms != newer_syms)
00289       deadly_error(WHERE, "unpacked test", "different symbol tables");
00290 
00291 #ifdef DEBUG_SYMBOL_TABLE
00292     LOG("now deleting new and newer symbol table...");
00293 #endif
00294   }
00295 }
00296 
00298 
00299 // jethro is a simple object for containment below.
00300 class jethro
00301 {
00302 public:
00303   istring _truck;
00304 
00305   bool operator ==(const jethro &tc) const { return tc._truck == _truck; }
00306   bool operator !=(const jethro &tc) const { return !(*this == tc); }
00307 };
00308 
00310 
00311 // the test_content object is an object with proper copy constructor
00312 // and assignment operator that also has deep contents.
00313 class test_content
00314 {
00315 public:
00316   int _q;
00317   istring _ted;
00318   istring _jed;
00319   int_array _ned;
00320   matrix<jethro> _med;
00321 
00322   test_content() : _q(9) {}
00323 
00324   test_content(const istring &ted, const istring &jed) : _q(4), _ted(ted),
00325           _jed(jed) {}
00326 
00327   bool operator ==(const test_content &tc) const {
00328     if (tc._q != _q) return false;
00329     if (tc._ted != _ted) return false;
00330     if (tc._jed != _jed) return false;
00331     if (tc._ned.length() != _ned.length()) return false;
00332     for (int i = 0; i < _ned.length(); i++)
00333       if (tc._ned[i] != _ned[i]) return false;
00334     
00335     if (tc._med.rows() != _med.rows()) return false;
00336     if (tc._med.columns() != _med.columns()) return false;
00337     for (int c = 0; c < _med.columns(); c++)
00338       for (int r = 0; r < _med.rows(); r++)
00339         if (tc._med.get(r, c) != _med.get(r, c)) return false;
00340 
00341     return true;
00342   }
00343   bool operator !=(const test_content &tc) const { return !operator ==(tc); }
00344 
00345   operator int() const { return _q; }
00346 };
00347 
00349 
00350 class second_table_def : public symbol_table<test_content>
00351 {
00352 public:
00353   bool operator == (const second_table_def &to_compare) {
00354     if (symbols() != to_compare.symbols()) return false;
00355     for (int i = 0; i < symbols(); i++) {
00356       if ((*this)[i] != to_compare[i]) return false;
00357     }
00358     return true;
00359   }
00360   bool operator != (const second_table_def &to_compare)
00361       { return !(*this == to_compare); }
00362 };
00363 
00364 void ADD2(second_table_def &syms, const istring &name,
00365     const test_content &to_add)
00366 { 
00367   time_stamp start;
00368   outcome added = syms.add(name, to_add);
00369   if (added == common::EXISTING)
00370     deadly_error(WHERE, "ADD2", "already in table");
00371   time_stamp end;
00372   time_in_add += end.value() - start.value();
00373   start = time_stamp();  // reset start.
00374 #ifdef OLD_TEST
00375   int indy = syms.find(name);
00376   if (negative(indy))
00377     deadly_error(WHERE, "ADD2", "not found after add");
00378   // refind to balance timing.
00379   indy = syms.find(name);
00380   if (negative(indy))
00381     deadly_error(WHERE, "ADD2", "not found after add");
00382   end = time_stamp();  // reset end.
00383   time_in_dep_find += end.value() - start.value();
00384 #else
00385   int indy = syms.dep_find(name);
00386   if (negative(indy))
00387     deadly_error(WHERE, "ADD2", "not found after add");
00388   end = time_stamp();  // reset end.
00389   time_in_dep_find += end.value() - start.value();
00390   start = time_stamp();
00391   test_content *found = syms.find(name);
00392   if (!found)
00393     deadly_error(WHERE, "ADD2", "not found after add");
00394   end = time_stamp();  // reset end.
00395   time_in_new_find += end.value() - start.value();
00396 #endif
00397   istring name_out;
00398   test_content content_out;
00399   if (syms.retrieve(indy, name_out, content_out) != common::OKAY) {
00400     if (name_out != name)
00401       deadly_error(WHERE, "ADD2", "name is incorrect after retrieve");
00402     if (content_out != to_add)
00403       deadly_error(WHERE, "ADD2", "content is incorrect after retrieve");
00404   }
00405 }
00406 
00408 
00409 void test_tc_table()
00410 {
00411   second_table_def syms;
00412   second_table_def new_syms;
00413   second_table_def newer_syms;
00414   for (int qq = 0; qq < test_iterations; qq++) {
00415     syms.reset();
00416 #ifdef DEBUG_SYMBOL_TABLE
00417     LOG(istring(istring::SPRINTF, "index %d", qq));
00418 #endif
00419     istring freudname("blurgh");
00420     test_content freud("Sigmund Freud was a very freaked dude.", "flutenorf");
00421     ADD2(syms, freudname, freud);
00422     istring borgname("borg");
00423     test_content borg("You will be assimilated.", "alabaster");
00424     ADD2(syms, borgname, borg);
00425     istring xname("X-Men");
00426     test_content x("The great unknown superhero cartoon.", "somnambulist");
00427     ADD2(syms, xname, x);
00428     istring aname("fleeny-brickle");
00429     test_content a("lallax menick publum.", "aglos bagnort pavlod");
00430     ADD2(syms, aname, a);
00431     istring axname("ax");
00432     test_content ax("Lizzy Borden has a very large hatchet.", "chop");
00433     ADD2(syms, axname, ax);
00434     istring bloinkname("urg.");
00435     test_content bloink("this is a short and stupid string", "not that short");
00436     ADD2(syms, bloinkname, bloink);
00437     istring faxname("fax");
00438     test_content fax("alligators in my teacup.", "lake placid");
00439     ADD2(syms, faxname, fax);
00440     istring zname("eagle ovaries");
00441     test_content z("malfeasors beware", "endangered");
00442     ADD2(syms, zname, z);
00443 
00444     // test copying the table.
00445     time_stamp start;
00446     second_table_def copy1(syms);
00447     {
00448       second_table_def joe(copy1);
00449       second_table_def joe2 = joe;
00450       if (joe2 != joe)
00451         deadly_error(WHERE, "copy test C", "different symbol tables");
00452     }
00453     if (! (syms == copy1) )
00454       deadly_error(WHERE, "copy test D", "different symbol tables");
00455     time_stamp end;
00456     time_in_copy += end.value() - start.value();
00457 
00458 /* need packing support on jethro or whatever.
00459 #ifdef DEBUG_SYMBOL_TABLE
00460     LOG(istring(istring::SPRINTF,"This is the symbol table before any manipulation\n%s", syms->text_form()));
00461     LOG("now packing the symbol table...");
00462 #endif
00463 
00464 #ifdef DEBUG_SYMBOL_TABLE
00465     LOG("now unpacking from packed form");
00466 #endif
00467     byte_array packed_form;
00468     syms->pack(packed_form);
00469     new_syms->unpack(packed_form);
00470 #ifdef DEBUG_SYMBOL_TABLE
00471     LOG(istring(istring::SPRINTF, "unpacked form has:\n%s", new_syms->text_form().s()));
00472 #endif
00473     if (! (*syms == *new_syms) )
00474       deadly_error(WHERE, "unpacked test", "different symbol tables");
00475 
00476 #ifdef DEBUG_SYMBOL_TABLE
00477     LOG("now deleting old symbol table...");
00478 #endif
00479     delete syms;
00480 
00481 #ifdef DEBUG_SYMBOL_TABLE
00482     LOG(istring(istring::SPRINTF, "got the unpacked form, and dumping it:\n%s", new_syms->text_form().s()));
00483     LOG("packing the symbol table again...");
00484 #endif
00485     byte_array packed_again(0);
00486     new_syms->pack(packed_again);
00487 #ifdef DEBUG_SYMBOL_TABLE
00488     LOG("now unpacking from packed form again...");
00489 #endif
00490     newer_syms->unpack(packed_again);
00491 #ifdef DEBUG_SYMBOL_TABLE
00492     LOG(istring(istring::SPRINTF, "got the unpacked form, and dumping it:\n%s", newer_syms->text_form().s()));
00493 #endif
00494     if (*new_syms != *newer_syms)
00495       deadly_error(WHERE, "unpacked test", "different symbol tables");
00496 
00497 #ifdef DEBUG_SYMBOL_TABLE
00498     LOG("now deleting new and newer symbol table...");
00499 #endif
00500     delete new_syms;
00501     delete newer_syms;
00502 */
00503   }
00504 }
00505 
00507 
00508 int main(int formal(argc), char *formal(argv)[])
00509 {
00510   out.log(istring("starting test 1: ") + timestamp(true, true));
00511   test_byte_table();
00512   out.log(istring("done test 1: ") + timestamp(true, true));
00513   out.log(istring("starting test 2: ") + timestamp(true, true));
00514   test_tc_table();
00515   out.log(istring("done test 2: ") + timestamp(true, true));
00516 
00517   out.log(istring(istring::SPRINTF, "time in add=%f", time_in_add));
00518   out.log(istring(istring::SPRINTF, "time in dep_find=%f", time_in_dep_find));
00519   out.log(istring(istring::SPRINTF, "time in new_find=%f", time_in_new_find));
00520   out.log(istring(istring::SPRINTF, "time in pack=%f", time_in_pack));
00521   out.log(istring(istring::SPRINTF, "time in unpack=%f", time_in_unpack));
00522 
00523   guards::alert_message("symbol_table:: works for those functions tested.");
00524   return 0;
00525 }
00526 

Generated on Fri Nov 21 04:30:08 2008 for HOOPLE Libraries by  doxygen 1.5.1