1 /*****************************************************************************\
4 * Author : Chris Koeritz *
6 *******************************************************************************
7 * Copyright (c) 1991-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
16 // when this flag is turned on, extra checking will be done in the allocator.
18 #include <application/hoople_main.h>
19 #include <basis/array.h>
20 #include <basis/byte_array.h>
21 #include <basis/enhance_cpp.h>
22 #include <basis/functions.h>
23 #include <basis/astring.h>
24 #include <loggers/console_logger.h>
25 #include <loggers/critical_events.h>
26 #include <mathematics/chaos.h>
27 #include <mathematics/double_plus.h>
28 #include <timely/time_stamp.h>
29 #include <unit_test/unit_base.h>
31 ///#include <stdio.h>//temp
33 using namespace application;
34 using namespace basis;
35 using namespace loggers;
36 using namespace mathematics;
37 using namespace timely;
38 using namespace unit_test;
40 //const float MAX_TEST_DURATION_ms = 28 * SECOND_ms;
41 const float MAX_TEST_DURATION_ms = 200;
42 // each of the tests calling on the templated tester will take this long.
44 const int MAX_SIMULTANEOUS_OBJECTS = 42; // the maximum arrays tested.
46 const int MIN_OBJECT = -30; // the smallest array we'll create.
47 const int MAX_OBJECT = 98; // the largest array we'll create.
49 const int MIN_BLOCK = 100; // the smallest exemplar we'll use.
50 const int MAX_BLOCK = MAX_OBJECT * 2; // the largest exempler.
52 //#define DEBUG_TEST_ARRAY
53 // uncomment for noisy version.
55 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
57 static chaos a_randomizer;
61 class test_array : public application_shell, public unit_base
65 : application_shell(),
68 //hmmm: should go into app shell
69 ////SETUP_CONSOLE_LOGGER;
71 DEFINE_CLASS_NAME("test_array");
72 virtual int execute();
73 void dump_array(array<void *> &ar, const char *name);
74 void test_arrays_of_void_pointer();
75 void test_iteration_speed();
77 template <class contents>
78 void array_tester(test_array &ta, const contents &formal(bogus), basis::un_short flags);
84 void test_array::dump_array(array<void *> &ar, const char *name)
86 #ifdef DEBUG_TEST_ARRAY
87 FUNCDEF("dump_array");
88 LOG(a_sprintf("array named \"%s\" has:", name));
89 for (int i = 0; i < ar.length(); i++) {
90 LOG(a_sprintf("\t%4d: %d", i, (int)ar[i]));
93 if (ar.length() && name) {}
97 void test_array::test_arrays_of_void_pointer()
99 FUNCDEF("void pointer test");
100 const int MAX_VOID_ARRAY = 20;
101 array<void *> argh(MAX_VOID_ARRAY, NULL_POINTER, byte_array::SIMPLE_COPY
102 | byte_array::EXPONE | byte_array::FLUSH_INVISIBLE);
103 array<void *> argh2(argh);
104 ASSERT_EQUAL(argh.length(), MAX_VOID_ARRAY, "check first array length");
105 ASSERT_EQUAL(argh2.length(), MAX_VOID_ARRAY, "check copied array length");
106 int wrong_counter = 0;
107 for (int o = 0; o < MAX_VOID_ARRAY; o++)
108 if (argh[o] != argh2[o]) wrong_counter++;
109 ASSERT_EQUAL(wrong_counter, 0, "compare array contents");
111 // fill it with values.
113 for (int i = 0; i < MAX_VOID_ARRAY; i++)
114 argh[i] = (void *)(&starter + i);
115 dump_array(argh, "first version");
119 for (int j = 0; j < MAX_VOID_ARRAY; j++)
120 if (argh[j] != (void *)(&starter + j) ) wrong_counter++;
121 ASSERT_EQUAL(wrong_counter, 0, "compare values that were set");
123 // add a constant to the values.
124 for (int k = 0; k < MAX_VOID_ARRAY; k++)
125 argh[k] = (void *)((int *)argh[k] + 23);
126 dump_array(argh, "second version");
131 for (int n = 0; n < MAX_VOID_ARRAY; n++)
132 if (argh2[n] != (void *)(&starter + n + 23)) wrong_counter++;
133 ASSERT_EQUAL(wrong_counter, 0, "compare values that were assigned");
135 // now test that values are kept in place after rearrangement.
137 dump_array(argh, "third version");
139 for (int l = 0; l < 3; l++)
140 if (argh[l] != (void *)(&starter + l + 23)) wrong_counter++;
141 ASSERT_EQUAL(wrong_counter, 0, "zap low values test");
143 for (int m = 3; m < MAX_VOID_ARRAY - 2; m++)
144 if (argh[m] != (void *)(&starter + m + 2 + 23)) wrong_counter++;
145 ASSERT_EQUAL(wrong_counter, 0, "zap high values test");
146 //hmmm: add more tests if void pointer arrays seem in question.
151 static astring blank_string;
153 // jethro is a simple object for containment below.
157 jethro(const astring &i = blank_string) : _truck(i) {}
161 bool operator ==(const jethro &tc) const { return tc._truck == _truck; }
166 // the test_content object is an object with proper copy constructor
167 // and assignment operator that also has deep contents.
176 test_content(abyte q = 3)
177 : _q(q), _ted("bl"), _jed("orp"),
178 _ned(12, NULL_POINTER)
182 for (int i = 0; i < _ned.length(); i++)
185 for (int r = 0; r < _med.rows(); r++)
186 for (int c = 0; c < _med.columns(); c++)
187 _med[r][c] = jethro(astring((r*c) % 256, 1));
188 for (int j = 0; j < _red.rows(); j++)
189 for (int k = 0; k < _red.columns(); k++)
194 bool operator ==(const test_content &tc) const {
195 if (tc._q != _q) return false;
196 if (tc._ted != _ted) return false;
197 if (tc._jed != _jed) return false;
198 if (tc._ned.length() != _ned.length()) return false;
199 for (int i = 0; i < _ned.length(); i++)
200 if (tc._ned[i] != _ned[i]) return false;
203 if (tc._med.rows() != _med.rows()) return false;
204 if (tc._med.columns() != _med.columns()) return false;
205 for (int c = 0; c < _med.columns(); c++)
206 for (int r = 0; r < _med.rows(); r++)
207 if (tc._med.get(r, c) != _med.get(r, c)) return false;
209 if (tc._red.rows() != _red.rows()) return false;
210 if (tc._red.columns() != _red.columns()) return false;
211 for (int j = 0; j < _red.rows(); j++)
212 for (int k = 0; k < _red.columns(); k++)
213 if (tc._red.get(j, k) != _red.get(j, k)) return false;
219 operator abyte() const { return _q; }
224 template <class contents>
225 bool compare_arrays(const array<contents> &a, const array<contents> &b)
227 if (a.length() != b.length()) return false;
228 for (int i = 0; i < a.length(); i++)
229 if (a[i] != b[i]) return false;
235 // this is a templated test for arrays, with some requirements. the contents
236 // object must support a constructor that takes a simple byte, whether
237 // that's meaningful for the object or not. if your type to test doesn't
238 // have that, derive a simple object from it, give it that constructor, and
239 // then it can be used below. the object must also support comparison with
240 // == and != for this test to be used. it must also provide a conversion
241 // to integer that returns the value passed to the constructor.
243 template <class contents>
244 void test_array::array_tester(test_array &ta, const contents &formal(bogus), basis::un_short flags)
246 FUNCDEF("array_tester");
247 // the space that all training for arrays comes from.
248 contents *junk_space = new contents[MAX_OBJECT + MAX_BLOCK];
249 for (int i = 0; i < MAX_OBJECT - 1; i++)
250 junk_space[i] = contents(a_randomizer.inclusive('a', 'z'));
251 junk_space[MAX_OBJECT + MAX_BLOCK - 1] = '\0';
253 array<contents> *testers[MAX_SIMULTANEOUS_OBJECTS];
254 for (int c = 0; c < MAX_SIMULTANEOUS_OBJECTS; c++) {
255 // set up the initial array guys.
256 testers[c] = new array<contents>(a_randomizer.inclusive(MIN_OBJECT, MAX_OBJECT),
257 NULL_POINTER, flags);
258 // copy the randomized junk space into the new object.
259 for (int i = 0; i < testers[c]->length(); i++)
260 testers[c]->put(i, junk_space[i]);
263 // these are the actions we try out with the array during the test.
264 // the first and last elements must be identical to the first and last
266 enum actions { first, do_train = first, do_size, do_assign,
267 do_access, do_zap, do_resizer, do_shrink, do_reset, do_indices,
268 do_concatenating, do_concatenating2, do_subarray, do_insert,
269 do_overwrite, do_stuff, do_memory_paring, do_snarf, do_flush,
270 do_observe, last = do_observe };
272 time_stamp exit_time(MAX_TEST_DURATION_ms);
273 while (time_stamp() < exit_time) {
274 int index = a_randomizer.inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
275 int choice = a_randomizer.inclusive(first, last);
278 #ifdef DEBUG_TEST_ARRAY
279 LOG(a_sprintf("do_train"));
281 int new_size = a_randomizer.inclusive(MIN_OBJECT, MAX_OBJECT);
282 testers[index]->retrain(new_size, (contents *)junk_space);
283 int wrong_counter = 0;
284 for (int i = 0; i < new_size; i++)
285 if (junk_space[i] != (*testers[index])[i]) wrong_counter++;
286 ASSERT_EQUAL(wrong_counter, 0, "test contents after retrain");
290 #ifdef DEBUG_TEST_ARRAY
291 LOG(a_sprintf("do_size"));
293 array<contents> old_version = *testers[index];
294 bool at_front = bool(a_randomizer.inclusive(0, 1));
295 int new_size = a_randomizer.inclusive(MIN_OBJECT, MAX_OBJECT);
296 bool smaller = new_size < old_version.length();
297 int difference = absolute_value(new_size - old_version.length());
298 testers[index]->resize(new_size,
299 at_front? old_version.NEW_AT_BEGINNING
300 : old_version.NEW_AT_END);
301 if (!smaller && difference) {
302 // neuter the contents in the new section so we can compare. this
303 // space is filled with whatever the object's constructor chooses.
305 for (int i = 0; i < difference; i++)
306 testers[index]->put(i, 'Q');
308 for (int i = old_version.length();
309 i < old_version.length() + difference; i++)
310 testers[index]->put(i, 'Q');
313 // now compute an equivalent form of what the state should be.
314 array<contents> equivalent(0, NULL_POINTER, flags);
317 equivalent = old_version.subarray(difference,
318 old_version.length() - 1);
320 array<contents> blank(difference, NULL_POINTER, flags);
321 for (int i = 0; i < blank.length(); i++)
323 equivalent = blank + old_version;
327 equivalent = old_version.subarray(0, old_version.length()
330 array<contents> blank(difference, NULL_POINTER, flags);
331 for (int i = 0; i < blank.length(); i++)
333 equivalent = old_version + blank;
336 ASSERT_EQUAL(equivalent.length(), testers[index]->length(),
337 "check length of resized form");
338 ASSERT_TRUE(compare_arrays(*testers[index], equivalent),
339 "check contents of resized form");
343 #ifdef DEBUG_TEST_ARRAY
344 LOG(a_sprintf("do_assign"));
346 array<contents> arrh = *testers[index]; // copy old value.
347 int to_assign = a_randomizer.inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
348 *testers[index] = *testers[to_assign];
349 ASSERT_TRUE(compare_arrays(*testers[index], *testers[to_assign]),
350 "check result of assign copying array");
351 *testers[to_assign] = arrh; // recopy contents to new place.
352 ASSERT_TRUE(compare_arrays(*testers[to_assign], arrh),
353 "check result of second assign");
357 #ifdef DEBUG_TEST_ARRAY
358 LOG(a_sprintf("do_access"));
360 int start = a_randomizer.inclusive(0, testers[index]->length());
361 int end = a_randomizer.inclusive(0, testers[index]->length());
362 flip_increasing(start, end);
363 array<contents> accumulator(0, NULL_POINTER, flags);
364 for (int i = start; i < end; i++) {
365 contents c = contents(a_randomizer.inclusive(1, 255));
366 testers[index]->access()[i] = c;
369 for (int j = start; j < end; j++)
370 ASSERT_EQUAL(accumulator[j - start], (*testers[index])[j],
371 "comparison accessing at index must be equal");
375 #ifndef CATCH_ERRORS // only works if not catching errors.
376 #ifdef DEBUG_TEST_ARRAY
377 LOG(a_sprintf("do_indices"));
379 // does some tests on bad indices.
380 contents c1 = testers[index]->operator[](-50);
381 contents c2 = testers[index]->operator[](-MAX_OBJECT);
382 bool test = (c1 == c2);
383 ASSERT_TRUE(test, "invalid values should be the same");
384 int tests = a_randomizer.inclusive(100, 500);
385 for (int i = 0; i < tests; i++) {
386 int indy = a_randomizer.inclusive(-1000, MAX_OBJECT * 3);
387 // testing if we can access without explosions.
388 contents c3 = testers[index]->operator[](indy);
390 ASSERT_EQUAL(c3, c4, "for do_indices, values should be the same");
396 #ifdef DEBUG_TEST_ARRAY
397 LOG(a_sprintf("do_observe"));
399 // tests contents returned by observe.
400 int start = a_randomizer.inclusive(0, testers[index]->length());
401 int end = a_randomizer.inclusive(0, testers[index]->length());
402 flip_increasing(start, end);
404 for (int i = start; i < end; i++)
405 total_1 += testers[index]->observe()[i];
407 for (int j = end - 1; j >= start; j--)
408 total_2 += testers[index]->observe()[j];
409 ASSERT_EQUAL(total_1, total_2, "totals should match up");
413 #ifdef DEBUG_TEST_ARRAY
414 LOG(a_sprintf("do_resizer"));
416 // tests whether the array will reuse space when it should be able to.
417 array<contents> &arrh = *testers[index];
418 // fill with known data.
420 for (i = 0; i < arrh.length(); i++)
421 arrh[i] = contents((i + 23) % 256);
422 // record the old starting point.
423 const contents *start = arrh.internal_block_start();
424 int zap_amount = a_randomizer.inclusive(1, arrh.length() - 1);
425 // now take out a chunk from the array at the beginning.
426 arrh.zap(0, zap_amount - 1);
427 // test the contents.
428 for (i = 0; i < arrh.length(); i++)
429 ASSERT_EQUAL(arrh[i], contents((i + 23 + zap_amount) % 256),
430 "the resized form should have same contents after zap");
431 // now add back in the space we ate.
432 arrh.resize(arrh.length() + zap_amount, arrh.NEW_AT_END);
433 // check the pointer; it should not have changed.
434 ASSERT_EQUAL(start, arrh.internal_block_start(),
435 "the resized form should have same start address");
436 // test the contents again. they should start at zero and have the
437 // same zap_amount offset. the stuff past the original point shouldn't
438 // be tested since we haven't set it.
439 for (i = 0; i < arrh.length() - zap_amount; i++)
440 ASSERT_EQUAL(arrh[i], contents((i + 23 + zap_amount) % 256),
441 "the resized form should still have same contents");
442 // now a test of all values through the zap_amount.
443 arrh.zap(0, zap_amount - 1);
444 for (i = 0; i < zap_amount; i++) {
445 arrh.resize(arrh.length() + 1, arrh.NEW_AT_END);
446 ASSERT_EQUAL(start, arrh.internal_block_start(),
447 "the slowly resized form should have same start address");
449 // test the contents once more. they should start at zero and have
450 // double the zap_amount offset. the stuff past the original point
451 // shouldn't be tested since we haven't set it.
452 for (i = 0; i < arrh.length() - 2 * zap_amount; i++)
453 ASSERT_EQUAL(arrh[i], contents((i + 23 + 2 * zap_amount) % 256),
454 "the slowly resized form should have same contents");
456 // the tests below should be nearly identical to the ones above, but
457 // they use the NEW_AT_BEGINNING style of copying.
459 // fill with known data.
460 for (i = 0; i < arrh.length(); i++)
461 arrh[i] = contents((i + 23) % 256);
462 // record the old starting point.
463 start = arrh.internal_block_start();
464 zap_amount = a_randomizer.inclusive(1, arrh.length() - 1);
465 // now take out a chunk from the array at the beginning.
466 arrh.zap(0, zap_amount - 1);
467 // test the contents.
468 for (i = 0; i < arrh.length(); i++)
469 ASSERT_EQUAL(arrh[i], contents((i + 23 + zap_amount) % 256),
470 "the resized form with known data should have right contents");
471 // now add back in the space we ate.
472 arrh.resize(arrh.length() + zap_amount,
473 arrh.NEW_AT_BEGINNING);
474 // check the pointer; it should not have changed.
475 ASSERT_EQUAL(start, arrh.internal_block_start(),
476 "the resized form with known data should have same start address");
477 // test the contents again. they should start at zap_amount but have
478 // the same zap_amount offset. the stuff before the original point
479 // shouldn't be tested since we haven't set it.
480 for (i = zap_amount; i < arrh.length(); i++)
481 ASSERT_EQUAL(arrh[i], contents((i + 23) % 256),
482 "the known data resized form should have same contents");
483 // now a test of all values through the zap_amount.
484 arrh.zap(0, zap_amount - 1);
485 for (i = 0; i < zap_amount; i++) {
486 arrh.resize(arrh.length() + 1, arrh.NEW_AT_BEGINNING);
487 ASSERT_EQUAL(start, arrh.internal_block_start(),
488 "the known data slowly resized form should have same start address");
490 // test the contents once more. the zap_amount offset should stay the
491 // same since we clobbered the place we added originally, then added
492 // more space in. so we skip the first part still.
493 for (i = zap_amount; i < arrh.length(); i++)
494 ASSERT_EQUAL(arrh[i], contents((i + 23) % 256),
495 "the known data slowly resized form should have same contents");
499 #ifdef DEBUG_TEST_ARRAY
500 LOG(a_sprintf("do_zap"));
504 bool erroneous = false;
505 int chose = a_randomizer.inclusive(1, 100);
507 // there's a ninety percent chance we pick a range that's valid.
508 start = a_randomizer.inclusive(0, testers[index]->length() - 1);
509 end = a_randomizer.inclusive(0, testers[index]->length() - 1);
510 } else if (chose <= 95) {
511 // and a 5 percent chance we pick to choose the zero index as our
512 // start; this gets at the code for fast zapping.
514 end = a_randomizer.inclusive(0, testers[index]->length() - 1);
516 // and a 5 percent chance we'll allow picking a bad index. the
517 // actual chance of picking a bad one is less.
519 start = a_randomizer.inclusive(-2, testers[index]->length() + 3);
520 end = a_randomizer.inclusive(-2, testers[index]->length() + 3);
522 flip_increasing(start, end);
523 array<contents> old_version = *testers[index];
524 testers[index]->zap(start, end);
526 array<contents> old_head = old_version.subarray(0, start - 1);
527 array<contents> old_tail = old_version.subarray(end + 1,
528 old_version.length() - 1);
529 array<contents> equivalent = old_head + old_tail;
530 ASSERT_EQUAL(equivalent.length(), testers[index]->length(),
531 "the zapped form should not have erroneous length");
532 ASSERT_TRUE(compare_arrays(*testers[index], equivalent),
533 "the zapped form should not have erroneous contents");
538 #ifdef DEBUG_TEST_ARRAY
539 LOG(a_sprintf("do_reset"));
541 int junk_start = a_randomizer.inclusive(MIN_BLOCK, MAX_BLOCK);
542 int junk_end = a_randomizer.inclusive(MIN_BLOCK, MAX_BLOCK);
543 flip_increasing(junk_start, junk_end);
544 int len = junk_end - junk_start + 1;
545 testers[index]->reset(len, (contents *)&junk_space[junk_start]);
546 ASSERT_EQUAL(testers[index]->length(), len, "reset should have proper length");
547 for (int i = 0; i < len; i++)
548 ASSERT_EQUAL(testers[index]->get(i), junk_space[junk_start + i],
549 "reset should copy data");
553 #ifdef DEBUG_TEST_ARRAY
554 LOG(a_sprintf("do_shrink"));
556 array<contents> garp = *testers[index];
557 testers[index]->shrink();
558 int new_diff = testers[index]->internal_real_length()
559 - testers[index]->length();
560 ASSERT_TRUE(compare_arrays(garp, *testers[index]), "shrink should keep contents");
561 // now force a real shrinkage.
562 if (testers[index]->length() < 5) continue; // need some room.
563 // pick an element to keep that is not first or last.
564 int kept = a_randomizer.inclusive(1, testers[index]->last() - 1);
565 // whack all but the lucky element.
566 testers[index]->zap(kept + 1, testers[index]->last());
567 testers[index]->zap(0, kept - 1);
568 // shrink it again, now a big shrink.
569 testers[index]->shrink();
570 // check the difference now.
571 new_diff = testers[index]->internal_real_length()
572 - testers[index]->length();
573 ASSERT_FALSE(new_diff > 1, "massive shrink size should be correct");
575 // restore the original contents and block size.
576 *testers[index] = garp;
579 case do_concatenating: {
580 #ifdef DEBUG_TEST_ARRAY
581 LOG(a_sprintf("do_concatenating"));
583 for (int i = 0; i < a_randomizer.inclusive(1, 20); i++) {
584 contents new_c = contents(a_randomizer.inclusive('a', 'z'));
585 testers[index]->concatenate(new_c);
586 ASSERT_EQUAL(new_c, testers[index]->get(testers[index]->last()),
587 "value should be equal after concatenate");
589 int indy = a_randomizer.inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
590 array<contents> flirpan = *testers[indy];
591 int start = a_randomizer.inclusive(0, flirpan.length() - 1);
592 int end = a_randomizer.inclusive(0, flirpan.length() - 1);
593 flip_increasing(start, end);
594 flirpan = flirpan.subarray(start, end);
595 array<contents> grumzor = *testers[index]; // old copy.
596 testers[index]->concatenate(flirpan);
597 array<contents> bubula = grumzor + flirpan;
598 ASSERT_TRUE(compare_arrays(bubula, *testers[index]),
599 "contents should be correct after concatenate or concatenation");
600 contents first_value;
601 contents second_value;
602 if (testers[index]->length() >= 1)
603 first_value = testers[index]->get(0);
604 if (testers[index]->length() >= 2)
605 second_value = testers[index]->get(1);
606 const int max_iters = a_randomizer.inclusive(1, 42);
607 for (int j = 0; j < max_iters; j++) {
608 contents new_c = contents(a_randomizer.inclusive('a', 'z'));
609 *testers[index] = *testers[index] + new_c;
610 // correct our value checks if new indices became available.
611 if (testers[index]->length() == 1) {
612 first_value = testers[index]->get(0);
613 } else if (testers[index]->length() == 2) {
614 second_value = testers[index]->get(1);
617 ASSERT_EQUAL(new_c, testers[index]->get(testers[index]->last()),
618 "value should not be wrong after concatenation");
620 ASSERT_FALSE((testers[index]->length() >= 1) && (first_value != testers[index]->get(0)),
621 "first value should not be corrupted");
622 ASSERT_FALSE((testers[index]->length() >= 2) && (second_value != testers[index]->get(1)),
623 "second value should not be corrupted");
625 *testers[index] += new_c;
626 // we don't have to correct the first value any more, but might have
627 // to correct the second.
628 if (testers[index]->length() == 2) {
629 second_value = testers[index]->get(1);
631 ASSERT_EQUAL(new_c, testers[index]->get(testers[index]->last()),
632 "value should be right after second concatenation");
633 ASSERT_FALSE( (testers[index]->length() >= 1) && (first_value != testers[index]->get(0)),
634 "first value should be uncorrupted after second concat");
635 ASSERT_FALSE((testers[index]->length() >= 2) && (second_value != testers[index]->get(1)),
636 "second value should be uncorrupted after second concat");
640 case do_concatenating2: {
641 // this tests the new concatenate content array method for array.
642 #ifdef DEBUG_TEST_ARRAY
643 LOG(a_sprintf("do_concatenating2"));
645 array<contents> &flirpan = *testers[index];
646 int new_len = a_randomizer.inclusive(0, 140);
647 contents *to_add = new contents[new_len];
648 for (int i = 0; i < new_len; i++) {
649 int rando = a_randomizer.inclusive(0, MAX_BLOCK - 1);
650 to_add[i] = junk_space[rando];
652 int old_len = flirpan.length();
653 flirpan.concatenate(to_add, new_len);
654 for (int i = 0; i < new_len; i++) {
655 ASSERT_EQUAL(flirpan[i + old_len], to_add[i],
656 "value should not be wrong after content array concatenation");
658 delete [] to_add; // clean up.
662 #ifdef DEBUG_TEST_ARRAY
663 LOG(a_sprintf("do_subarray"));
665 array<contents> flirpan = *testers[index];
666 int start = a_randomizer.inclusive(0, flirpan.length() - 1);
667 int end = a_randomizer.inclusive(0, flirpan.length() - 1);
668 flip_increasing(start, end);
669 flirpan = flirpan.subarray(start, end);
670 for (int i = 0; i < end - start; i++)
671 ASSERT_EQUAL(flirpan[i], testers[index]->get(i + start),
672 "subarray should produce right array");
675 case do_memory_paring: {
676 #ifdef DEBUG_TEST_ARRAY
677 LOG(a_sprintf("do_memory_paring"));
679 for (int i = 0; i < MAX_SIMULTANEOUS_OBJECTS; i++) {
680 // zap extra junk off so we bound the memory usage.
681 if (testers[i]->length() > MAX_OBJECT) {
682 testers[i]->zap(MAX_OBJECT, testers[i]->length() - 1);
683 testers[i]->shrink();
689 #ifdef DEBUG_TEST_ARRAY
690 LOG(a_sprintf("do_snarf"));
692 array<contents> flirpan = *testers[index];
693 // int start = a_randomizer.inclusive(0, flirpan.length() - 1);
694 // int end = a_randomizer.inclusive(0, flirpan.length() - 1);
695 // flip_increasing(start, end);
696 // flirpan = flirpan.subarray(start, end);
697 int rand_index = a_randomizer.inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
698 if (index == rand_index) continue; // skip it; try again later.
699 array<contents> nugwort = *testers[rand_index];
700 // perform a swap between two of our arrays.
701 array<contents> temp_hold(0, NULL_POINTER, flags);
702 temp_hold.snarf(*testers[index]);
703 testers[index]->snarf(*testers[rand_index]);
704 testers[rand_index]->snarf(temp_hold);
705 // the copies should have flipped places now. check them.
706 ASSERT_EQUAL(flirpan.length(), testers[rand_index]->length(),
707 "snarf needs to produce right length at A");
708 for (int i = 0; i < flirpan.length(); i++)
709 ASSERT_EQUAL(flirpan[i], testers[rand_index]->get(i),
710 "snarf needs to produce right array at A");
711 ASSERT_EQUAL(nugwort.length(), testers[index]->length(),
712 "snarf needs to produce right length at B");
713 for (int j = 0; j < nugwort.length(); j++)
714 ASSERT_EQUAL(nugwort[j], testers[index]->get(j),
715 "snarf needs to produce right array at B");
719 #ifdef DEBUG_TEST_ARRAY
720 LOG(a_sprintf("do_flush"));
722 array<contents> flirpan = *testers[index];
724 ///fix up it up in it.
733 #ifdef DEBUG_TEST_ARRAY
734 LOG(a_sprintf("do_insert"));
736 array<contents> hold = *testers[index];
737 int where = a_randomizer.inclusive(0, hold.last());
738 int how_many = a_randomizer.inclusive(0, 25);
739 testers[index]->insert(where, how_many);
740 for (int i = 0; i < where; i++)
741 ASSERT_EQUAL(hold[i], testers[index]->get(i),
742 "should have good contents on left after insert");
743 for (int j = where + how_many; j < testers[index]->length(); j++)
744 ASSERT_EQUAL(hold[j - how_many], testers[index]->get(j),
745 "should have good contents on right after insert");
749 #ifdef DEBUG_TEST_ARRAY
750 LOG(a_sprintf("do_overwrite"));
752 if (!testers[index]->length()) continue;
753 array<contents> hold = *testers[index];
755 while (index2 == index)
756 index2 = a_randomizer.inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
757 array<contents> &hold2 = *testers[index2];
758 if (!hold2.length()) continue;
759 int write_indy = a_randomizer.inclusive(0, hold.last());
760 int write_len = minimum(hold2.length(), (hold.length() - write_indy));
761 // LOG(a_sprintf("len1 = %d len2 = %d wrindy=%d wrlen=%d", hold.length(), hold2.length(), write_indy, write_len));
762 outcome ret = testers[index]->overwrite(write_indy,
763 *testers[index2], write_len);
764 ASSERT_EQUAL(ret.value(), common::OKAY,
765 astring("should not have had outcome=") + common::outcome_name(ret));
766 for (int i = 0; i < write_indy; i++)
767 ASSERT_EQUAL(hold[i], testers[index]->get(i),
768 "should have good contents on left after overwrite");
769 for (int j = write_indy; j < write_indy + write_len; j++)
770 ASSERT_EQUAL(hold2[j - write_indy], testers[index]->get(j),
771 "should have good contents in middle after overwrite");
772 for (int k = write_indy + write_len; k < testers[index]->length(); k++)
773 ASSERT_EQUAL(hold[k], testers[index]->get(k),
774 "should have good contents on right after overwrite");
778 #ifdef DEBUG_TEST_ARRAY
779 LOG(a_sprintf("do_stuff"));
781 array<contents> &hold = *testers[index];
782 contents burgers[100];
783 int stuff_len = a_randomizer.inclusive(0, hold.length());
784 stuff_len = minimum(stuff_len, 100);
785 outcome ret = hold.stuff(stuff_len, burgers);
786 ASSERT_EQUAL(ret.value(), common::OKAY,
787 astring("should not have had outcome=") + common::outcome_name(ret));
788 for (int i = 0; i < stuff_len; i++)
789 ASSERT_EQUAL(burgers[i], hold[i],
790 "should have good contents after stuff");
794 ASSERT_FALSE(true, "test cases should have no invalid choices!");
801 delete [] junk_space;
802 for (int d = 0; d < MAX_SIMULTANEOUS_OBJECTS; d++) delete testers[d];
807 struct gerkin { int l; abyte *p; char *r; void *pffttt; };
815 virtual gerkin *boorba() = 0;
818 class boop : public foop
821 virtual gerkin *boorba() { return &borgia; }
824 void test_array::test_iteration_speed()
826 FUNCDEF("test_iteration_speed");
827 const int MAX_CHUNK = 100000;
828 const int MAX_REPS = 20;
829 byte_array chunky(MAX_CHUNK);
834 for (int j = 0; j < MAX_REPS; j++) {
835 for (int i = 0; i < MAX_CHUNK; i++) {
839 int duration = int(time_stamp().value() - start.value());
841 a_sprintf message("iteration over %d elements took %d ms,\t"
842 "or %f ms per 1000 iters.",
843 MAX_CHUNK * MAX_REPS, duration,
844 double(duration) / double(MAX_CHUNK * MAX_REPS) * 1000.0);
845 //base_logger &b = program_wide_logger::get();
852 const abyte *head = chunky.observe();
853 for (int j = 0; j < MAX_REPS; j++) {
854 for (int i = 0; i < MAX_CHUNK; i++) {
858 int duration = int(time_stamp().value() - start.value());
860 LOG(a_sprintf("less-safe iteration over %d elements took %d ms,\tor %f ms per 1000 iters.",
861 MAX_CHUNK * MAX_REPS, duration,
862 double(duration) / double(MAX_CHUNK * MAX_REPS) * 1000.0));
868 for (int j = 0; j < MAX_REPS; j++) {
869 for (int i = 0; i < MAX_CHUNK; i++) {
870 // chunky.modus().sampler();
874 int duration = int(time_stamp().value() - start.value());
876 LOG(a_sprintf("virtual-function-only over %d elements took %d ms,\tor %f ms per 1000 iters.",
877 MAX_CHUNK * MAX_REPS, duration,
878 double(duration) / double(MAX_CHUNK * MAX_REPS) * 1000.0));
884 int test_array::execute()
888 // if enabled for the abusive type tests, then allow this one...
889 test_iteration_speed();
890 // LOG(a_sprintf("did iteration test."));
893 int_array checking_start;
894 ASSERT_FALSE(checking_start.length(),
895 "int_array should not have contents from empty constructor");
897 double_plus bogus4 = float(12.32);
898 array_tester<double_plus >(*this, bogus4,
899 byte_array::SIMPLE_COPY | byte_array::EXPONE
900 | byte_array::FLUSH_INVISIBLE);
901 // LOG(a_sprintf("did float array test."));
904 array_tester<int>(*this, bogus2,
905 byte_array::SIMPLE_COPY | byte_array::EXPONE
906 | byte_array::FLUSH_INVISIBLE);
907 // LOG(a_sprintf("did int array test."));
909 test_content bogus3(12);
910 array_tester<test_content>(*this, bogus3, byte_array::EXPONE
911 | byte_array::FLUSH_INVISIBLE);
912 // LOG(a_sprintf("did test_content array test."));
914 test_arrays_of_void_pointer();
915 // LOG(a_sprintf("did void * array test."));
918 array_tester<abyte>(*this, bogus1,
919 byte_array::SIMPLE_COPY | byte_array::EXPONE
920 | byte_array::FLUSH_INVISIBLE);
921 // LOG(a_sprintf("did byte array test."));
923 //// LOG("array:: works for those functions tested.");
925 return final_report();
928 HOOPLE_MAIN(test_array, )