t_amorph.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : test_byte_array_amorph                                            *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *  Purpose:                                                                   *
00007 *                                                                             *
00008 *    Puts the amorph object through its paces.                                *
00009 *                                                                             *
00010 *******************************************************************************
00011 * Copyright (c) 2000-$now By Author.  This program is free software; you can  *
00012 * redistribute it and/or modify it under the terms of the GNU General Public  *
00013 * License as published by the Free Software Foundation; either version 2 of   *
00014 * the License or (at your option) any later version.  This is online at:      *
00015 *     http://www.fsf.org/copyleft/gpl.html                                    *
00016 * Please send any updates to: fred@gruntose.com                               *
00017 \*****************************************************************************/
00018 
00019 #define DEBUG_ARRAY
00020   // uncomment to enable array debugging.
00021 
00022 #define DEBUG_AMORPH
00023   // uncomment to enable amorph debugging.
00024 
00025 //#define DEBUG_TEST_AMORPH
00026   // uncomment for this program to be noisier.
00027 
00028 #ifdef DEBUG_TEST_AMORPH
00029   #define LOG(to_print) EMERGENCY_LOG(program_wide_logger(), to_print)
00030 #else
00031   #define LOG(to_print) {}
00032 #endif
00033 
00034 #include "bogon.cpp"
00035   // definition of bogon class and the amorph of bogons.
00036 
00037 #include <basis/chaos.h>
00038 #include <basis/function.h>
00039 #include <basis/guards.h>
00040 #include <data_struct/amorph.cpp>
00041 #include <mechanisms/time_stamp.h>
00042 #include <loggers/file_logger.h>
00043 #include <data_struct/static_memory_gremlin.h>
00044 
00045 #include <memory.h>
00046 #include <stdlib.h>
00047 
00048 using namespace basis;
00049 
00050 HOOPLE_STARTUP_CODE;
00051 
00052 #define static_class_name() "t_amorph"
00053 
00054 const int default_test_iterations = 28;
00055 
00056 const int MAX_LIMBS = 200;
00057   // the highest number of items stored in the amorphs here.
00058 
00059 const int MIN_CHUBBY = 60;
00060   // the smallest chunk to allocate for storing text strings...  all strings
00061   // must therefore be shorter than this length.
00062 const int MAX_RANDO = 275;
00063   // the maximum amount of space to add when allocating a randomly sized chunk.
00064 
00065 #define PROGRAM_NAME "test_amorph"
00066 
00067 int compare(amorph<byte_array> &one, amorph<byte_array> &two)
00068 {
00069   FUNCDEF("compare amorph<byte_array>");
00070   if (one.elements() != two.elements()) return false;
00071   if (one.valid_fields() != two.valid_fields()) return false;
00072   for (int i = 0; i < one.elements(); i++) {
00073     if (!one.get(i) && !two.get(i)) continue;
00074     else if (!one.get(i) || !two.get(i)) {
00075       continuable_error(PROGRAM_NAME, func,
00076           istring(istring::SPRINTF, "one nil, one not, at %d!", i).s());
00077       return false;
00078     } else if (one.get(i)->length() != two.get(i)->length()) {
00079       continuable_error(PROGRAM_NAME, func,
00080           istring(istring::SPRINTF, "unequal sizes at %d!", i).s());
00081       return false;
00082     } else if (one.get(i)->length() > 0) {
00083       if (one[i]->observe() == two[i]->observe()) {
00084         continuable_error(PROGRAM_NAME, func,
00085             istring(istring::SPRINTF, "pointer in use twice at %d!", i).s());
00086         return false;
00087       }
00088       if (memcmp(one[i]->observe(), two[i]->observe(), one[i]->length())) {
00089         continuable_error(PROGRAM_NAME, func,
00090             istring(istring::SPRINTF, "unequal contents at %d!", i).s());
00091         LOG(istring(istring::SPRINTF, "a has: %s", one[i]->observe()));
00092         LOG(istring(istring::SPRINTF, "b has: %s", two[i]->observe()));
00093         return false;
00094       }
00095     }
00096   }
00097   return true;
00098 }
00099 
00100 struct blob_hold { int size; int offset; };
00101 #define PACK_BLOB_SIZE(max_limbs) (max_limbs * sizeof(blob_hold))
00102 
00103 byte_array fake_pack(amorph<byte_array> &me)
00104 {
00105   // snagged from the packable_amorph pack function!
00106   // count the whole size needed to store the amorph.
00107   int amo_size = 0;
00108   amorph<byte_array> hold_packed_bits(me.elements());
00109 
00110   for (int i = 0; i < me.elements(); i++)
00111     if (me.get(i) && me.get(i)->length()) {
00112       byte_array packed_item;
00113       attach(packed_item, *me[i]);
00114       byte_array *to_stuff = new byte_array(packed_item);
00115       hold_packed_bits.put(i, to_stuff);
00116       amo_size += packed_item.length();
00117     }
00118   int len = amo_size + sizeof(int) + PACK_BLOB_SIZE(me.elements());
00119 
00120   // allocate a storage area for the packed form.
00121   byte_array to_return(len);
00122   int temp = me.elements();
00123   object_assign((int *)to_return.access(), &temp);
00124     // size of package is stored at the beginning of the memory.
00125 
00126   int current_offset = sizeof(int);
00127   // the indices into the packed form are located after the amorph header.
00128   blob_hold *blob_array = (blob_hold *)(to_return.access() + current_offset);
00129   current_offset += PACK_BLOB_SIZE(me.elements());
00130 
00131   // the entire amorph is replicated into the new buffer.
00132   for (int j = 0; j < me.elements(); j++) {
00133     // the offset of this limb in the packed area is saved in the hold.
00134     blob_array[j].size
00135       = (hold_packed_bits[j]? hold_packed_bits[j]->length() : 0);
00136     blob_array[j].offset = current_offset;
00137     if (hold_packed_bits[j] && hold_packed_bits[j]->length()) {
00138       // the actual data is copied....
00139       memory_assign(to_return.access() + current_offset,
00140             (byte *)hold_packed_bits[j]->observe(),
00141             hold_packed_bits[j]->length());
00142       // and the "address" is updated.
00143       current_offset += hold_packed_bits[j]->length();
00144     }
00145   }
00146   if (current_offset != len)
00147     deadly_error(static_class_name(), "pack", "offset is incorrect after packing");
00148   return to_return;
00149 }
00150 
00151 amorph<byte_array> *fake_amorph_unpack(byte_array &packed_amorph)
00152 {
00153   // snagged from the packable_amorph unpack function!
00154   int max_limbs;
00155   object_assign(&max_limbs, (int *)packed_amorph.access());
00156   amorph<byte_array> *to_return = new amorph<byte_array>(max_limbs);
00157 
00158   blob_hold *blob_array = new blob_hold[max_limbs];
00159   memory_assign(blob_array, (blob_hold *)(packed_amorph.access()
00160      + sizeof(int)), PACK_BLOB_SIZE(max_limbs));
00161   for (int i = 0; i < to_return->elements(); i++)
00162     if (blob_array[i].size) {
00163       byte *source = packed_amorph.access() + blob_array[i].offset;
00164       byte_array packed_byte_array(blob_array[i].size, source);
00165       byte_array *unpacked = new byte_array;
00166       detach(packed_byte_array, *unpacked);
00167       to_return->put(i, unpacked);
00168     }
00169   delete [] blob_array;
00170   return to_return;
00171 }
00172 
00173 void test_byte_array_amorph()
00174 {
00175   FUNCDEF("test_byte_array_amorph");
00176   LOG("start of amorph of byte array test");
00177   for (int qq = 0; qq < default_test_iterations; qq++) {
00178     LOG(istring(istring::SPRINTF, "index %d", qq));
00179     {
00180       // some simple creation and stuffing tests....
00181       amorph<byte_array> fred(20);
00182       amorph<byte_array> gen(10);
00183       for (int i=0; i < 10; i++)  {
00184         byte_array *gens = new byte_array(8, (byte *)"goodbye");
00185         gen.put(i, gens);
00186       }
00187       for (int j = 0; j < 20; j++)  {
00188         byte_array *freds = new byte_array(6, (byte *)"hello");
00189          fred.put(j, freds);
00190       }
00191       amorph_assign(gen, fred);
00192       LOG("done with fred & gen");
00193     }
00194 
00195     LOG("before fred creation");
00196     chaos randomizer;
00197     amorph<byte_array> fred(MAX_LIMBS - 1);
00198     fred.append(NIL);  // add one to make it max limbs big.
00199     LOG("after append nil");
00200     {
00201       for (int i = 0; i < fred.elements(); i++) {
00202         int size = MIN_CHUBBY + randomizer.inclusive(0, MAX_RANDO);
00203         istring text("bogus burfonium nuggets");
00204         istring burph(istring::SPRINTF, " ung %d ", i);
00205         text += burph;
00206         byte *temp = new byte[size];
00207         text.stuff((char *)temp, text.length()+1);
00208         byte_array *to_stuff = new byte_array(size, temp);
00209         fred.put(i, to_stuff);
00210         delete [] temp;
00211       }
00212     }
00213     LOG("after first loop");
00214     {
00215       amorph<byte_array> bungee3;
00216       amorph_assign(bungee3, fred);
00217       amorph<byte_array> burglar2;
00218       amorph_assign(burglar2, bungee3);
00219       amorph<byte_array> trunklid;
00220       amorph_assign(trunklid, burglar2);
00221       if (!trunklid.elements())
00222         deadly_error(static_class_name(), "const constructor test", "no elements!");
00223     }
00224     LOG("after copies performed");
00225     {
00226       istring text;
00227       text = "hello this is part one.";
00228       LOG(istring(istring::SPRINTF, "len is %d, content is %s",
00229           text.length(), text.observe()));
00230       char *tadr = text.access();
00231       byte *badr = (byte *)tadr;
00232       byte_array *to_stuff = new byte_array(text.length() + 1, badr);
00233       fred.put(183, to_stuff);
00234       text = "wonky tuniea bellowbop";
00235       byte_array *to_stuff1 = new byte_array(text.length()+1, (byte *)text.s());
00236       fred.put(90, to_stuff1);
00237 
00238       text = "frunkwioioio";
00239       byte_array *to_stuff2 = new byte_array(text.length()+1, (byte *)text.s());
00240       fred.put(12, to_stuff2);
00241 
00242       fred.clear(98); fred.clear(122); fred.clear(123);
00243       fred.clear(256);
00244       fred.clear(129);
00245       fred.zap(82, 90);
00246       fred.zap(93, 107);
00247     }
00248     LOG("after second loop");
00249     {
00250       byte_array packed = fake_pack(fred);
00251       LOG(istring(istring::SPRINTF, "done packing in %s, pack has %d "
00252           "elems.", static_class_name(), packed.length()));
00253       amorph<byte_array> *new_fred = fake_amorph_unpack(packed);
00254       LOG("done unpacking in test_amorph");
00255       if (!compare(fred, *new_fred))
00256         deadly_error(static_class_name(), "first pack test", "amorphs not the same");
00257       byte *cont1
00258         = (new_fred->get(14)? (*new_fred)[14]->access() : (byte *)"NIL");
00259       byte *cont2
00260         = (new_fred->get(20)? (*new_fred)[20]->access() : (byte *)"NIL");
00261       byte *cont3
00262         = (new_fred->get(36)? (*new_fred)[36]->access() : (byte *)"NIL");
00263 
00264       if (cont1) LOG(istring(istring::SPRINTF, "14: %s", cont1));
00265       if (cont2) LOG(istring(istring::SPRINTF, "20: %s", cont2));
00266       if (cont3) LOG(istring(istring::SPRINTF, "36: %s", cont3));
00267       LOG("fields all compare identically after pack and unpack");
00268       byte_array packed_second = fake_pack(*new_fred);
00269       delete new_fred;
00270       amorph<byte_array> *newer_fred = fake_amorph_unpack(packed_second);
00271       if (!compare(*newer_fred, fred))
00272         deadly_error(static_class_name(), "second pack test", "amorphs not the same");
00273       delete newer_fred;
00274     }
00275 
00276     {
00277       amorph<byte_array> fred(randomizer.inclusive(20, 30));
00278       int size = MIN_CHUBBY + randomizer.inclusive(0, MAX_RANDO);
00279       istring text("bogus burfonium nuggets");
00280       istring burph(istring::SPRINTF, " ung %d ", 2314);
00281       text += burph;
00282       byte_array intermed(size);
00283 
00284       for (int i = 0; i < fred.elements(); i += 5) {
00285         byte_array *to_stuff = new byte_array(size, intermed.access());
00286         memory_assign(intermed.access(), (byte *)text.s(), text.length() + 1);
00287         fred.put(i, to_stuff);
00288       }
00289       fred.clear_all();
00290       for (int j = 0; j < fred.elements(); j += 5) {
00291         byte_array *to_stuff = new byte_array(size, intermed.access());
00292         memory_assign(intermed.access(), (byte *)text.s(), text.length() + 1);
00293         fred.put(j, to_stuff);
00294       }
00295       text = "frunkwioioio";
00296       byte_array *to_stuff = new byte_array(text.length()+1, (byte *)text.s());
00297       fred.put(12, to_stuff);
00298       fred.clear_all();
00299     }
00300     LOG("survived the clear_alls");
00301     {
00302       amorph<byte_array> *ted = new amorph<byte_array>(0);
00303       amorph_assign(*ted, fred);
00304       if (!compare(*ted, fred))
00305         deadly_error(static_class_name(), func, "ted and fred aren't the same");
00306       {
00307         amorph<byte_array> *george = new amorph<byte_array>(0);
00308         amorph_assign(*george, fred);
00309         if (!compare(*george, fred))
00310           deadly_error(static_class_name(), func, "fred and george aren't the same");
00311         ted->zap(3, 20);
00312         george->zap(3, 10);
00313         george->zap(3, 12);
00314         if (!compare(*ted, *george))
00315           deadly_error(static_class_name(), "after zap", "ted and george aren't the same");
00316         ted->adjust(ted->elements() - 20);
00317         george->adjust(george->elements() - 5);
00318         george->adjust(george->elements() - 5);
00319         george->adjust(george->elements() - 5);
00320         george->adjust(george->elements() - 5);
00321         if (!compare(*ted, *george))
00322           deadly_error(static_class_name(), "after zap", "ted and george aren't the same");
00323         delete george;
00324       }
00325       delete ted;
00326     }
00327   }
00328 }
00329 
00330 int compare(const amorph<bogon> &one, const amorph<bogon> &two)
00331 {
00332   FUNCDEF("compare amorph<bogon>");
00333   if (one.elements() != two.elements()) return false;
00334   for (int i = 0; i < one.elements(); i++) {
00335     if (!one.get(i) && !two.get(i)) continue;
00336     else if (!one.get(i) || !two.get(i)) {
00337       continuable_error(PROGRAM_NAME, func, istring(istring::SPRINTF, "one nil, one not, at %d!", i).s());
00338       return false;
00339     } else if (one.get(i)->size() != two.get(i)->size()) {
00340       continuable_error(PROGRAM_NAME, func, istring(istring::SPRINTF, "unequal sizes at %d!", i).s());
00341       return false;
00342     } else if (one.get(i)->size() > 0) {
00343       if (one.get(i)->held() == two.get(i)->held()) {
00344         continuable_error(PROGRAM_NAME, func, istring(istring::SPRINTF, "pointer in use twice at %d!", i).s());
00345         return false;
00346       }
00347       if (memcmp(one.get(i)->held(), two.get(i)->held(), one.get(i)->size())) {
00348         continuable_error(PROGRAM_NAME, func, istring(istring::SPRINTF, "unequal contents at %d!", i).s());
00349         return false;
00350       }
00351     }
00352   }
00353   return true;
00354 }
00355 
00356 void test_bogon_amorph()
00357 {
00358   FUNCDEF("test_bogon_amorph");
00359   LOG("start of amorph of bogon test");
00360   for (int qq = 0; qq < default_test_iterations; qq++) {
00361     LOG(istring(istring::SPRINTF, "index %d", qq));
00362     {
00363       // some simple creation and stuffing tests....
00364       amorph<bogon> fred(20);
00365       amorph<bogon> gen(10);
00366       for (int i = 0; i < 10; i++)  {
00367         bogon *gens = new bogon((byte *)"goodbye");
00368         gen.put(i, gens);
00369       }
00370       for (int j = 0; j < 20; j++)  {
00371         bogon *freds = new bogon((byte *)"hello");
00372         fred.put(j, freds);
00373       }
00374       if (compare(fred, gen))
00375         deadly_error(static_class_name(), func, "fred and gen ARE the same");
00376       amorph_assign(gen, fred);
00377       if (!compare(gen, fred))
00378         deadly_error(static_class_name(), func, "gen and fred aren't the same");
00379     }
00380 
00381     chaos randomizer;
00382 
00383     amorph<bogon> fred(MAX_LIMBS);
00384 
00385     LOG("after append nil");
00386     {
00387       for (int i = 0; i < fred.elements(); i++) {
00388         int size = MIN_CHUBBY + randomizer.inclusive(0, MAX_RANDO);
00389         istring text("bogus burfonium nuggets");
00390         istring burph(istring::SPRINTF, " ung %d ", i);
00391         text += burph;
00392         byte *temp = new byte[size];
00393         text.stuff((char *)temp, text.length()+1);
00394         bogon *to_stuff = new bogon(temp);
00395         fred.put(i, to_stuff);
00396         delete [] temp;
00397       }
00398     }
00399 
00400     LOG("after first loop");
00401     {
00402       amorph<bogon> bungee3;
00403       amorph_assign(bungee3, fred);
00404       amorph<bogon> burglar2;
00405       amorph_assign(burglar2, bungee3);
00406       amorph_assign(burglar2, bungee3);
00407       amorph<bogon> trunklid;
00408       amorph_assign(trunklid, burglar2);
00409       if (!trunklid.elements())
00410         deadly_error(static_class_name(), "const constructor test", "no elements!");
00411     }
00412     {
00413       istring text;
00414       text = "hello this is part one.";
00415       bogon *to_stuff = new bogon((byte *)text.s());
00416       fred.put(32, to_stuff);
00417 
00418       text = "wonky tuniea bellowbop";
00419       bogon *to_stuff1 = new bogon((byte *)text.s());
00420       fred.put(84, to_stuff1);
00421 
00422       text = "frunkwioioio";
00423       bogon *to_stuff2 = new bogon((byte *)text.s());
00424       fred.put(27, to_stuff2);
00425 
00426       fred.clear(98); fred.clear(122); fred.clear(123);
00427       fred.clear(256);
00428       fred.clear(129);
00429       fred.zap(82, 90);
00430       fred.zap(93, 107);
00431     }
00432     LOG("after second loop");
00433     {
00434       amorph<bogon> fred(randomizer.inclusive(20, 30));
00435       istring text("bogus burfonium nuggets");
00436       istring burph(istring::SPRINTF, " ung %d ", 2314);
00437       text += burph;
00438 
00439       for (int i = 0; i < fred.elements(); i += 5) {
00440         bogon *to_stuff = new bogon((byte *)text.s());
00441         fred.put(i, to_stuff);
00442       }
00443       fred.clear_all();
00444       for (int j = 0; j < fred.elements(); j += 5) {
00445         bogon *to_stuff = new bogon((byte *)text.s());
00446         fred.put(j, to_stuff);
00447       }
00448       text = "frunkwioioio";
00449       bogon *to_stuff = new bogon((byte *)text.s());
00450       fred.put(6, to_stuff);
00451       fred.clear_all();
00452     }
00453     LOG("survived the clear_alls");
00454     {
00455       amorph<bogon> *ted = new amorph<bogon>();
00456       amorph_assign(*ted, fred);
00457       if (!compare(*ted, fred))
00458         deadly_error(static_class_name(), func, "ted and fred aren't the same");
00459       {
00460         amorph<bogon> *george = new amorph<bogon>();
00461         amorph_assign(*george, fred);
00462         if (!compare(*george, fred))
00463           deadly_error(static_class_name(), func, "fred and george aren't the same");
00464         ted->zap(3, 20);
00465         george->zap(3, 10);
00466         george->zap(3, 12);
00467         if (!compare(*ted, *george))
00468           deadly_error(static_class_name(), "after zap", "ted and george aren't the same");
00469         ted->adjust(ted->elements()-20);
00470         george->adjust(george->elements()-5);
00471         george->adjust(george->elements()-5);
00472         george->adjust(george->elements()-5);
00473         george->adjust(george->elements()-5);
00474         if (!compare(*ted, *george))
00475           deadly_error(static_class_name(), "after zap", "ted and george aren't the same");
00476         delete george;
00477       }
00478       delete ted;
00479     }
00480   }
00481 }
00482 
00483 const int MAX_TEST_DURATION = 1 * MINUTE_ms;
00484   // each of the tests calling on the templated tester will take this long.
00485 
00486 const int MAX_SIMULTANEOUS_OBJECTS = 42;  // the maximum length tested.
00487 
00488 //hmmm: this test_amorph_of is not completed.
00489 
00490 template <class contents>
00491 void test_amorph_of(const contents &bogus)
00492 {
00493   chaos rando;
00494 
00495   // these are the actions we try on the amorph during the test.
00496   // the first and last elements must be identical to the first and last
00497   // tests to perform.
00498   enum actions { first, do_zap = first, do_adjust, do_assign,
00499 
00500 
00501       do_borrow, last = do_borrow};
00502 
00503   time_stamp exit_time(::MAX_TEST_DURATION);
00504   while (time_stamp() < exit_time) {
00505     int index = rando.inclusive(0, ::MAX_SIMULTANEOUS_OBJECTS - 1);
00506     int choice = rando.inclusive(first, last);
00507     switch (choice) {
00508       case do_zap: {
00509 
00510         break;
00511       }
00512       case do_adjust: {
00513 
00514         break;
00515       }
00516       case do_assign: {
00517 
00518         break;
00519       }
00520       case do_borrow: {
00521 
00522         break;
00523       }
00524     }
00525   }
00526 }
00527 
00528 int main(int formal(argc), char *formal(argv)[])
00529 {
00530   SET_DEFAULT_COMBO_LOGGER;
00531   test_byte_array_amorph();
00532   test_bogon_amorph();
00533   guards::alert_message("amorph:: works for those functions tested.");
00534   return 0;
00535 }
00536 
00537 #undef static_class_name
00538 
00539 

Generated on Fri Oct 10 04:29:00 2008 for HOOPLE Libraries by  doxygen 1.5.1