34 using namespace basis;
55 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
57 static chaos a_randomizer;
72 virtual int execute();
74 void test_arrays_of_void_pointer();
75 void test_iteration_speed();
77 template <
class contents>
84 void test_array::dump_array(
array<void *> &ar,
const char *name)
86 #ifdef DEBUG_TEST_ARRAY
89 for (
int i = 0; i < ar.
length(); i++) {
93 if (ar.
length() && name) {}
97 void test_array::test_arrays_of_void_pointer()
100 const int MAX_VOID_ARRAY = 20;
102 | byte_array::EXPONE | byte_array::FLUSH_INVISIBLE);
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");
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");
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");
137 dump_array(argh,
"third version");
139 for (
int l = 0; l < 3; l++)
140 if (argh[l] != (
void *)(&starter + l + 23)) wrong_counter++;
143 for (
int m = 3; m < MAX_VOID_ARRAY - 2; m++)
144 if (argh[m] != (
void *)(&starter + m + 2 + 23)) wrong_counter++;
157 jethro(
const astring &i = blank_string) : _truck(i) {}
161 bool operator ==(
const jethro &tc)
const {
return tc._truck == _truck; }
176 test_content(
abyte q = 3)
177 : _q(q), _ted(
"bl"), _jed(
"orp"),
182 for (
int i = 0; i < _ned.
length(); i++)
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;
219 operator abyte()
const {
return _q; }
224 template <
class contents>
228 for (
int i = 0; i < a.
length(); i++)
229 if (a[i] != b[i])
return false;
243 template <
class contents>
250 junk_space[i] = contents(a_randomizer.
inclusive(
'a',
'z'));
259 for (
int i = 0; i < testers[c]->
length(); i++)
260 testers[c]->put(i, junk_space[i]);
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 };
275 int choice = a_randomizer.
inclusive(first, last);
278 #ifdef DEBUG_TEST_ARRAY
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
294 bool at_front = bool(a_randomizer.
inclusive(0, 1));
296 bool smaller = new_size < old_version.
length();
298 testers[index]->
resize(new_size,
301 if (!smaller && difference) {
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');
317 equivalent = old_version.
subarray(difference,
318 old_version.
length() - 1);
321 for (
int i = 0; i < blank.length(); i++)
323 equivalent = blank + old_version;
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");
339 "check contents of resized form");
343 #ifdef DEBUG_TEST_ARRAY
348 *testers[index] = *testers[to_assign];
350 "check result of assign copying array");
351 *testers[to_assign] = arrh;
353 "check result of second assign");
357 #ifdef DEBUG_TEST_ARRAY
360 int start = a_randomizer.
inclusive(0, testers[index]->length());
361 int end = a_randomizer.
inclusive(0, testers[index]->length());
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");
376 #ifdef DEBUG_TEST_ARRAY
380 contents c1 = testers[index]->operator[](-50);
381 contents c2 = testers[index]->operator[](-
MAX_OBJECT);
382 bool test = (c1 == c2);
384 int tests = a_randomizer.
inclusive(100, 500);
385 for (
int i = 0; i < tests; i++) {
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
400 int start = a_randomizer.
inclusive(0, testers[index]->length());
401 int end = a_randomizer.
inclusive(0, testers[index]->length());
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
420 for (i = 0; i < arrh.
length(); i++)
421 arrh[i] = contents((i + 23) % 256);
426 arrh.
zap(0, zap_amount - 1);
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");
435 "the resized form should have same start address");
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");
443 arrh.
zap(0, zap_amount - 1);
444 for (i = 0; i < zap_amount; i++) {
447 "the slowly resized form should have same start address");
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");
460 for (i = 0; i < arrh.
length(); i++)
461 arrh[i] = contents((i + 23) % 256);
466 arrh.
zap(0, zap_amount - 1);
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");
476 "the resized form with known data should have same start address");
480 for (i = zap_amount; i < arrh.
length(); i++)
482 "the known data resized form should have same contents");
484 arrh.
zap(0, zap_amount - 1);
485 for (i = 0; i < zap_amount; i++) {
488 "the known data slowly resized form should have same start address");
493 for (i = zap_amount; i < arrh.
length(); i++)
495 "the known data slowly resized form should have same contents");
499 #ifdef DEBUG_TEST_ARRAY
504 bool erroneous =
false;
505 int chose = a_randomizer.
inclusive(1, 100);
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) {
514 end = a_randomizer.
inclusive(0, testers[index]->length() - 1);
519 start = a_randomizer.
inclusive(-2, testers[index]->length() + 3);
520 end = a_randomizer.
inclusive(-2, testers[index]->length() + 3);
524 testers[index]->
zap(start, end);
528 old_version.
length() - 1);
531 "the zapped form should not have erroneous length");
533 "the zapped form should not have erroneous contents");
538 #ifdef DEBUG_TEST_ARRAY
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
559 - testers[index]->
length();
562 if (testers[index]->length() < 5)
continue;
564 int kept = a_randomizer.
inclusive(1, testers[index]->last() - 1);
566 testers[index]->
zap(kept + 1, testers[index]->last());
567 testers[index]->
zap(0, kept - 1);
572 - testers[index]->
length();
573 ASSERT_FALSE(new_diff > 1,
"massive shrink size should be correct");
576 *testers[index] = garp;
579 case do_concatenating: {
580 #ifdef DEBUG_TEST_ARRAY
583 for (
int i = 0; i < a_randomizer.
inclusive(1, 20); i++) {
584 contents new_c = contents(a_randomizer.
inclusive(
'a',
'z'));
586 ASSERT_EQUAL(new_c, testers[index]->get(testers[index]->last()),
587 "value should be equal after concatenate");
594 flirpan = flirpan.
subarray(start, end);
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;
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;
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: {
642 #ifdef DEBUG_TEST_ARRAY
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++) {
650 to_add[i] = junk_space[
rando];
652 int old_len = flirpan.
length();
654 for (
int i = 0; i < new_len; i++) {
656 "value should not be wrong after content array concatenation");
662 #ifdef DEBUG_TEST_ARRAY
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
689 #ifdef DEBUG_TEST_ARRAY
698 if (index == rand_index)
continue;
702 temp_hold.snarf(*testers[index]);
703 testers[index]->
snarf(*testers[rand_index]);
704 testers[rand_index]->
snarf(temp_hold);
707 "snarf needs to produce right length at A");
708 for (
int i = 0; i < flirpan.
length(); i++)
710 "snarf needs to produce right array at A");
712 "snarf needs to produce right length at B");
713 for (
int j = 0; j < nugwort.
length(); j++)
715 "snarf needs to produce right array at B");
719 #ifdef DEBUG_TEST_ARRAY
733 #ifdef DEBUG_TEST_ARRAY
738 int how_many = a_randomizer.
inclusive(0, 25);
739 testers[index]->
insert(where, how_many);
740 for (
int i = 0; i < where; 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
752 if (!testers[index]->length())
continue;
755 while (index2 == index)
758 if (!hold2.
length())
continue;
763 *testers[index2], write_len);
765 astring(
"should not have had outcome=") + common::outcome_name(ret));
766 for (
int i = 0; i < write_indy; 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++)
774 "should have good contents on right after overwrite");
778 #ifdef DEBUG_TEST_ARRAY
782 contents burgers[100];
784 stuff_len =
minimum(stuff_len, 100);
787 astring(
"should not have had outcome=") + common::outcome_name(ret));
788 for (
int i = 0; i < stuff_len; i++)
790 "should have good contents after stuff");
794 ASSERT_FALSE(
true,
"test cases should have no invalid choices!");
801 delete [] junk_space;
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");
828 const int MAX_REPS = 20;
834 for (
int j = 0; j < MAX_REPS; j++) {
841 a_sprintf message(
"iteration over %d elements took %d ms,\t"
842 "or %f ms per 1000 iters.",
844 double(duration) /
double(
MAX_CHUNK * MAX_REPS) * 1000.0);
852 const abyte *head = chunky.observe();
853 for (
int j = 0; j < MAX_REPS; j++) {
860 LOG(
a_sprintf(
"less-safe iteration over %d elements took %d ms,\tor %f ms per 1000 iters.",
862 double(duration) /
double(
MAX_CHUNK * MAX_REPS) * 1000.0));
868 for (
int j = 0; j < MAX_REPS; j++) {
876 LOG(
a_sprintf(
"virtual-function-only over %d elements took %d ms,\tor %f ms per 1000 iters.",
878 double(duration) /
double(
MAX_CHUNK * MAX_REPS) * 1000.0));
884 int test_array::execute()
889 test_iteration_speed();
895 "int_array should not have contents from empty constructor");
898 array_tester<double_plus >(*
this, bogus4,
899 byte_array::SIMPLE_COPY | byte_array::EXPONE
900 | byte_array::FLUSH_INVISIBLE);
904 array_tester<int>(*
this, bogus2,
905 byte_array::SIMPLE_COPY | byte_array::EXPONE
906 | byte_array::FLUSH_INVISIBLE);
909 test_content bogus3(12);
910 array_tester<test_content>(*
this, bogus3, byte_array::EXPONE
911 | byte_array::FLUSH_INVISIBLE);
914 test_arrays_of_void_pointer();
918 array_tester<abyte>(*
this, bogus1,
919 byte_array::SIMPLE_COPY | byte_array::EXPONE
920 | byte_array::FLUSH_INVISIBLE);
925 return final_report();
The application_shell is a base object for console programs.
a_sprintf is a specialization of astring that provides printf style support.
Represents a sequential, ordered, contiguous collection of objects.
outcome put(int index, const contents &to_put)
Stores an object at the index "index" in the array.
outcome insert(int index, int new_indices)
Adds "new_indices" new positions for objects into the array at "index".
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
outcome shrink()
Cuts loose any allocated space that is beyond the real length.
outcome overwrite(int index, const array &write_with, int count=-1)
Stores the array "write_with" into the current array at the "index".
array & concatenate(const array &to_concatenate)
Appends the array "to_concatenate" onto "this" and returns "this".
array subarray(int start, int end) const
Returns the array segment between the indices "start" and "end".
const contents & get(int index) const
Accesses individual objects stored in "this" at the "index" position.
const contents * internal_block_start() const
Gritty Internal: constant peek at the real allocated pointer.
contents * access()
A non-constant access of the underlying C-array. BE REALLY CAREFUL.
outcome retrain(int new_size, const contents *to_copy)
Resizes the C array and stuffs it with the contents in "to_copy".
outcome resize(int new_size, how_to_copy way=NEW_AT_END)
Changes the size of the C array to "new_size".
int length() const
Returns the current reported length of the allocated C array.
outcome zap(int start, int end)
Deletes from "this" the objects inclusively between "start" and "end".
outcome stuff(int length, contents *to_stuff) const
Copies at most "length" elements from this into the array "to_stuff".
int internal_real_length() const
Gritty Internal: the real allocated length.
int last() const
Returns the last valid element in the array.
void snarf(array &new_contents)
Drops "this" array's contents into the dustbin and uses "new_contents".
Provides a dynamically resizable ASCII character string.
A very common template for a dynamic array of bytes.
A simple object that wraps a templated array of ints.
Outcomes describe the state of completion for an operation.
a platform-independent way to acquire random numbers in a specific range.
int inclusive(int low, int high) const
< Returns a pseudo-random number r, such that "low" <= r <= "high".
Represents a point in time relative to the operating system startup time.
time_representation value() const
returns the time_stamp in terms of the lower level type.
#define formal(parameter)
This macro just eats what it's passed; it marks unused formal parameters.
#define NULL_POINTER
The value representing a pointer to nothing.
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Provides macros that implement the 'main' program of an application.
#define HOOPLE_MAIN(obj_name, obj_args)
options that should work for most unix and linux apps.
Implements an application lock to ensure only one is running at once.
The guards collection helps in testing preconditions and reporting errors.
unsigned char abyte
A fairly important unit which is seldom defined...
void flip_increasing(type &a, type &b)
Makes sure that two values are in increasing order (a < b).
unsigned short un_short
Abbreviated name for unsigned short integers.
type minimum(type a, type b)
maximum returns the greater of two values.
type absolute_value(type a)
Returns a if a is non-negative, and returns -a otherwise.
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
Useful support functions for unit testing, especially within hoople.
const int MAX_SIMULTANEOUS_OBJECTS
const float MAX_TEST_DURATION_ms
bool compare_arrays(const array< contents > &a, const array< contents > &b)
#define ASSERT_EQUAL(a, b, test_name)
#define ASSERT_TRUE(a, test_name)
#define ASSERT_FALSE(a, test_name)