3 * Author : Chris Koeritz
5 * Tests out the stack object with both flat objects (byte_array) but also
6 * deep objects (pointer to byte_array). Both bounded and unbounded stacks
9 * Copyright (c) 1992-$now By Author. This program is free software; you can *
10 * redistribute it and/or modify it under the terms of the GNU General Public *
11 * License as published by the Free Software Foundation; either version 2 of *
12 * the License or (at your option) any later version. This is online at: *
13 * http://www.fsf.org/copyleft/gpl.html *
14 * Please send any updates to: fred@gruntose.com *
15 \*****************************************************************************/
17 #include <application/hoople_main.h>
18 #include <basis/byte_array.h>
19 #include <basis/guards.h>
20 #include <basis/astring.h>
21 #include <loggers/program_wide_logger.h>
22 #include <mathematics/chaos.h>
23 #include <structures/stack.h>
24 #include <structures/static_memory_gremlin.h>
25 #include <unit_test/unit_base.h>
28 #define LOG(to_print) EMERGENCY_LOG(program_wide_logger::get(), to_print)
34 using namespace application;
35 using namespace basis;
36 ///using namespace configuration;
37 using namespace mathematics;
38 using namespace filesystem;
39 using namespace loggers;
40 using namespace structures;
41 using namespace textual;
42 using namespace timely;
43 using namespace unit_test;
45 //HOOPLE_STARTUP_CODE;
48 // uncomment for a noisier version.
50 const int test_iterations = 40;
53 class test_stack : public virtual unit_base, public virtual application_shell
57 DEFINE_CLASS_NAME("test_stack");
60 void test_stack_with_objects();
61 void test_stack_with_pointers();
63 void CHECK_STACK_RESULT(outcome retval, const astring &place);
64 byte_array generate_flat(const char *to_store);
65 byte_array *generate_deep(const char *to_store);
66 astring text_form(stack<byte_array *> &s);
67 astring text_form(stack<byte_array> &s);
70 // CHECK_STACK_RESULT: a function that takes care of error testing for a
71 // stack command. if executing the command ends in full or empty, then
73 void test_stack::CHECK_STACK_RESULT(outcome retval, const astring &place)
76 if (retval == common::IS_FULL)
77 LOG(astring(astring::SPRINTF, "returned IS_FULL at %s", place.s()))
78 else if (retval == common::IS_EMPTY)
79 LOG(astring(astring::SPRINTF, "returned IS_EMPTY at %s", place.s()));
81 if (retval.value() || !place) {}
85 byte_array test_stack::generate_flat(const char *to_store)
87 byte_array to_return = byte_array(int(strlen(to_store) + 1), (abyte *)to_store);
91 byte_array *test_stack::generate_deep(const char *to_store)
93 byte_array *to_return = new byte_array(int(strlen(to_store) + 1),
98 astring test_stack::text_form(stack<byte_array *> &s)
101 for (int i = 0; i < s.elements(); i++) {
102 to_return += astring(astring::SPRINTF, "#%d: %s\n", i, s[i]->observe());
107 astring test_stack::text_form(stack<byte_array> &s)
110 for (int i = 0; i < s.elements(); i++) {
111 to_return += astring(astring::SPRINTF, "#%d: %s\n", i, s[i].observe());
116 void test_stack::test_stack_with_objects()
118 FUNCDEF("test_stack_with_objects");
119 for (int qq = 0; qq < test_iterations; qq++) {
121 LOG(astring(astring::SPRINTF, "index %d", qq));
123 stack<byte_array > bounded_stack(3);
124 stack<byte_array > unlimited_stack(0);
129 LOG("testing the bounded stack first:");
131 CHECK_STACK_RESULT(bounded_stack.push(generate_flat("the first line")), "first push");
132 CHECK_STACK_RESULT(bounded_stack.push(generate_flat("the second line")), "second push");
133 CHECK_STACK_RESULT(bounded_stack.push(generate_flat("the final and third")), "third push");
134 byte_array gend = generate_flat("this shouldn't work");
135 ASSERT_EQUAL(bounded_stack.push(gend).value(), common::IS_FULL,
136 "the bounded stack push should catch IS_FULL");
138 LOG("pushing worked successfully...");
139 LOG("printing the stack in element order");
141 for (int i = 0; i < bounded_stack.size(); i++) {
143 LOG(astring(astring::SPRINTF, "depth %d has %s.", i,
144 bounded_stack[i].observe()));
148 LOG("now popping the stack all the way back.");
150 int full_size = bounded_stack.size();
151 for (int j = 0; j < full_size; j++) {
153 LOG(astring(astring::SPRINTF, "pop %d, stack size is %d, has %s", j+1,
154 bounded_stack.size(), bounded_stack.top().observe()));
157 bounded_stack.acquire_pop(found);
158 astring got((char *)found.observe());
161 ASSERT_EQUAL(got, astring("the final and third"),
162 "acquire_pop should have right contents at 2");
165 ASSERT_EQUAL(got, astring("the second line"),
166 "acquire_pop should have right contents at 1");
169 ASSERT_EQUAL(got, astring("the first line"),
170 "acquire_pop should have right contents at 0");
174 ASSERT_EQUAL(bounded_stack.pop().value(), common::IS_EMPTY,
175 "bounded pop should have right outcome");
180 LOG("testing the unbounded stack now:");
182 for (int j = 0; j < 24; j++) {
183 astring line(astring::SPRINTF, "{posn %d here}", j);
184 CHECK_STACK_RESULT(unlimited_stack.push(generate_flat(line.s())), "unbound push");
187 LOG("unbounded stack in element order:");
189 for (int k = 0; k < unlimited_stack.size(); k++) {
191 LOG(astring(astring::SPRINTF, "#%d is %s", k, unlimited_stack[k].observe()));
195 LOG("now popping fresh order:");
197 while (unlimited_stack.size()) {
199 LOG(astring(astring::SPRINTF, "size %d, content %s",
200 unlimited_stack.size(), unlimited_stack.top().observe()));
202 unlimited_stack.pop();
207 ASSERT_EQUAL(unlimited_stack.pop().value(), common::IS_EMPTY,
208 "unlimited pop should return empty as expected");
211 ----------------------------------------------\n\
212 both types of stack exercises were successful.\n\
213 ----------------------------------------------");
218 LOG("now setting up some simple stacks...");
223 LOG("bounded first...");
225 stack<byte_array > bounder(randomizer.inclusive(30, 80));
227 LOG(astring(astring::SPRINTF, "length of bounder is max %d, curr %d", bounder.elements(), bounder.size()));
229 int max = bounder.elements();
230 for (int i = 0; i < max; i++) {
231 ASSERT_EQUAL(bounder.size(), i, "the bounder size should be in step with loop");
232 int byte_array_size = randomizer.inclusive(259, 287);
233 byte_array to_stuff(byte_array_size);
234 astring visible(astring::SPRINTF, "entry %d...", i);
235 visible.stuff((char *)to_stuff.access(), visible.length() + 1);
236 for (int j = visible.length() + 1; j < to_stuff.length(); j++)
237 *(to_stuff.access() + j) = '\0';
239 LOG(astring(astring::SPRINTF, "pushing index %d", i));
241 outcome ret = bounder.push(to_stuff);
242 ASSERT_EQUAL(ret.value(), common::OKAY, "pushing should not fail in simple test");
244 ASSERT_EQUAL(bounder.elements(), bounder.size(), "bounder set should see size and max same");
250 LOG(astring(astring::SPRINTF, "inverted is:\n%s", text_form(bounder).s()));
252 while (bounder.size()) bounder.pop();
257 void test_stack::test_stack_with_pointers()
259 FUNCDEF("test_stack_with_pointers")
260 for (int qq = 0; qq < test_iterations; qq++) {
262 LOG(astring(astring::SPRINTF, "index %d", qq));
264 stack<byte_array *> bounded_stack(3);
265 stack<byte_array *> unlimited_stack(0);
270 LOG("testing the bounded stack first:");
272 CHECK_STACK_RESULT(bounded_stack.push(generate_deep("the first line")), "first push");
273 CHECK_STACK_RESULT(bounded_stack.push(generate_deep("the second line")), "second push");
274 CHECK_STACK_RESULT(bounded_stack.push(generate_deep("the final and third")), "third push");
275 byte_array *gend = generate_deep("this shouldn't work");
276 ASSERT_EQUAL(bounded_stack.push(gend).value(), common::IS_FULL,
277 "the bounded stack push should catch IS_FULL");
280 LOG("pushing worked successfully...");
281 LOG("printing the stack in element order");
283 for (int i = 0; i < bounded_stack.size(); i++) {
285 LOG(astring(astring::SPRINTF, "depth %d has: %s", i, bounded_stack[i]->observe()));
289 LOG("now popping the stack all the way back.");
291 int full_size = bounded_stack.size();
292 for (int j = 0; j < full_size; j++) {
294 LOG(astring(astring::SPRINTF, "pop %d, stack size is %d, has %s", j+1, bounded_stack.size(), bounded_stack.top()->observe()));
297 bounded_stack.acquire_pop(found);
298 ASSERT_TRUE(found, "acquire_pop test should not return nil");
299 ASSERT_TRUE(found->observe(), "acquire_pop test should have non-nil observe");
300 astring got((char *)found->observe());
303 ASSERT_EQUAL(got, astring("the final and third"),
304 "popping should have right contents at 2");
307 ASSERT_EQUAL(got, astring("the second line"),
308 "popping should have right contents at 1");
311 ASSERT_EQUAL(got, astring("the first line"),
312 "popping should have right contents at 0");
317 ASSERT_EQUAL(bounded_stack.pop().value(), common::IS_EMPTY,
318 "bounded pop failure in result");
323 LOG("testing the unbounded stack now:");
325 for (int j = 0; j < 24; j++) {
326 astring line(astring::SPRINTF, "{posn %d here}", j);
327 CHECK_STACK_RESULT(unlimited_stack.push(generate_deep(line.s())), "unbound push");
330 LOG("unbounded stack in element order:");
332 for (int k = 0; k < unlimited_stack.size(); k++) {
334 LOG(astring(astring::SPRINTF, "#%d is %s", k, unlimited_stack[k]->observe()));
338 LOG("\nnow popping order:");
340 while (unlimited_stack.size()) {
342 LOG(astring(astring::SPRINTF, "size %d, content %s", unlimited_stack.size(), unlimited_stack.top()->observe()));
344 byte_array *to_zap = unlimited_stack.top();
345 unlimited_stack.pop();
347 // okay because the pointer was copied, and the reference from top
348 // is not being relied on.
353 ASSERT_EQUAL(unlimited_stack.pop().value(), common::IS_EMPTY,
354 "unlimited pop should return empty as expected");
357 ----------------------------------------------\n\
358 both types of stack exercises were successful.\n\
359 ----------------------------------------------");
364 LOG("now setting up some simple stacks...");
369 LOG("bounded first...");
371 stack<byte_array *> bounder(randomizer.inclusive(30, 80));
373 LOG(astring(astring::SPRINTF, "length of bounder is max %d, curr %d",
374 bounder.elements(), bounder.size()));
376 int max = bounder.elements();
377 for (int i = 0; i < max; i++) {
378 ASSERT_EQUAL(bounder.size(), i, "bounder size should remain in step with loop");
379 int byte_array_size = randomizer.inclusive(259, 287);
380 byte_array *to_stuff = new byte_array(byte_array(byte_array_size));
381 astring visible(astring::SPRINTF, "entry %d...", i);
382 visible.stuff((char *)to_stuff->observe(), visible.length() + 1);
383 for (int j = visible.length() + 1; j < to_stuff->length(); j++)
384 *(to_stuff->access() + j) = '\0';
385 ASSERT_EQUAL(bounder.push(to_stuff).value(), common::OKAY,
386 "pushing should not fail in bound simple test");
388 ASSERT_EQUAL(bounder.elements(), bounder.size(), "bounder set must have size and max agree");
394 LOG(astring(astring::SPRINTF, "inverted is:\n%s", text_form(bounder).s()));
396 while (bounder.size()) {
397 byte_array *to_zap = bounder.top();
405 int test_stack::execute()
407 test_stack_with_objects();
408 test_stack_with_pointers();
409 return final_report();
412 HOOPLE_MAIN(test_stack, )