00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00041
00042
00043 const int test_iterations = 40;
00044
00045 #define WHERE __WHERE__.s()
00046
00047
00048
00049
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
00316
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