t_deep_array.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : test_deep_array                                                   *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *******************************************************************************
00007 * Copyright (c) 2006-$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/chaos.h>
00017 #include <basis/function.h>
00018 #include <basis/guards.h>
00019 #include <basis/istring.h>
00020 #include <data_struct/deep_array.cpp>
00021 #include <data_struct/matrix.cpp>
00022 #include <mathematics/float_plus.h>
00023 #include <mechanisms/time_stamp.h>
00024 #include <opsystem/application_shell.h>
00025 #include <loggers/console_logger.h>
00026 #include <data_struct/static_memory_gremlin.h>
00027 
00028 const int MAX_TEST_DURATION = 1 * MINUTE_ms;
00029   // each of the tests calling on the templated tester will take this long.
00030 
00031 const int MAX_SIMULTANEOUS_OBJECTS = 42;  // the maximum deep_arrays tested.
00032 
00033 const int MIN_OBJECT = -30; // the smallest deep_array we'll create.
00034 const int MAX_OBJECT = 98; // the largest deep_array we'll create.
00035 
00036 const int MIN_BLOCK = 100;  // the smallest exemplar we'll use.
00037 const int MAX_BLOCK = MAX_OBJECT * 2;  // the largest exempler.
00038 
00039 //#define DEBUG_TEST_ARRAY
00040   // uncomment for noisy version.
00041 
00042 #define LOG(s) EMERGENCY_LOG(program_wide_logger(), s)
00043 
00044 typedef void *void_pointer;
00045 
00047 
00048 class test_deep_array : public application_shell
00049 {
00050 public:
00051   test_deep_array() : application_shell(class_name()) {}
00052   IMPLEMENT_CLASS_NAME("test_deep_array");
00053   virtual int execute();
00054   void dump_deep_array(deep_array<void_pointer> &ar, const char *name);
00055   void test_deep_arrays_of_void_pointer();
00056   void test_packing_deep_arrays();
00057 };
00058 
00060 
00061 void test_deep_array::dump_deep_array(deep_array<void_pointer> &ar, const char *name)
00062 {
00063 #ifdef DEBUG_TEST_ARRAY
00064   LOG(isprintf("deep_array named \"%s\" has:", name)); 
00065   for (int i = 0; i < ar.length(); i++) {
00066     LOG(isprintf("\t%4d: %d", i, (int)ar[i]));
00067   }
00068 #else
00069   if (ar.length() || name) {}
00070 #endif
00071 }
00072 
00073 void test_deep_array::test_deep_arrays_of_void_pointer()
00074 {
00075   FUNCDEF("void pointer test");
00076   if (sizeof(void_pointer) != 4)
00077     deadly_error(class_name(), func, "the void pointer has an unexpected size!");
00078   const int MAX_VOID_ARRAY = 20;
00079   deep_array<void_pointer> argh(MAX_VOID_ARRAY);
00080   deep_array<void_pointer> argh2(argh);
00081   if (argh.length() != MAX_VOID_ARRAY)
00082     deadly_error(class_name(), func, "the first deep_array length is incorrect!");
00083   if (argh2.length() != MAX_VOID_ARRAY)
00084     deadly_error(class_name(), func, "the copied deep_array length is incorrect!");
00085 /* not appropriate for this type of content:
00086   for (int o = 0; o < MAX_VOID_ARRAY; o++)
00087     if (argh[o] != argh2[o])
00088       deadly_error(class_name(), func, "the deep_arrays have different contents!");
00089 */
00090     
00091   // fill it with values.
00092   int starter;
00093   for (int i = 0; i < MAX_VOID_ARRAY; i++)
00094     argh[i] = (void_pointer)(&starter + i);
00095   dump_deep_array(argh, "first version");
00096 
00097   // check the values.
00098   for (int j = 0; j < MAX_VOID_ARRAY; j++)
00099     if (argh[j] != (void *)(&starter + j))
00100       deadly_error(class_name(), func, "setting values are incorrect!");
00101 
00102   // add a constant to the values.
00103   for (int k = 0; k < MAX_VOID_ARRAY; k++)
00104     argh[k] = (void_pointer)((int *)argh[k] + 98);
00105   dump_deep_array(argh, "second version");
00106 
00107   // check assignment.
00108   argh2 = argh;
00109   for (int n = 0; n < MAX_VOID_ARRAY; n++)
00110     if (argh2[n] != (void_pointer)(&starter + n + 98))
00111       deadly_error(class_name(), func, "assign values are incorrect!");
00112 
00113   // now test that values are kept in place after rearrangement.
00114   argh.zap(3, 4);
00115   dump_deep_array(argh, "third version");
00116   for (int l = 0; l < 3; l++)
00117     if (argh[l] != (void_pointer)(&starter + l + 98))
00118       deadly_error(class_name(), func, "zap low values are incorrect!");
00119   for (int m = 3; m < MAX_VOID_ARRAY - 2; m++)
00120     if (argh[m] != (void_pointer)(&starter + m + 2 + 98))
00121       deadly_error(class_name(), func, "zap high values are incorrect!");
00122 
00123 //hmmm: add more tests if void pointer deep_arrays seem in question.
00124 }
00125 
00127 
00128 static istring blank_string;
00129 
00130 // jethro is a simple object for containment below.
00131 class jethro
00132 {
00133 public:
00134   jethro(const istring &i = blank_string) : _truck(i) {}
00135 
00136   istring _truck;
00137 
00138   bool operator ==(const jethro &tc) const { return tc._truck == _truck; }
00139   bool operator !=(const jethro &tc) const { return !(*this == tc); }
00140 };
00141 
00143 
00144 // the test_content object is an object with proper copy constructor
00145 // and assignment operator that also has deep contents.
00146 class test_content
00147 {
00148 public:
00149   byte _q;
00150   istring _ted;
00151   istring _jed;
00152   int_array _ned;
00153   matrix<jethro> _med;
00154   int_matrix _red;
00155 
00156   test_content(byte q = 3)
00157   : _q(q), _ted("bl"), _jed("orp"),
00158     _ned(12, NIL),
00159     _med(3, 2),
00160     _red(2, 4)
00161   {
00162     for (int i = 0; i < _ned.length(); i++)
00163       _ned[i] = -i;
00164     for (int r = 0; r < _med.rows(); r++)
00165       for (int c = 0; c < _med.columns(); c++)
00166         _med[r][c] = jethro(istring((r*c) % 256, 1));
00167     for (int j = 0; j < _red.rows(); j++)
00168       for (int k = 0; k < _red.columns(); k++)
00169         _red[j][k] = j * k;
00170   }
00171 
00172   bool operator ==(const test_content &tc) const {
00173     if (tc._q != _q)
00174       return false;
00175     if (tc._ted != _ted)
00176       return false;
00177     if (tc._jed != _jed)
00178       return false;
00179     if (tc._ned.length() != _ned.length())
00180       return false;
00181     for (int i = 0; i < _ned.length(); i++)
00182       if (tc._ned[i] != _ned[i])
00183         return false;
00184     
00185     if (tc._med.rows() != _med.rows())
00186       return false;
00187     if (tc._med.columns() != _med.columns())
00188       return false;
00189     for (int c = 0; c < _med.columns(); c++)
00190       for (int r = 0; r < _med.rows(); r++)
00191         if (tc._med.get(r, c) != _med.get(r, c))
00192           return false;
00193 
00194     if (tc._red.rows() != _red.rows())
00195       return false;
00196     if (tc._red.columns() != _red.columns())
00197       return false;
00198     for (int j = 0; j < _red.rows(); j++)
00199       for (int k = 0; k < _red.columns(); k++)
00200         if (tc._red.get(j, k) != _red.get(j, k))
00201           return false;
00202 
00203     return true;
00204   }
00205   bool operator !=(const test_content &tc) const { return !operator ==(tc); }
00206 
00207   operator byte() const { return _q; }
00208 };
00209 
00211 
00212 template <class contents>
00213 bool compare_deep_arrays(const deep_array<contents> &a, const deep_array<contents> &b)
00214 {
00215   if (a.length() != b.length()) return false;
00216   for (int i = 0; i < a.length(); i++)
00217     if (a[i] != b[i]) return false;
00218   return true;
00219 }
00220 
00221 template <class contents>
00222 void fill_in(deep_array<contents> &to_fill, const contents &filler)
00223 {
00224   for (int i = 0; i < to_fill.length(); i++)
00225     if (!to_fill.restore(i))
00226       to_fill.put(i, filler);
00227 }
00228 
00230 
00231 // this is a templated test for deep_arrays, with some requirements.  the
00232 // contents object must support a constructor that takes a simple byte,
00233 // whether that's meaningful for the object or not.  if your type to test
00234 // doesn't have that, derive a simple object from it, give it that
00235 // constructor, and then it can be used below.  the object must also support
00236 // comparison with == and != for this test to be used.  it must also provide
00237 // a conversion to integer that returns the value passed to the constructor.
00238 
00239 template <class contents>
00240 void deep_array_tester(test_deep_array &ta, const contents &bogus)
00241 {
00242   // the space that all training for deep_arrays comes from.
00243   contents *junk_space = new contents[MAX_OBJECT + MAX_BLOCK];
00244   for (int i = 0; i < MAX_OBJECT - 1; i++)
00245     junk_space[i] = contents(ta.randomizer().inclusive('a', 'z'));
00246   junk_space[MAX_OBJECT + MAX_BLOCK - 1] = '\0';
00247 
00248   deep_array<contents> *testers[MAX_SIMULTANEOUS_OBJECTS];
00249   for (int c = 0; c < MAX_SIMULTANEOUS_OBJECTS; c++) {
00250     // set up the initial deep_array guys.
00251     testers[c] = new deep_array<contents>(ta.randomizer().inclusive(MIN_OBJECT, MAX_OBJECT));
00252     // copy the randomized junk space into the new object.
00253     for (int i = 0; i < testers[c]->length(); i++)
00254       testers[c]->put(i, junk_space[i]);
00255   }
00256 
00257   // these are the actions we try out with the deep_array during the test.
00258   // the first and last elements must be identical to the first and last
00259   // tests to perform.
00260   enum actions { first, do_size = first, do_assign, do_access, do_zap,
00261       do_reset, do_resizer, do_indices, do_concatenating, do_subarray,
00262       do_insert, do_overwrite, do_memory_paring, do_snarf, last = do_snarf };
00263 
00264   time_stamp exit_time(MAX_TEST_DURATION);
00265   while (time_stamp() < exit_time) {
00266     int index = ta.randomizer().inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
00267     int choice = ta.randomizer().inclusive(first, last);
00268     switch (choice) {
00269       case do_size: {
00270 #ifdef DEBUG_TEST_ARRAY
00271         LOG(isprintf("do_size"));
00272 #endif
00273         deep_array<contents> old_version = *testers[index];
00274         bool at_front = bool(ta.randomizer().inclusive(0, 1));
00275         int new_size = ta.randomizer().inclusive(MIN_OBJECT, MAX_OBJECT);
00276         bool smaller = new_size < old_version.length();
00277         int difference = absolute_value(new_size - old_version.length());
00278         testers[index]->resize(new_size, at_front? common::NEW_AT_BEGINNING
00279             : common::NEW_AT_END);
00280         if (!smaller && difference) {
00281           // neuter the contents in the new section so we can compare.  this
00282           // space is filled with whatever the object's constructor chooses.
00283           if (at_front) {
00284             for (int i = 0; i < difference; i++)
00285               testers[index]->put(i, 'Q');
00286           } else {
00287             for (int i = old_version.length();
00288                 i < old_version.length() + difference; i++)
00289               testers[index]->put(i, 'Q');
00290           }
00291         }
00292         // now compute an equivalent form of what the state should be.
00293         deep_array<contents> equivalent(0);
00294         if (at_front) {
00295           if (smaller) {
00296             equivalent = old_version.subarray(difference,
00297                 old_version.length() - 1);
00298           } else {
00299             deep_array<contents> blank(difference);
00300             for (int i = 0; i < blank.length(); i++)
00301               blank[i] = 'Q';
00302             equivalent = blank + old_version;
00303           }
00304         } else {
00305           if (smaller) {
00306             equivalent = old_version.subarray(0, old_version.length()
00307                 - difference - 1);
00308           } else {
00309             deep_array<contents> blank(difference);
00310             for (int i = 0; i < blank.length(); i++)
00311               blank[i] = 'Q';
00312             equivalent = old_version + blank;
00313           }
00314         }
00315         if (equivalent.length() != testers[index]->length())
00316           deadly_error(ta.class_name(), __WHERE__, "the resized form had "
00317               "erroneous length");
00318         if (!compare_deep_arrays(*testers[index], equivalent))
00319           deadly_error(ta.class_name(), __WHERE__, "the resized form had "
00320               "erroneous contents");
00321         break;
00322       }
00323       case do_assign: {
00324 #ifdef DEBUG_TEST_ARRAY
00325         LOG(isprintf("do_assign"));
00326 #endif
00327         deep_array<contents> arrh = *testers[index];  // copy old value.
00328         int to_assign = ta.randomizer().inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
00329         *testers[index] = *testers[to_assign];
00330         if (!compare_deep_arrays(*testers[index], *testers[to_assign]))
00331           deadly_error(ta.class_name(), __WHERE__, "assign failed to copy deep_array");
00332         *testers[to_assign] = arrh;  // recopy contents to new place.
00333         if (!compare_deep_arrays(*testers[to_assign], arrh))
00334           deadly_error(ta.class_name(), __WHERE__, "second assign failed");
00335         break;
00336       }
00337       case do_access: {
00338 #ifdef DEBUG_TEST_ARRAY
00339         LOG(isprintf("do_access"));
00340 #endif
00341         int start = ta.randomizer().inclusive(0, testers[index]->length());
00342         int end = ta.randomizer().inclusive(0, testers[index]->length());
00343         flip_increasing(start, end);
00344         deep_array<contents> accumulator(0);
00345         for (int i = start; i < end; i++) {
00346           contents c = contents(ta.randomizer().inclusive(1, 255));
00347           testers[index]->put(i, c);
00348           accumulator += c;
00349         }
00350         for (int j = start; j < end; j++)
00351           if (accumulator[j - start] != (*testers[index])[j])
00352             deadly_error(ta.class_name(), __WHERE__, "accessing failed");
00353         break;
00354       }
00355       case do_indices: {
00356 #ifndef CATCH_ERRORS  // only works if not catching errors.
00357   #ifdef DEBUG_TEST_ARRAY
00358         LOG(isprintf("do_indices"));
00359   #endif
00360         // does some tests on bad indices.
00361         contents c1 = testers[index]->operator[](-50);
00362         contents c2 = testers[index]->operator[](-MAX_OBJECT);
00363         bool test = (c1 == c2);
00364         if (!test)
00365           deadly_error(ta.class_name(), __WHERE__, "invalid values were not same");
00366         int tests = ta.randomizer().inclusive(100, 500);
00367         for (int i = 0; i < tests; i++) {
00368           int indy = ta.randomizer().inclusive(-1000, MAX_OBJECT * 3);
00369           // testing if we can access without explosions.
00370           contents c3 = testers[index]->operator[](indy);
00371           contents c4 = c3;
00372           if (c3 != c4) 
00373             deadly_error(ta.class_name(), __WHERE__, "values were not same");
00374         }
00375 #endif
00376         break;
00377       }
00378       case do_resizer: {
00379 #ifdef DEBUG_TEST_ARRAY
00380         LOG(isprintf("do_resizer"));
00381 #endif
00382         // tests whether the deep_array will reuse space when it should be able to.
00383         deep_array<contents> &arrh = *testers[index];
00384         // fill with known data.
00385         int i;
00386         for (i = 0; i < arrh.length(); i++)
00387           arrh[i] = contents((i + 23) % 256);
00388         int zap_amount = ta.randomizer().inclusive(1, arrh.length() - 1);
00389         // now take out a chunk from the deep_array at the beginning.
00390         arrh.zap(0, zap_amount - 1);
00391         // test the contents.
00392         for (i = 0; i < arrh.length(); i++)
00393           if (arrh[i] != contents((i + 23 + zap_amount) % 256))
00394             deadly_error(ta.class_name(), __WHERE__, "the resized form "
00395                 "had different contents");
00396         // now add back in the space we ate.
00397         arrh.resize(arrh.length() + zap_amount, common::NEW_AT_END);
00398         // test the contents again.  they should start at zero and have the
00399         // same zap_amount offset.  the stuff past the original point shouldn't
00400         // be tested since we haven't set it.
00401         for (i = 0; i < arrh.length() - zap_amount; i++)
00402           if (arrh[i] != contents((i + 23 + zap_amount) % 256))
00403             deadly_error(ta.class_name(), __WHERE__, "the resized form "
00404                 "had different contents");
00405         // now a test of all values through the zap_amount.
00406         arrh.zap(0, zap_amount - 1);
00407         for (i = 0; i < zap_amount; i++) {
00408           arrh.resize(arrh.length() + 1, common::NEW_AT_END);
00409         }
00410         // test the contents once more.  they should start at zero and have
00411         // double the zap_amount offset.  the stuff past the original point
00412         // shouldn't be tested since we haven't set it.
00413         for (i = 0; i < arrh.length() - 2 * zap_amount; i++)
00414           if (arrh[i] != contents((i + 23 + 2 * zap_amount) % 256))
00415             deadly_error(ta.class_name(), __WHERE__, "the slowly resized "
00416                 "form had different contents");
00417 
00418         // the tests below should be nearly identical to the ones above, but
00419         // they use the NEW_AT_BEGINNING style of copying.
00420 
00421         // fill with known data.
00422         for (i = 0; i < arrh.length(); i++)
00423           arrh[i] = contents((i + 23) % 256);
00424         zap_amount = ta.randomizer().inclusive(1, arrh.length() - 1);
00425         // now take out a chunk from the deep_array at the beginning.
00426         arrh.zap(0, zap_amount - 1);
00427         // test the contents.
00428         for (i = 0; i < arrh.length(); i++)
00429           if (arrh[i] != contents((i + 23 + zap_amount) % 256))
00430             deadly_error(ta.class_name(), __WHERE__, "the resized form "
00431                 "had different contents");
00432         // now add back in the space we ate.
00433         arrh.resize(arrh.length() + zap_amount,
00434             common::NEW_AT_BEGINNING);
00435         // test the contents again.  they should start at zap_amount but have
00436         // the same zap_amount offset.  the stuff before the original point
00437         // shouldn't be tested since we haven't set it.
00438         for (i = zap_amount; i < arrh.length(); i++)
00439           if (arrh[i] != contents((i + 23) % 256))
00440             deadly_error(ta.class_name(), __WHERE__, "the resized form "
00441                 "had different contents");
00442         // now a test of all values through the zap_amount.
00443         arrh.zap(0, zap_amount - 1);
00444         for (i = 0; i < zap_amount; i++) {
00445           arrh.resize(arrh.length() + 1, common::NEW_AT_BEGINNING);
00446         }
00447         // test the contents once more.  the zap_amount offset should stay the
00448         // same since we clobbered the place we added originally, then added
00449         // more space in.  so we skip the first part still.
00450         for (i = zap_amount; i < arrh.length(); i++)
00451           if (arrh[i] != contents((i + 23) % 256))
00452             deadly_error(ta.class_name(), __WHERE__, "the slowly resized "
00453                 "form had different contents");
00454         break;
00455       }
00456       case do_zap: {
00457 #ifdef DEBUG_TEST_ARRAY
00458         LOG(isprintf("do_zap"));
00459 #endif
00460         int start;
00461         int end;
00462         bool erroneous = false;
00463         int chose = ta.randomizer().inclusive(1, 100);
00464         if (chose <= 90) {
00465           // there's a ninety percent chance we pick a range that's valid.
00466           start = ta.randomizer().inclusive(0, testers[index]->length() - 1);
00467           end = ta.randomizer().inclusive(0, testers[index]->length() - 1);
00468         } else if (chose <= 95) {
00469           // and a 5 percent chance we pick to choose the zero index as our
00470           // start; this gets at the code for fast zapping.
00471           start = 0;
00472           end = ta.randomizer().inclusive(0, testers[index]->length() - 1);
00473         } else {
00474           // and a 5 percent chance we'll allow picking a bad index.  the
00475           // actual chance of picking a bad one is less.
00476           erroneous = true;
00477           start = ta.randomizer().inclusive(-2, testers[index]->length() + 3);
00478           end = ta.randomizer().inclusive(-2, testers[index]->length() + 3);
00479         }
00480         flip_increasing(start, end);
00481         deep_array<contents> old_version = *testers[index];
00482         testers[index]->zap(start, end);
00483         if (!erroneous) {
00484           deep_array<contents> old_head = old_version.subarray(0, start - 1);
00485           deep_array<contents> old_tail = old_version.subarray(end + 1,
00486               old_version.length() - 1);
00487           deep_array<contents> equivalent = old_head + old_tail;
00488           if (equivalent.length() != testers[index]->length())
00489             deadly_error(ta.class_name(), __WHERE__, "the zapped form had "
00490                 "erroneous length");
00491           if (!compare_deep_arrays(*testers[index], equivalent))
00492             deadly_error(ta.class_name(), __WHERE__, "the zapped form had "
00493                 "erroneous contents");
00494         }
00495         break;
00496       }
00497       case do_reset: {
00498 #ifdef DEBUG_TEST_ARRAY
00499         LOG(isprintf("do_reset"));
00500 #endif
00501         int junk_start = ta.randomizer().inclusive(MIN_BLOCK, MAX_BLOCK);
00502         int junk_end = ta.randomizer().inclusive(MIN_BLOCK, MAX_BLOCK);
00503         flip_increasing(junk_start, junk_end);
00504         int len = junk_end - junk_start + 1;
00505         testers[index]->reset(len);
00506         if (testers[index]->length() != len)
00507           deadly_error(ta.class_name(), __WHERE__, "reset gave a bad length");
00508         for (int i = 0; i < len; i++) {
00509           testers[index]->put(i, junk_space[junk_start + i]);
00510           if (testers[index]->get(i) != junk_space[junk_start + i])
00511             deadly_error(ta.class_name(), __WHERE__, "reset failed to copy data");
00512         }
00513         break;
00514       }
00515       case do_concatenating: {
00516 #ifdef DEBUG_TEST_ARRAY
00517         LOG(isprintf("do_concatenating"));
00518 #endif
00519         for (int i = 0; i < ta.randomizer().inclusive(1, 20); i++) {
00520           contents new_c = contents(ta.randomizer().inclusive('a', 'z'));
00521           testers[index]->concatenate(new_c);
00522           if (new_c != testers[index]->get(testers[index]->last()))
00523             deadly_error(ta.class_name(), __WHERE__,
00524                 "value wrong after concatenate");
00525         }
00526         int indy = ta.randomizer().inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
00527         deep_array<contents> flirpan = *testers[indy];
00528         int start = ta.randomizer().inclusive(0, flirpan.length() - 1);
00529         int end = ta.randomizer().inclusive(0, flirpan.length() - 1);
00530         flip_increasing(start, end);
00531         flirpan = flirpan.subarray(start, end);
00532         deep_array<contents> grumzor = *testers[index];  // old copy.
00533         testers[index]->concatenate(flirpan);
00534         deep_array<contents> bubula = grumzor + flirpan;
00535         if (!compare_deep_arrays(bubula, *testers[index]))
00536           deadly_error(ta.class_name(), __WHERE__,
00537               "contents wrong after concatenate or concatenation");
00538         contents first_value;
00539         contents second_value;
00540         if (testers[index]->length() >= 1)
00541           first_value = testers[index]->get(0);
00542         if (testers[index]->length() >= 2)
00543           second_value = testers[index]->get(1);
00544         const int max_iters = ta.randomizer().inclusive(1, 42);
00545         for (int j = 0; j < max_iters; j++) {
00546           contents new_c = contents(ta.randomizer().inclusive('a', 'z'));
00547           *testers[index] = *testers[index] + new_c;
00548           // correct our value checks if new indices became available.
00549           if (testers[index]->length() == 1) {
00550             first_value = testers[index]->get(0);
00551           } else if (testers[index]->length() == 2) {
00552             second_value = testers[index]->get(1);
00553           }
00554 
00555           if (new_c != testers[index]->get(testers[index]->last()))
00556             deadly_error(ta.class_name(), __WHERE__, "value wrong after "
00557                 "concatenation");
00558 
00559           if ( (testers[index]->length() >= 1)
00560               && (first_value != testers[index]->get(0)) )
00561             deadly_error(ta.class_name(), __WHERE__, "first value got "
00562                 "corrupted");
00563           if ( (testers[index]->length() >= 2)
00564               && (second_value != testers[index]->get(1)) )
00565             deadly_error(ta.class_name(), __WHERE__, "second value got "
00566                 "corrupted");
00567 
00568           *testers[index] += new_c;
00569           // we don't have to correct the first value any more, but might have
00570           // to correct the second.
00571           if (testers[index]->length() == 2) {
00572             second_value = testers[index]->get(1);
00573           }
00574           if (new_c != testers[index]->get(testers[index]->last()))
00575             deadly_error(ta.class_name(), __WHERE__, "value wrong after "
00576                 "second concatenation");
00577           if ( (testers[index]->length() >= 1)
00578               && (first_value != testers[index]->get(0)) )
00579             deadly_error(ta.class_name(), __WHERE__, "first value got "
00580                 "corrupted after second concat");
00581           if ( (testers[index]->length() >= 2)
00582               && (second_value != testers[index]->get(1)) )
00583             deadly_error(ta.class_name(), __WHERE__, "second value got "
00584                 "corrupted after second concat");
00585         }
00586         break;
00587       }
00588       case do_subarray: {
00589 #ifdef DEBUG_TEST_ARRAY
00590         LOG(isprintf("do_subarray"));
00591 #endif
00592         fill_in(*testers[index], bogus);  // make sure items are comparable.
00593         deep_array<contents> flirpan = *testers[index];
00594         int start = ta.randomizer().inclusive(0, flirpan.length() - 1);
00595         int end = ta.randomizer().inclusive(0, flirpan.length() - 1);
00596         flip_increasing(start, end);
00597         flirpan = flirpan.subarray(start, end);
00598         for (int i = 0; i < end - start; i++)
00599           if (flirpan[i] != testers[index]->get(i + start))
00600             deadly_error(ta.class_name(), __WHERE__, "subarray produced wrong deep_array");
00601         break;
00602       }
00603       case do_memory_paring: {
00604 #ifdef DEBUG_TEST_ARRAY
00605         LOG(isprintf("do_memory_paring"));
00606 #endif
00607         for (int i = 0; i < MAX_SIMULTANEOUS_OBJECTS; i++) {
00608           // zap extra junk off so we bound the memory usage.
00609           if (testers[i]->length() > MAX_OBJECT) {
00610             testers[i]->zap(MAX_OBJECT, testers[i]->length() - 1);
00611           }
00612         }
00613         break;
00614       }
00615       case do_snarf: {
00616 //this test becomes the acquire test?
00617 /*
00618 #ifdef DEBUG_TEST_ARRAY
00619         LOG(isprintf("do_snarf"));
00620 #endif
00621         deep_array<contents> flirpan = *testers[index];
00622 //        int start = ta.randomizer().inclusive(0, flirpan.length() - 1);
00623 //        int end = ta.randomizer().inclusive(0, flirpan.length() - 1);
00624 //        flip_increasing(start, end);
00625 //        flirpan = flirpan.subarray(start, end);
00626         int rand_index = ta.randomizer().inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
00627         if (index == rand_index) continue;  // skip it; try again later.
00628         deep_array<contents> nugwort = *testers[rand_index];
00629         // perform a swap between two of our deep_arrays.
00630         deep_array<contents> temp_hold(0);
00631         temp_hold.snarf(*testers[index]);
00632         testers[index]->snarf(*testers[rand_index]);
00633         testers[rand_index]->snarf(temp_hold);
00634         // the copies should have flipped places now.  check them.
00635         if (flirpan.length() != testers[rand_index]->length())
00636           deadly_error(ta.class_name(), __WHERE__, "snarf produced wrong length A");
00637         for (int i = 0; i < flirpan.length(); i++)
00638           if (flirpan[i] != testers[rand_index]->get(i))
00639             deadly_error(ta.class_name(), __WHERE__, "snarf produced wrong deep_array A");
00640         if (nugwort.length() != testers[index]->length())
00641           deadly_error(ta.class_name(), __WHERE__, "snarf produced wrong length B");
00642         for (int j = 0; j < nugwort.length(); j++)
00643           if (nugwort[j] != testers[index]->get(j))
00644             deadly_error(ta.class_name(), __WHERE__, "snarf produced wrong deep_array B");
00645 */
00646       }
00647       case do_insert: {
00648 #ifdef DEBUG_TEST_ARRAY
00649         LOG(isprintf("do_insert"));
00650 #endif
00651         fill_in(*testers[index], bogus);  // make sure items are comparable.
00652         deep_array<contents> hold = *testers[index];
00653         int put_where = ta.randomizer().inclusive(0, hold.last());
00654         int how_many = ta.randomizer().inclusive(0, 25);
00655         testers[index]->insert(put_where, how_many);
00656         for (int i = 0; i < put_where; i++)
00657           if (hold[i] != testers[index]->get(i))
00658             deadly_error(ta.class_name(), __WHERE__, "bad contents on left after insert");
00659         for (int j = put_where + how_many; j < testers[index]->length(); j++)
00660           if (hold[j - how_many] != testers[index]->get(j))
00661             deadly_error(ta.class_name(), __WHERE__, "bad contents on right after insert");
00662         break;
00663       }
00664       case do_overwrite: {
00665 #ifdef DEBUG_TEST_ARRAY
00666         LOG(isprintf("do_overwrite"));
00667 #endif
00668         fill_in(*testers[index], bogus);  // make sure items are comparable.
00669         if (!testers[index]->length()) continue;
00670         fill_in(*testers[index], bogus);  // make sure items are comparable.
00671         deep_array<contents> hold = *testers[index];
00672         int index2 = index;
00673         while (index2 == index)
00674           index2 = ta.randomizer().inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
00675         fill_in(*testers[index2], bogus);  // make sure items are comparable.
00676         deep_array<contents> &hold2 = *testers[index2];
00677         if (!hold2.length()) continue;
00678         int write_indy = ta.randomizer().inclusive(0, hold.last());
00679         int write_len = minimum(hold2.length(), (hold.length() - write_indy));
00680 // LOG(isprintf("len1 = %d len2 = %d wrindy=%d wrlen=%d", hold.length(), hold2.length(), write_indy, write_len));
00681         outcome ret = testers[index]->overwrite(write_indy,
00682             *testers[index2], write_len);
00683         if (ret != common::OKAY)
00684           deadly_error(ta.class_name(), __WHERE__, istring("bad outcome=")
00685               + common::outcome_name(ret));
00686         for (int i = 0; i < write_indy; i++)
00687           if (hold[i] != testers[index]->get(i))
00688             deadly_error(ta.class_name(), __WHERE__,
00689                 "bad contents on left after overwrite");
00690         for (int j = write_indy; j < write_indy + write_len; j++)
00691           if (hold2[j - write_indy] != testers[index]->get(j))
00692             deadly_error(ta.class_name(), __WHERE__,
00693                 "bad contents in middle after overwrite");
00694         for (int k = write_indy + write_len; k < testers[index]->length(); k++)
00695           if (hold[k] != testers[index]->get(k))
00696             deadly_error(ta.class_name(), __WHERE__,
00697                 "bad contents on right after overwrite");
00698         break;
00699       }
00700       default: {
00701         deadly_error(ta.class_name(), "action choice", "invalid choice!");
00702         break;
00703       }
00704     }
00705   }
00706 
00707   // clean up.
00708   delete [] junk_space;
00709   for (int d = 0; d < MAX_SIMULTANEOUS_OBJECTS; d++) delete testers[d];
00710 }
00711 
00713 
00714 struct gerkin { int l; byte *p; char *r; void *pffttt; };
00715 
00716 gerkin borgia;
00717 
00718 class foop
00719 {
00720 public:
00721   virtual ~foop() {}
00722   virtual gerkin *boorba() = 0;
00723 };
00724 
00725 class boop : public foop
00726 {
00727 public:
00728   virtual gerkin *boorba() { return &borgia; }
00729 };
00730 
00732 
00733 class deep_pack_object : public packable
00734 {
00735 public:
00736   istring _glunk;
00737   int _foof;
00738 
00739   deep_pack_object() : packable(), _glunk("arf"), _foof(2398) {}
00740   virtual ~deep_pack_object() { _glunk = ""; _foof = 0; }
00741 
00742   virtual void pack(byte_array &packed_form) const {
00743     _glunk.pack(packed_form);
00744     basis::attach(packed_form, _foof);
00745   }
00746 
00747   virtual bool unpack(byte_array &packed_form) {
00748     if (!_glunk.unpack(packed_form)) return false;
00749     if (!basis::detach(packed_form, _foof)) return false;
00750     return true;
00751   }
00752 
00753   virtual int packed_size() const {
00754       return _glunk.length() + 1
00755           + sizeof(int);
00756   }
00757 };
00758 
00759 void test_deep_array::test_packing_deep_arrays()
00760 {
00761   FUNCDEF("test_packing_deep_arrays");
00762   deep_array<deep_pack_object> fred1;
00763   for (int i = 0; i < 3 + chaos().inclusive(0, 80); i++)
00764     fred1 += deep_pack_object(); 
00765   byte_array packed_form;
00766   data_structure::pack(packed_form, fred1);
00767   if (data_structure::packed_size(fred1) != packed_form.length())
00768     deadly_error(func, "packed_size", "calculated wrong packed size");
00769   deep_array<deep_pack_object> fred2;
00770   if (!data_structure::unpack(packed_form, fred2)) 
00771     deadly_error(func, "unpack", "unpacking failed on deep array");
00772   if (fred2.length() != fred1.length()) 
00773     deadly_error(func, "unpack", "unpacking got wrong length in result");
00774   for (int i = 0; i < fred2.length(); i++) {
00775     if (fred2[i]._foof != 2398)
00776       deadly_error(func, "unpack", "unpacking got wrong int content");
00777     if (fred2[i]._glunk != "arf")
00778       deadly_error(func, "unpack", "unpacking got wrong string content");
00779   }
00780 }
00781 
00783 
00784 int test_deep_array::execute()
00785 {
00786   test_packing_deep_arrays();
00787   LOG(isprintf("did deep_array packing test.")); 
00788 
00789   int_array checking_start;
00790   if (checking_start.length())
00791     deadly_error(class_name(), "int_array length",
00792         "has contents from empty constructor!");
00793 
00794   float_plus<double> bogus4 = float(12.32);
00795   deep_array_tester<float_plus<double> >(*this, bogus4);
00796   LOG(isprintf("did float deep_array test.")); 
00797 
00798   int bogus2 = 39;
00799   deep_array_tester<int>(*this, bogus2);
00800   LOG(isprintf("did int deep_array test.")); 
00801 
00802   test_content bogus3(12);
00803   deep_array_tester<test_content>(*this, bogus3);
00804   LOG(isprintf("did test_content deep_array test.")); 
00805 
00806   test_deep_arrays_of_void_pointer();
00807   LOG(isprintf("did void * deep_array test.")); 
00808 
00809   byte bogus1 = 'c';
00810   deep_array_tester<byte>(*this, bogus1);
00811   LOG(isprintf("did byte deep_array test.")); 
00812 
00813   guards::alert_message("deep_array:: works for those functions tested.");
00814 
00815   return 0;
00816 }
00817 
00818 HOOPLE_MAIN(test_deep_array, )
00819 

Generated on Fri Nov 28 04:29:36 2008 for HOOPLE Libraries by  doxygen 1.5.1