t_stack.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : t_stack                                                           *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *  Purpose:                                                                   *
00007 *                                                                             *
00008 *    Tests out the stack object with both flat objects (byte_array) but also  *
00009 *  deep objects (pointer to byte_array).  Both bounded and unbounded stacks   *
00010 *  are tested for each.                                                       *
00011 *                                                                             *
00012 *******************************************************************************
00013 * Copyright (c) 1992-$now By Author.  This program is free software; you can  *
00014 * redistribute it and/or modify it under the terms of the GNU General Public  *
00015 * License as published by the Free Software Foundation; either version 2 of   *
00016 * the License or (at your option) any later version.  This is online at:      *
00017 *     http://www.fsf.org/copyleft/gpl.html                                    *
00018 * Please send any updates to: fred@gruntose.com                               *
00019 \*****************************************************************************/
00020 
00021 #include <basis/byte_array.h>
00022 #include <basis/chaos.h>
00023 #include <basis/guards.h>
00024 #include <basis/istring.h>
00025 #include <data_struct/stack.cpp>
00026 #include <data_struct/static_memory_gremlin.h>
00027 
00028 #ifdef DEBUG_STACK
00029   #include <loggers/console_logger.h>
00030   #include <stdio.h>
00031   console_logger out;
00032   #define LOG(to_print) { out.log(to_print); fflush(0); }
00033 #endif
00034 
00035 #include <stdlib.h>
00036 #include <string.h>
00037 
00038 HOOPLE_STARTUP_CODE;
00039 
00040 //#define DEBUG_STACK
00041   // uncomment for a noisier version.
00042 
00043 const int test_iterations = 40;
00044 
00045 #define WHERE __WHERE__.s()
00046 
00047 // CHECK_STACK_RESULT: a function that takes care of error testing for a
00048 // stack command.  if executing the command ends in full or empty, then
00049 // that is reported.
00050 void CHECK_STACK_RESULT(outcome retval, const istring &place)
00051 {
00052 #ifdef DEBUG_STACK
00053   if (retval == common::IS_FULL)
00054     LOG(istring(istring::SPRINTF, "returned IS_FULL at %s", place.s()))
00055   else if (retval == common::IS_EMPTY)
00056     LOG(istring(istring::SPRINTF, "returned IS_EMPTY at %s", place.s()));
00057 #else
00058   if (retval.value() || !place) {}
00059 #endif
00060 }
00061 
00062 byte_array generate_flat(const char *to_store)
00063 {
00064   byte_array to_return = byte_array(int(strlen(to_store) + 1), (byte *)to_store);
00065   return to_return;
00066 }
00067 
00068 byte_array *generate_deep(const char *to_store)
00069 {
00070   byte_array *to_return = new byte_array(int(strlen(to_store) + 1),
00071       (byte *)to_store);
00072   return to_return;
00073 }
00074 
00075 istring text_form(stack<byte_array *> &s)
00076 {
00077   istring to_return;
00078   for (int i = 0; i < s.elements(); i++) {
00079     to_return += istring(istring::SPRINTF, "#%d: %s\n", i, s[i]->observe());
00080   }
00081   return to_return;
00082 }
00083 
00084 istring text_form(stack<byte_array> &s)
00085 {
00086   istring to_return;
00087   for (int i = 0; i < s.elements(); i++) {
00088     to_return += istring(istring::SPRINTF, "#%d: %s\n", i, s[i].observe());
00089   }
00090   return to_return;
00091 }
00092 
00093 void test_stack_with_objects()
00094 {
00095   for (int qq = 0; qq < test_iterations; qq++) {
00096 #ifdef DEBUG_STACK
00097     LOG(istring(istring::SPRINTF, "index %d", qq));
00098 #endif
00099     stack<byte_array > bounded_stack(3);
00100     stack<byte_array > unlimited_stack(0);
00101     chaos randomizer;
00102 
00103     {
00104 #ifdef DEBUG_STACK
00105       LOG("testing the bounded stack first:");
00106 #endif
00107       CHECK_STACK_RESULT(bounded_stack.push(generate_flat("the first line")), "first push");
00108       CHECK_STACK_RESULT(bounded_stack.push(generate_flat("the second line")), "second push");
00109       CHECK_STACK_RESULT(bounded_stack.push(generate_flat("the final and third")), "third push");
00110       byte_array gend = generate_flat("this shouldn't work");
00111       if (bounded_stack.push(gend) != common::IS_FULL)
00112         deadly_error(WHERE, "main", "the bounded stack push didn't catch IS_FULL");
00113 #ifdef DEBUG_STACK
00114       LOG("pushing worked successfully...");
00115       LOG("printing the stack in element order");
00116 #endif
00117       for (int i = 0; i < bounded_stack.size(); i++) {
00118 #ifdef DEBUG_STACK
00119         LOG(istring(istring::SPRINTF, "depth %d has %s.", i,
00120             bounded_stack[i].observe()));
00121 #endif
00122       }
00123 #ifdef DEBUG_STACK
00124       LOG("now popping the stack all the way back.");
00125 #endif
00126       int full_size = bounded_stack.size();
00127       for (int j = 0; j < full_size; j++) {
00128 #ifdef DEBUG_STACK
00129         LOG(istring(istring::SPRINTF, "pop %d, stack size is %d, has %s", j+1,
00130             bounded_stack.size(), bounded_stack.top().observe()));
00131 #endif
00132         byte_array found;
00133         bounded_stack.acquire_pop(found);
00134         istring got((char *)found.observe());
00135         switch (j) {
00136         case 0: if (got != istring("the final and third"))
00137           deadly_error(WHERE, "acquire_pop", "wrong contents at 2"); break;
00138         case 1: if (got != istring("the second line"))
00139           deadly_error(WHERE, "acquire_pop", "wrong contents at 1"); break;
00140         case 2: if (got != istring("the first line"))
00141           deadly_error(WHERE, "acquire_pop", "wrong contents at 0"); break;
00142         }
00143       }
00144       if (bounded_stack.pop() != common::IS_EMPTY)
00145         deadly_error(WHERE, "main", "bounded pop failure");
00146     }
00147 
00148     {
00149 #ifdef DEBUG_STACK
00150       LOG("testing the unbounded stack now:");
00151 #endif
00152       for (int j = 0; j < 24; j++) {
00153         istring line(istring::SPRINTF, "{posn %d here}", j);
00154         CHECK_STACK_RESULT(unlimited_stack.push(generate_flat(line.s())), "unbound push");
00155       }
00156 #ifdef DEBUG_STACK
00157       LOG("unbounded stack in element order:");
00158 #endif
00159       for (int k = 0; k < unlimited_stack.size(); k++) {
00160 #ifdef DEBUG_STACK
00161         LOG(istring(istring::SPRINTF, "#%d is %s", k, unlimited_stack[k].observe()));
00162 #endif
00163       }
00164 #ifdef DEBUG_STACK
00165       LOG("now popping fresh order:");
00166 #endif
00167       while (unlimited_stack.size()) {
00168 #ifdef DEBUG_STACK
00169         LOG(istring(istring::SPRINTF, "size %d, content %s",
00170             unlimited_stack.size(), unlimited_stack.top().observe()));
00171 #endif
00172         unlimited_stack.pop();
00173       }
00174 #ifdef DEBUG_STACK
00175       LOG("");
00176 #endif
00177       if (unlimited_stack.pop() != common::IS_EMPTY)
00178         deadly_error(WHERE, "main", "pop did not return empty as expected");
00179 #ifdef DEBUG_STACK
00180       LOG("\
00181 ----------------------------------------------\n\
00182 both types of stack exercises were successful.\n\
00183 ----------------------------------------------");
00184 #endif
00185     }
00186 
00187 #ifdef DEBUG_STACK
00188     LOG("now setting up some simple stacks...");
00189 #endif
00190 
00191     {
00192 #ifdef DEBUG_STACK
00193       LOG("bounded first...");
00194 #endif
00195       stack<byte_array > bounder(randomizer.inclusive(30, 80));
00196 #ifdef DEBUG_STACK
00197       LOG(istring(istring::SPRINTF, "length of bounder is max %d, curr %d", bounder.elements(), bounder.size()));
00198 #endif
00199       int max = bounder.elements();
00200       for (int i = 0; i < max; i++) {
00201         if (bounder.size() != i)
00202           deadly_error(WHERE, "bounder size", "out of step with loop");
00203         int byte_array_size = randomizer.inclusive(259, 287);
00204         byte_array to_stuff(byte_array_size);
00205         istring visible(istring::SPRINTF, "entry %d...", i);
00206         visible.stuff((char *)to_stuff.access(), visible.length() + 1);
00207         for (int j = visible.length() + 1; j < to_stuff.length(); j++)
00208           *(to_stuff.access() + j) = '\0';
00209 #ifdef DEBUG_STACK
00210         LOG(istring(istring::SPRINTF, "pushing index %d", i));
00211 #endif
00212         outcome ret = bounder.push(to_stuff);
00213         if (ret != common::OKAY)
00214           deadly_error(WHERE, "pushing",
00215               isprintf("%d failure in simple test", ret.value()));
00216       }
00217       if (bounder.elements() != bounder.size())
00218         deadly_error(WHERE, "bounder set", "size and max disagree");
00219 #ifdef DEBUG_STACK
00220       LOG("inverting:");
00221 #endif
00222       bounder.invert();
00223 #ifdef DEBUG_STACK
00224       LOG(istring(istring::SPRINTF, "inverted is:\n%s", text_form(bounder).s()));
00225 #endif
00226       while (bounder.size()) bounder.pop();
00227     }
00228   }
00229 }
00230 
00231 void test_stack_with_pointers()
00232 {
00233   for (int qq = 0; qq < test_iterations; qq++) {
00234 #ifdef DEBUG_STACK
00235     LOG(istring(istring::SPRINTF, "index %d", qq));
00236 #endif
00237     stack<byte_array *> bounded_stack(3);
00238     stack<byte_array *> unlimited_stack(0);
00239     chaos randomizer;
00240 
00241     {
00242 #ifdef DEBUG_STACK
00243       LOG("testing the bounded stack first:");
00244 #endif
00245       CHECK_STACK_RESULT(bounded_stack.push(generate_deep("the first line")), "first push");
00246       CHECK_STACK_RESULT(bounded_stack.push(generate_deep("the second line")), "second push");
00247       CHECK_STACK_RESULT(bounded_stack.push(generate_deep("the final and third")), "third push");
00248       byte_array *gend = generate_deep("this shouldn't work");
00249       if (bounded_stack.push(gend) != common::IS_FULL)
00250         deadly_error(WHERE, "main", "the bounded stack push didn't catch IS_FULL");
00251       delete gend;
00252 #ifdef DEBUG_STACK
00253       LOG("pushing worked successfully...");
00254       LOG("printing the stack in element order");
00255 #endif
00256       for (int i = 0; i < bounded_stack.size(); i++) {
00257 #ifdef DEBUG_STACK
00258         LOG(istring(istring::SPRINTF, "depth %d has: %s", i, bounded_stack[i]->observe()));
00259 #endif
00260       }
00261 #ifdef DEBUG_STACK
00262       LOG("now popping the stack all the way back.");
00263 #endif
00264       int full_size = bounded_stack.size();
00265       for (int j = 0; j < full_size; j++) {
00266 #ifdef DEBUG_STACK
00267         LOG(istring(istring::SPRINTF, "pop %d, stack size is %d, has %s", j+1, bounded_stack.size(), bounded_stack.top()->observe()));
00268 #endif
00269         byte_array *found;
00270         bounded_stack.acquire_pop(found);
00271         if (!found) deadly_error(WHERE, "acquire_pop test", "nil returned");
00272         if (!found->observe())
00273           deadly_error(WHERE, "acquire_pop test", "observe is nil");
00274         istring got((char *)found->observe());
00275         switch (j) {
00276         case 0: if (got != istring("the final and third"))
00277           deadly_error(WHERE, "acquire_top", "wrong contents at 2"); break;
00278         case 1: if (got != istring("the second line"))
00279           deadly_error(WHERE, "acquire_top", "wrong contents at 1"); break;
00280         case 2: if (got != istring("the first line"))
00281           deadly_error(WHERE, "acquire_top", "wrong contents at 0"); break;
00282         }
00283         delete found;
00284       }
00285       if (bounded_stack.pop() != common::IS_EMPTY)
00286         deadly_error(WHERE, "main", "bounded pop failure");
00287     }
00288 
00289     {
00290 #ifdef DEBUG_STACK
00291       LOG("testing the unbounded stack now:");
00292 #endif
00293       for (int j = 0; j < 24; j++) {
00294         istring line(istring::SPRINTF, "{posn %d here}", j);
00295         CHECK_STACK_RESULT(unlimited_stack.push(generate_deep(line.s())), "unbound push");
00296       }
00297 #ifdef DEBUG_STACK
00298       LOG("unbounded stack in element order:");
00299 #endif
00300       for (int k = 0; k < unlimited_stack.size(); k++) {
00301 #ifdef DEBUG_STACK
00302         LOG(istring(istring::SPRINTF, "#%d is %s", k, unlimited_stack[k]->observe()));
00303 #endif
00304       }
00305 #ifdef DEBUG_STACK
00306       LOG("\nnow popping order:");
00307 #endif
00308       while (unlimited_stack.size()) {
00309 #ifdef DEBUG_STACK
00310         LOG(istring(istring::SPRINTF, "size %d, content %s", unlimited_stack.size(), unlimited_stack.top()->observe()));
00311 #endif
00312         byte_array *to_zap = unlimited_stack.top();
00313         unlimited_stack.pop();
00314         delete to_zap;
00315           // okay because the pointer was copied, and the reference from top
00316           // is not being relied on.
00317       }
00318 #ifdef DEBUG_STACK
00319       LOG("");
00320 #endif
00321       if (unlimited_stack.pop() != common::IS_EMPTY)
00322         deadly_error(WHERE, "main", "pop did not return empty as expected");
00323 #ifdef DEBUG_STACK
00324       LOG("\n\
00325 ----------------------------------------------\n\
00326 both types of stack exercises were successful.\n\
00327 ----------------------------------------------");
00328 #endif
00329     }
00330 
00331 #ifdef DEBUG_STACK
00332     LOG("now setting up some simple stacks...");
00333 #endif
00334 
00335     {
00336 #ifdef DEBUG_STACK
00337       LOG("bounded first...");
00338 #endif
00339       stack<byte_array *> bounder(randomizer.inclusive(30, 80));
00340 #ifdef DEBUG_STACK
00341       LOG(istring(istring::SPRINTF, "length of bounder is max %d, curr %d",
00342           bounder.elements(), bounder.size()));
00343 #endif
00344       int max = bounder.elements();
00345       for (int i = 0; i < max; i++) {
00346         if (bounder.size() != i)
00347           deadly_error(WHERE, "bounder size", "out of step with loop");
00348         int byte_array_size = randomizer.inclusive(259, 287);
00349         byte_array *to_stuff = new byte_array(byte_array(byte_array_size));
00350         istring visible(istring::SPRINTF, "entry %d...", i);
00351         visible.stuff((char *)to_stuff->observe(), visible.length() + 1);
00352         for (int j = visible.length() + 1; j < to_stuff->length(); j++)
00353           *(to_stuff->access() + j) = '\0';
00354         if (bounder.push(to_stuff) != common::OKAY)
00355           deadly_error(WHERE, "pushing", "failure in simple test");
00356       }
00357       if (bounder.elements() != bounder.size())
00358         deadly_error(WHERE, "bounder set", "size and max disagree");
00359 #ifdef DEBUG_STACK
00360       LOG("inverting:");
00361 #endif
00362       bounder.invert();
00363 #ifdef DEBUG_STACK
00364       LOG(istring(istring::SPRINTF, "inverted is:\n%s", text_form(bounder).s()));
00365 #endif
00366       while (bounder.size()) {
00367         byte_array *to_zap = bounder.top();
00368         bounder.pop();
00369         delete to_zap;
00370       }
00371     }
00372   }
00373 }
00374 
00375 int main(int formal(argc), char *formal(argv)[])
00376 {
00377   test_stack_with_objects();
00378   test_stack_with_pointers();
00379   guards::alert_message("stack:: works for those functions tested.");
00380   return 0;
00381 }
00382 

Generated on Sat Aug 30 04:32:05 2008 for HOOPLE Libraries by  doxygen 1.5.1