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/function.h>
00024 #include <basis/guards.h>
00025 #include <basis/istring.h>
00026 #include <data_struct/matrix.cpp>
00027 #include <mathematics/float_plus.h>
00028 #include <mechanisms/time_stamp.h>
00029 #include <opsystem/application_shell.h>
00030 #include <loggers/console_logger.h>
00031 #include <data_struct/static_memory_gremlin.h>
00032
00033 const int MAX_TEST_DURATION = 0.5 * MINUTE_ms;
00034
00035
00036 const int MAX_SIMULTANEOUS_OBJECTS = 42;
00037
00038 const int MIN_OBJECT = -30;
00039 const int MAX_OBJECT = 98;
00040
00041 const int MIN_BLOCK = 100;
00042 const int MAX_BLOCK = MAX_OBJECT * 2;
00043
00044
00045
00046
00047 #define LOG(s) EMERGENCY_LOG(program_wide_logger(), s)
00048
00050
00051 class test_array : public application_shell
00052 {
00053 public:
00054 test_array() : application_shell(class_name()) {}
00055 IMPLEMENT_CLASS_NAME("test_array");
00056 virtual int execute();
00057 void dump_array(array<void *> &ar, const char *name);
00058 void test_arrays_of_void_pointer();
00059 void test_iteration_speed();
00060 };
00061
00063
00064 void test_array::dump_array(array<void *> &ar, const char *name)
00065 {
00066 #ifdef DEBUG_TEST_ARRAY
00067 LOG(isprintf("array named \"%s\" has:", name));
00068 for (int i = 0; i < ar.length(); i++) {
00069 LOG(isprintf("\t%4d: %d", i, (int)ar[i]));
00070 }
00071 #else
00072 if (ar.length() && name) {}
00073 #endif
00074 }
00075
00076 void test_array::test_arrays_of_void_pointer()
00077 {
00078 FUNCDEF("void pointer test");
00079 if (sizeof(void *) != 4)
00080 deadly_error(class_name(), func, "the void pointer has an unexpected size!");
00081 const int MAX_VOID_ARRAY = 20;
00082 array<void *> argh(MAX_VOID_ARRAY, NIL, byte_array::SIMPLE_COPY
00083 | byte_array::EXPONE | byte_array::FLUSH_INVISIBLE);
00084 array<void *> argh2(argh);
00085 if (argh.length() != MAX_VOID_ARRAY)
00086 deadly_error(class_name(), func, "the first array length is incorrect!");
00087 if (argh2.length() != MAX_VOID_ARRAY)
00088 deadly_error(class_name(), func, "the copied array length is incorrect!");
00089 for (int o = 0; o < MAX_VOID_ARRAY; o++)
00090 if (argh[o] != argh2[o])
00091 deadly_error(class_name(), func, "the arrays have different contents!");
00092
00093
00094 int starter;
00095 for (int i = 0; i < MAX_VOID_ARRAY; i++)
00096 argh[i] = (void *)(&starter + i);
00097 dump_array(argh, "first version");
00098
00099
00100 for (int j = 0; j < MAX_VOID_ARRAY; j++)
00101 if (argh[j] != (void *)(&starter + j))
00102 deadly_error(class_name(), func, "setting values are incorrect!");
00103
00104
00105 for (int k = 0; k < MAX_VOID_ARRAY; k++)
00106 argh[k] = (void *)((int *)argh[k] + 23);
00107 dump_array(argh, "second version");
00108
00109
00110 argh2 = argh;
00111 for (int n = 0; n < MAX_VOID_ARRAY; n++)
00112 if (argh2[n] != (void *)(&starter + n + 23))
00113 deadly_error(class_name(), func, "assign values are incorrect!");
00114
00115
00116 argh.zap(3, 4);
00117 dump_array(argh, "third version");
00118 for (int l = 0; l < 3; l++)
00119 if (argh[l] != (void *)(&starter + l + 23))
00120 deadly_error(class_name(), func, "zap low values are incorrect!");
00121 for (int m = 3; m < MAX_VOID_ARRAY - 2; m++)
00122 if (argh[m] != (void *)(&starter + m + 2 + 23))
00123 deadly_error(class_name(), func, "zap high values are incorrect!");
00124
00125
00126 }
00127
00129
00130 static istring blank_string;
00131
00132
00133 class jethro
00134 {
00135 public:
00136 jethro(const istring &i = blank_string) : _truck(i) {}
00137
00138 istring _truck;
00139
00140 bool operator ==(const jethro &tc) const { return tc._truck == _truck; }
00141 bool operator !=(const jethro &tc) const { return !(*this == tc); }
00142 };
00143
00145
00146
00147
00148 class test_content
00149 {
00150 public:
00151 byte _q;
00152 istring _ted;
00153 istring _jed;
00154 int_array _ned;
00155 matrix<jethro> _med;
00156 int_matrix _red;
00157
00158 test_content(byte q = 3)
00159 : _q(q), _ted("bl"), _jed("orp"),
00160 _ned(12, NIL),
00161 _med(3, 2),
00162 _red(2, 4)
00163 {
00164 for (int i = 0; i < _ned.length(); i++)
00165 _ned[i] = -i;
00166 for (int r = 0; r < _med.rows(); r++)
00167 for (int c = 0; c < _med.columns(); c++)
00168 _med[r][c] = jethro(istring((r*c) % 256, 1));
00169 for (int j = 0; j < _red.rows(); j++)
00170 for (int k = 0; k < _red.columns(); k++)
00171 _red[j][k] = j * k;
00172 }
00173
00174 bool operator ==(const test_content &tc) const {
00175 if (tc._q != _q) return false;
00176 if (tc._ted != _ted) return false;
00177 if (tc._jed != _jed) return false;
00178 if (tc._ned.length() != _ned.length()) return false;
00179 for (int i = 0; i < _ned.length(); i++)
00180 if (tc._ned[i] != _ned[i]) return false;
00181
00182 if (tc._med.rows() != _med.rows()) return false;
00183 if (tc._med.columns() != _med.columns()) return false;
00184 for (int c = 0; c < _med.columns(); c++)
00185 for (int r = 0; r < _med.rows(); r++)
00186 if (tc._med.get(r, c) != _med.get(r, c)) return false;
00187
00188 if (tc._red.rows() != _red.rows()) return false;
00189 if (tc._red.columns() != _red.columns()) return false;
00190 for (int j = 0; j < _red.rows(); j++)
00191 for (int k = 0; k < _red.columns(); k++)
00192 if (tc._red.get(j, k) != _red.get(j, k)) return false;
00193
00194 return true;
00195 }
00196 bool operator !=(const test_content &tc) const { return !operator ==(tc); }
00197
00198 operator byte() const { return _q; }
00199 };
00200
00202
00203 template <class contents>
00204 bool compare_arrays(const array<contents> &a, const array<contents> &b)
00205 {
00206 if (a.length() != b.length()) return false;
00207 for (int i = 0; i < a.length(); i++)
00208 if (a[i] != b[i]) return false;
00209 return true;
00210 }
00211
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 template <class contents>
00223 void array_tester(test_array &ta, const contents &formal(bogus), u_short flags)
00224 {
00225
00226 contents *junk_space = new contents[MAX_OBJECT + MAX_BLOCK];
00227 for (int i = 0; i < MAX_OBJECT - 1; i++)
00228 junk_space[i] = contents(ta.randomizer().inclusive('a', 'z'));
00229 junk_space[MAX_OBJECT + MAX_BLOCK - 1] = '\0';
00230
00231 array<contents> *testers[MAX_SIMULTANEOUS_OBJECTS];
00232 for (int c = 0; c < MAX_SIMULTANEOUS_OBJECTS; c++) {
00233
00234 testers[c] = new array<contents>(ta.randomizer().inclusive(MIN_OBJECT, MAX_OBJECT),
00235 NIL, flags);
00236
00237 for (int i = 0; i < testers[c]->length(); i++)
00238 testers[c]->put(i, junk_space[i]);
00239 }
00240
00241
00242
00243
00244 enum actions { first, do_train = first, do_size, do_assign,
00245 do_access, do_zap, do_resizer, do_shrink, do_reset, do_indices,
00246 do_concatenating, do_concatenating2, do_subarray, do_insert,
00247 do_overwrite, do_stuff, do_memory_paring, do_snarf, do_flush,
00248 do_observe, last = do_observe };
00249
00250 time_stamp exit_time(MAX_TEST_DURATION);
00251 while (time_stamp() < exit_time) {
00252 int index = ta.randomizer().inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
00253 int choice = ta.randomizer().inclusive(first, last);
00254 switch (choice) {
00255 case do_train: {
00256 #ifdef DEBUG_TEST_ARRAY
00257 LOG(isprintf("do_train"));
00258 #endif
00259 int new_size = ta.randomizer().inclusive(MIN_OBJECT, MAX_OBJECT);
00260 testers[index]->retrain(new_size, (contents *)junk_space);
00261 for (int i = 0; i < new_size; i++) {
00262 if (junk_space[i] != (*testers[index])[i])
00263 deadly_error(ta.class_name(), __WHERE__, "bad contents after retrain");
00264 }
00265 break;
00266 }
00267 case do_size: {
00268 #ifdef DEBUG_TEST_ARRAY
00269 LOG(isprintf("do_size"));
00270 #endif
00271 array<contents> old_version = *testers[index];
00272 bool at_front = bool(ta.randomizer().inclusive(0, 1));
00273 int new_size = ta.randomizer().inclusive(MIN_OBJECT, MAX_OBJECT);
00274 bool smaller = new_size < old_version.length();
00275 int difference = absolute_value(new_size - old_version.length());
00276 testers[index]->resize(new_size,
00277 at_front? common::NEW_AT_BEGINNING
00278 : common::NEW_AT_END);
00279 if (!smaller && difference) {
00280
00281
00282 if (at_front) {
00283 for (int i = 0; i < difference; i++)
00284 testers[index]->put(i, 'Q');
00285 } else {
00286 for (int i = old_version.length();
00287 i < old_version.length() + difference; i++)
00288 testers[index]->put(i, 'Q');
00289 }
00290 }
00291
00292 array<contents> equivalent(0, NIL, flags);
00293 if (at_front) {
00294 if (smaller) {
00295 equivalent = old_version.subarray(difference,
00296 old_version.length() - 1);
00297 } else {
00298 array<contents> blank(difference, NIL, flags);
00299 for (int i = 0; i < blank.length(); i++)
00300 blank[i] = 'Q';
00301 equivalent = blank + old_version;
00302 }
00303 } else {
00304 if (smaller) {
00305 equivalent = old_version.subarray(0, old_version.length()
00306 - difference - 1);
00307 } else {
00308 array<contents> blank(difference, NIL, flags);
00309 for (int i = 0; i < blank.length(); i++)
00310 blank[i] = 'Q';
00311 equivalent = old_version + blank;
00312 }
00313 }
00314 if (equivalent.length() != testers[index]->length())
00315 deadly_error(ta.class_name(), __WHERE__, "the resized form had "
00316 "erroneous length");
00317 if (!compare_arrays(*testers[index], equivalent))
00318 deadly_error(ta.class_name(), __WHERE__, "the resized form had "
00319 "erroneous contents");
00320 break;
00321 }
00322 case do_assign: {
00323 #ifdef DEBUG_TEST_ARRAY
00324 LOG(isprintf("do_assign"));
00325 #endif
00326 array<contents> arrh = *testers[index];
00327 int to_assign = ta.randomizer().inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
00328 *testers[index] = *testers[to_assign];
00329 if (!compare_arrays(*testers[index], *testers[to_assign]))
00330 deadly_error(ta.class_name(), __WHERE__, "assign failed to copy array");
00331 *testers[to_assign] = arrh;
00332 if (!compare_arrays(*testers[to_assign], arrh))
00333 deadly_error(ta.class_name(), __WHERE__, "second assign failed");
00334 break;
00335 }
00336 case do_access: {
00337 #ifdef DEBUG_TEST_ARRAY
00338 LOG(isprintf("do_access"));
00339 #endif
00340 int start = ta.randomizer().inclusive(0, testers[index]->length());
00341 int end = ta.randomizer().inclusive(0, testers[index]->length());
00342 flip_increasing(start, end);
00343 array<contents> accumulator(0, NIL, flags);
00344 for (int i = start; i < end; i++) {
00345 contents c = contents(ta.randomizer().inclusive(1, 255));
00346 testers[index]->access()[i] = c;
00347 accumulator += c;
00348 }
00349 for (int j = start; j < end; j++)
00350 if (accumulator[j - start] != (*testers[index])[j])
00351 deadly_error(ta.class_name(), __WHERE__, "accessing failed");
00352 break;
00353 }
00354 case do_indices: {
00355 #ifndef CATCH_ERRORS // only works if not catching errors.
00356 #ifdef DEBUG_TEST_ARRAY
00357 LOG(isprintf("do_indices"));
00358 #endif
00359
00360 contents c1 = testers[index]->operator[](-50);
00361 contents c2 = testers[index]->operator[](-MAX_OBJECT);
00362 bool test = (c1 == c2);
00363 if (!test)
00364 deadly_error(ta.class_name(), __WHERE__, "invalid values were not same");
00365 int tests = ta.randomizer().inclusive(100, 500);
00366 for (int i = 0; i < tests; i++) {
00367 int indy = ta.randomizer().inclusive(-1000, MAX_OBJECT * 3);
00368
00369 contents c3 = testers[index]->operator[](indy);
00370 contents c4 = c3;
00371 if (c3 != c4)
00372 deadly_error(ta.class_name(), __WHERE__, "values were not same");
00373 }
00374 #endif
00375 break;
00376 }
00377 case do_observe: {
00378 #ifdef DEBUG_TEST_ARRAY
00379 LOG(isprintf("do_observe"));
00380 #endif
00381
00382 int start = ta.randomizer().inclusive(0, testers[index]->length());
00383 int end = ta.randomizer().inclusive(0, testers[index]->length());
00384 flip_increasing(start, end);
00385 double total_1 = 0;
00386 for (int i = start; i < end; i++)
00387 total_1 += testers[index]->observe()[i];
00388 double total_2 = 0;
00389 for (int j = end - 1; j >= start; j--)
00390 total_2 += testers[index]->observe()[j];
00391 if (total_1 != total_2)
00392 deadly_error(ta.class_name(), __WHERE__, "totals didn't match");
00393 break;
00394 }
00395 case do_resizer: {
00396 #ifdef DEBUG_TEST_ARRAY
00397 LOG(isprintf("do_resizer"));
00398 #endif
00399
00400 array<contents> &arrh = *testers[index];
00401
00402 int i;
00403 for (i = 0; i < arrh.length(); i++)
00404 arrh[i] = contents((i + 23) % 256);
00405
00406 const contents *start = arrh.internal_block_start();
00407 int zap_amount = ta.randomizer().inclusive(1, arrh.length() - 1);
00408
00409 arrh.zap(0, zap_amount - 1);
00410
00411 for (i = 0; i < arrh.length(); i++)
00412 if (arrh[i] != contents((i + 23 + zap_amount) % 256))
00413 deadly_error(ta.class_name(), __WHERE__, "the resized form "
00414 "had different contents");
00415
00416 arrh.resize(arrh.length() + zap_amount, common::NEW_AT_END);
00417
00418 if (start != arrh.internal_block_start())
00419 deadly_error(ta.class_name(), __WHERE__, "the resized form had "
00420 "a different start address");
00421
00422
00423
00424 for (i = 0; i < arrh.length() - zap_amount; i++)
00425 if (arrh[i] != contents((i + 23 + zap_amount) % 256))
00426 deadly_error(ta.class_name(), __WHERE__, "the resized form "
00427 "had different contents");
00428
00429 arrh.zap(0, zap_amount - 1);
00430 for (i = 0; i < zap_amount; i++) {
00431 arrh.resize(arrh.length() + 1, common::NEW_AT_END);
00432 if (start != arrh.internal_block_start())
00433 deadly_error(ta.class_name(), __WHERE__, "the slowly resized "
00434 "form had a different start address");
00435 }
00436
00437
00438
00439 for (i = 0; i < arrh.length() - 2 * zap_amount; i++)
00440 if (arrh[i] != contents((i + 23 + 2 * zap_amount) % 256))
00441 deadly_error(ta.class_name(), __WHERE__, "the slowly resized "
00442 "form had different contents");
00443
00444
00445
00446
00447
00448 for (i = 0; i < arrh.length(); i++)
00449 arrh[i] = contents((i + 23) % 256);
00450
00451 start = arrh.internal_block_start();
00452 zap_amount = ta.randomizer().inclusive(1, arrh.length() - 1);
00453
00454 arrh.zap(0, zap_amount - 1);
00455
00456 for (i = 0; i < arrh.length(); i++)
00457 if (arrh[i] != contents((i + 23 + zap_amount) % 256))
00458 deadly_error(ta.class_name(), __WHERE__, "the resized form "
00459 "had different contents");
00460
00461 arrh.resize(arrh.length() + zap_amount,
00462 common::NEW_AT_BEGINNING);
00463
00464 if (start != arrh.internal_block_start())
00465 deadly_error(ta.class_name(), __WHERE__, "the resized form had "
00466 "a different start address");
00467
00468
00469
00470 for (i = zap_amount; i < arrh.length(); i++)
00471 if (arrh[i] != contents((i + 23) % 256))
00472 deadly_error(ta.class_name(), __WHERE__, "the resized form "
00473 "had different contents");
00474
00475 arrh.zap(0, zap_amount - 1);
00476 for (i = 0; i < zap_amount; i++) {
00477 arrh.resize(arrh.length() + 1, common::NEW_AT_BEGINNING);
00478 if (start != arrh.internal_block_start())
00479 deadly_error(ta.class_name(), __WHERE__, "the slowly resized "
00480 "form had a different start address");
00481 }
00482
00483
00484
00485 for (i = zap_amount; i < arrh.length(); i++)
00486 if (arrh[i] != contents((i + 23) % 256))
00487 deadly_error(ta.class_name(), __WHERE__, "the slowly resized "
00488 "form had different contents");
00489 break;
00490 }
00491 case do_zap: {
00492 #ifdef DEBUG_TEST_ARRAY
00493 LOG(isprintf("do_zap"));
00494 #endif
00495 int start;
00496 int end;
00497 bool erroneous = false;
00498 int chose = ta.randomizer().inclusive(1, 100);
00499 if (chose <= 90) {
00500
00501 start = ta.randomizer().inclusive(0, testers[index]->length() - 1);
00502 end = ta.randomizer().inclusive(0, testers[index]->length() - 1);
00503 } else if (chose <= 95) {
00504
00505
00506 start = 0;
00507 end = ta.randomizer().inclusive(0, testers[index]->length() - 1);
00508 } else {
00509
00510
00511 erroneous = true;
00512 start = ta.randomizer().inclusive(-2, testers[index]->length() + 3);
00513 end = ta.randomizer().inclusive(-2, testers[index]->length() + 3);
00514 }
00515 flip_increasing(start, end);
00516 array<contents> old_version = *testers[index];
00517 testers[index]->zap(start, end);
00518 if (!erroneous) {
00519 array<contents> old_head = old_version.subarray(0, start - 1);
00520 array<contents> old_tail = old_version.subarray(end + 1,
00521 old_version.length() - 1);
00522 array<contents> equivalent = old_head + old_tail;
00523 if (equivalent.length() != testers[index]->length())
00524 deadly_error(ta.class_name(), __WHERE__, "the zapped form had "
00525 "erroneous length");
00526 if (!compare_arrays(*testers[index], equivalent))
00527 deadly_error(ta.class_name(), __WHERE__, "the zapped form had "
00528 "erroneous contents");
00529 }
00530 break;
00531 }
00532 case do_reset: {
00533 #ifdef DEBUG_TEST_ARRAY
00534 LOG(isprintf("do_reset"));
00535 #endif
00536 int junk_start = ta.randomizer().inclusive(MIN_BLOCK, MAX_BLOCK);
00537 int junk_end = ta.randomizer().inclusive(MIN_BLOCK, MAX_BLOCK);
00538 flip_increasing(junk_start, junk_end);
00539 int len = junk_end - junk_start + 1;
00540 testers[index]->reset(len, (contents *)&junk_space[junk_start]);
00541 if (testers[index]->length() != len)
00542 deadly_error(ta.class_name(), __WHERE__, "reset gave a bad length");
00543 for (int i = 0; i < len; i++)
00544 if (testers[index]->get(i) != junk_space[junk_start + i])
00545 deadly_error(ta.class_name(), __WHERE__, "reset failed to copy data");
00546 break;
00547 }
00548 case do_shrink: {
00549 #ifdef DEBUG_TEST_ARRAY
00550 LOG(isprintf("do_shrink"));
00551 #endif
00552 array<contents> garp = *testers[index];
00553 testers[index]->shrink();
00554 int new_diff = testers[index]->internal_real_length()
00555 - testers[index]->length();
00556 if (!compare_arrays(garp, *testers[index]))
00557 deadly_error(ta.class_name(), __WHERE__, "shrink failed to keep contents");
00558
00559 if (testers[index]->length() < 5) continue;
00560
00561 int kept = ta.randomizer().inclusive(1, testers[index]->last() - 1);
00562
00563 testers[index]->zap(kept + 1, testers[index]->last());
00564 testers[index]->zap(0, kept - 1);
00565
00566 testers[index]->shrink();
00567
00568 new_diff = testers[index]->internal_real_length()
00569 - testers[index]->length();
00570 if (new_diff > 1)
00571 deadly_error(ta.class_name(), __WHERE__, "massive shrink gave a bad size");
00572
00573
00574 *testers[index] = garp;
00575 break;
00576 }
00577 case do_concatenating: {
00578 #ifdef DEBUG_TEST_ARRAY
00579 LOG(isprintf("do_concatenating"));
00580 #endif
00581 for (int i = 0; i < ta.randomizer().inclusive(1, 20); i++) {
00582 contents new_c = contents(ta.randomizer().inclusive('a', 'z'));
00583 testers[index]->concatenate(new_c);
00584 if (new_c != testers[index]->get(testers[index]->last()))
00585 deadly_error(ta.class_name(), __WHERE__,
00586 "value wrong after concatenate");
00587 }
00588 int indy = ta.randomizer().inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
00589 array<contents> flirpan = *testers[indy];
00590 int start = ta.randomizer().inclusive(0, flirpan.length() - 1);
00591 int end = ta.randomizer().inclusive(0, flirpan.length() - 1);
00592 flip_increasing(start, end);
00593 flirpan = flirpan.subarray(start, end);
00594 array<contents> grumzor = *testers[index];
00595 testers[index]->concatenate(flirpan);
00596 array<contents> bubula = grumzor + flirpan;
00597 if (!compare_arrays(bubula, *testers[index]))
00598 deadly_error(ta.class_name(), __WHERE__,
00599 "contents wrong after concatenate or concatenation");
00600 contents first_value;
00601 contents second_value;
00602 if (testers[index]->length() >= 1)
00603 first_value = testers[index]->get(0);
00604 if (testers[index]->length() >= 2)
00605 second_value = testers[index]->get(1);
00606 const int max_iters = ta.randomizer().inclusive(1, 42);
00607 for (int j = 0; j < max_iters; j++) {
00608 contents new_c = contents(ta.randomizer().inclusive('a', 'z'));
00609 *testers[index] = *testers[index] + new_c;
00610
00611 if (testers[index]->length() == 1) {
00612 first_value = testers[index]->get(0);
00613 } else if (testers[index]->length() == 2) {
00614 second_value = testers[index]->get(1);
00615 }
00616
00617 if (new_c != testers[index]->get(testers[index]->last()))
00618 deadly_error(ta.class_name(), __WHERE__, "value wrong after "
00619 "concatenation");
00620
00621 if ( (testers[index]->length() >= 1)
00622 && (first_value != testers[index]->get(0)) )
00623 deadly_error(ta.class_name(), __WHERE__, "first value got "
00624 "corrupted");
00625 if ( (testers[index]->length() >= 2)
00626 && (second_value != testers[index]->get(1)) )
00627 deadly_error(ta.class_name(), __WHERE__, "second value got "
00628 "corrupted");
00629
00630 *testers[index] += new_c;
00631
00632
00633 if (testers[index]->length() == 2) {
00634 second_value = testers[index]->get(1);
00635 }
00636 if (new_c != testers[index]->get(testers[index]->last()))
00637 deadly_error(ta.class_name(), __WHERE__, "value wrong after "
00638 "second concatenation");
00639 if ( (testers[index]->length() >= 1)
00640 && (first_value != testers[index]->get(0)) )
00641 deadly_error(ta.class_name(), __WHERE__, "first value got "
00642 "corrupted after second concat");
00643 if ( (testers[index]->length() >= 2)
00644 && (second_value != testers[index]->get(1)) )
00645 deadly_error(ta.class_name(), __WHERE__, "second value got "
00646 "corrupted after second concat");
00647 }
00648 break;
00649 }
00650 case do_concatenating2: {
00651
00652 #ifdef DEBUG_TEST_ARRAY
00653 LOG(isprintf("do_concatenating2"));
00654 #endif
00655 array<contents> &flirpan = *testers[index];
00656 int new_len = ta.randomizer().inclusive(0, 140);
00657 contents *to_add = new contents[new_len];
00658 for (int i = 0; i < new_len; i++) {
00659 int rando = ta.randomizer().inclusive(0, MAX_BLOCK - 1);
00660 to_add[i] = junk_space[rando];
00661 }
00662 int old_len = flirpan.length();
00663 flirpan.concatenate(to_add, new_len);
00664 for (int i = 0; i < new_len; i++) {
00665 if (flirpan[i + old_len] != to_add[i])
00666 deadly_error(ta.class_name(), __WHERE__, "value wrong after "
00667 "content array concatenation");
00668 }
00669 delete [] to_add;
00670 break;
00671 }
00672 case do_subarray: {
00673 #ifdef DEBUG_TEST_ARRAY
00674 LOG(isprintf("do_subarray"));
00675 #endif
00676 array<contents> flirpan = *testers[index];
00677 int start = ta.randomizer().inclusive(0, flirpan.length() - 1);
00678 int end = ta.randomizer().inclusive(0, flirpan.length() - 1);
00679 flip_increasing(start, end);
00680 flirpan = flirpan.subarray(start, end);
00681 for (int i = 0; i < end - start; i++)
00682 if (flirpan[i] != testers[index]->get(i + start))
00683 deadly_error(ta.class_name(), __WHERE__, "subarray produced wrong array");
00684 break;
00685 }
00686 case do_memory_paring: {
00687 #ifdef DEBUG_TEST_ARRAY
00688 LOG(isprintf("do_memory_paring"));
00689 #endif
00690 for (int i = 0; i < MAX_SIMULTANEOUS_OBJECTS; i++) {
00691
00692 if (testers[i]->length() > MAX_OBJECT) {
00693 testers[i]->zap(MAX_OBJECT, testers[i]->length() - 1);
00694 testers[i]->shrink();
00695 }
00696 }
00697 break;
00698 }
00699 case do_snarf: {
00700 #ifdef DEBUG_TEST_ARRAY
00701 LOG(isprintf("do_snarf"));
00702 #endif
00703 array<contents> flirpan = *testers[index];
00704
00705
00706
00707
00708 int rand_index = ta.randomizer().inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
00709 if (index == rand_index) continue;
00710 array<contents> nugwort = *testers[rand_index];
00711
00712 array<contents> temp_hold(0, NIL, flags);
00713 temp_hold.snarf(*testers[index]);
00714 testers[index]->snarf(*testers[rand_index]);
00715 testers[rand_index]->snarf(temp_hold);
00716
00717 if (flirpan.length() != testers[rand_index]->length())
00718 deadly_error(ta.class_name(), __WHERE__, "snarf produced wrong length A");
00719 for (int i = 0; i < flirpan.length(); i++)
00720 if (flirpan[i] != testers[rand_index]->get(i))
00721 deadly_error(ta.class_name(), __WHERE__, "snarf produced wrong array A");
00722 if (nugwort.length() != testers[index]->length())
00723 deadly_error(ta.class_name(), __WHERE__, "snarf produced wrong length B");
00724 for (int j = 0; j < nugwort.length(); j++)
00725 if (nugwort[j] != testers[index]->get(j))
00726 deadly_error(ta.class_name(), __WHERE__, "snarf produced wrong array B");
00727 break;
00728 }
00729 case do_flush: {
00730 #ifdef DEBUG_TEST_ARRAY
00731 LOG(isprintf("do_flush"));
00732 #endif
00733 array<contents> flirpan = *testers[index];
00734
00736
00738
00739
00740 break;
00741 }
00742
00743 case do_insert: {
00744 #ifdef DEBUG_TEST_ARRAY
00745 LOG(isprintf("do_insert"));
00746 #endif
00747 array<contents> hold = *testers[index];
00748 int where = ta.randomizer().inclusive(0, hold.last());
00749 int how_many = ta.randomizer().inclusive(0, 25);
00750 testers[index]->insert(where, how_many);
00751 for (int i = 0; i < where; i++)
00752 if (hold[i] != testers[index]->get(i))
00753 deadly_error(ta.class_name(), __WHERE__, "bad contents on left after insert");
00754 for (int j = where + how_many; j < testers[index]->length(); j++)
00755 if (hold[j - how_many] != testers[index]->get(j))
00756 deadly_error(ta.class_name(), __WHERE__, "bad contents on right after insert");
00757 break;
00758 }
00759 case do_overwrite: {
00760 #ifdef DEBUG_TEST_ARRAY
00761 LOG(isprintf("do_overwrite"));
00762 #endif
00763 if (!testers[index]->length()) continue;
00764 array<contents> hold = *testers[index];
00765 int index2 = index;
00766 while (index2 == index)
00767 index2 = ta.randomizer().inclusive(0, MAX_SIMULTANEOUS_OBJECTS - 1);
00768 array<contents> &hold2 = *testers[index2];
00769 if (!hold2.length()) continue;
00770 int write_indy = ta.randomizer().inclusive(0, hold.last());
00771 int write_len = minimum(hold2.length(), (hold.length() - write_indy));
00772
00773 outcome ret = testers[index]->overwrite(write_indy,
00774 *testers[index2], write_len);
00775 if (ret != common::OKAY)
00776 deadly_error(ta.class_name(), __WHERE__, istring("bad outcome=")
00777 + common::outcome_name(ret));
00778 for (int i = 0; i < write_indy; i++)
00779 if (hold[i] != testers[index]->get(i))
00780 deadly_error(ta.class_name(), __WHERE__,
00781 "bad contents on left after overwrite");
00782 for (int j = write_indy; j < write_indy + write_len; j++)
00783 if (hold2[j - write_indy] != testers[index]->get(j))
00784 deadly_error(ta.class_name(), __WHERE__,
00785 "bad contents in middle after overwrite");
00786 for (int k = write_indy + write_len; k < testers[index]->length(); k++)
00787 if (hold[k] != testers[index]->get(k))
00788 deadly_error(ta.class_name(), __WHERE__,
00789 "bad contents on right after overwrite");
00790 break;
00791 }
00792 case do_stuff: {
00793 #ifdef DEBUG_TEST_ARRAY
00794 LOG(isprintf("do_stuff"));
00795 #endif
00796 array<contents> &hold = *testers[index];
00797 contents burgers[100];
00798 int stuff_len = ta.randomizer().inclusive(0, hold.length());
00799 stuff_len = minimum(stuff_len, 100);
00800 outcome ret = hold.stuff(stuff_len, burgers);
00801 if (ret != common::OKAY)
00802 deadly_error(ta.class_name(), __WHERE__, istring("bad outcome=")
00803 + common::outcome_name(ret));
00804 for (int i = 0; i < stuff_len; i++)
00805 if (burgers[i] != hold[i])
00806 deadly_error(ta.class_name(), __WHERE__, "bad contents after stuff");
00807 break;
00808 }
00809 default: {
00810 deadly_error(ta.class_name(), "action choice", "invalid choice!");
00811 break;
00812 }
00813 }
00814 }
00815
00816
00817 delete [] junk_space;
00818 for (int d = 0; d < MAX_SIMULTANEOUS_OBJECTS; d++) delete testers[d];
00819 }
00820
00822
00823 struct gerkin { int l; byte *p; char *r; void *pffttt; };
00824
00825 gerkin borgia;
00826
00827 class foop
00828 {
00829 public:
00830 virtual ~foop() {}
00831 virtual gerkin *boorba() = 0;
00832 };
00833
00834 class boop : public foop
00835 {
00836 public:
00837 virtual gerkin *boorba() { return &borgia; }
00838 };
00839
00840 void test_array::test_iteration_speed()
00841 {
00842 const int MAX_CHUNK = 100000;
00843 const int MAX_REPS = 20;
00844 byte_array chunky(MAX_CHUNK);
00845
00846 {
00847 time_stamp start;
00848 int sum = 0;
00849 for (int j = 0; j < MAX_REPS; j++) {
00850 for (int i = 0; i < MAX_CHUNK; i++) {
00851 sum += chunky[i];
00852 }
00853 }
00854 int duration = int(time_stamp().value() - start.value());
00855
00856 LOG(isprintf("iteration over %d elements took %d ms,\tor %f ms per 1000 iters.",
00857 MAX_CHUNK * MAX_REPS, duration,
00858 double(duration) / double(MAX_CHUNK * MAX_REPS) * 1000.0));
00859 }
00860
00861 {
00862 time_stamp start;
00863 int sum = 0;
00864 const byte *head = chunky.observe();
00865 for (int j = 0; j < MAX_REPS; j++) {
00866 for (int i = 0; i < MAX_CHUNK; i++) {
00867 sum += head[i];
00868 }
00869 }
00870 int duration = int(time_stamp().value() - start.value());
00871
00872 LOG(isprintf("less-safe iteration over %d elements took %d ms,\tor %f ms per 1000 iters.",
00873 MAX_CHUNK * MAX_REPS, duration,
00874 double(duration) / double(MAX_CHUNK * MAX_REPS) * 1000.0));
00875 }
00876 {
00877 time_stamp start;
00878 boop tester;
00879
00880 for (int j = 0; j < MAX_REPS; j++) {
00881 for (int i = 0; i < MAX_CHUNK; i++) {
00882
00883 tester.boorba();
00884 }
00885 }
00886 int duration = int(time_stamp().value() - start.value());
00887
00888 LOG(isprintf("virtual-function-only over %d elements took %d ms,\tor %f ms per 1000 iters.",
00889 MAX_CHUNK * MAX_REPS, duration,
00890 double(duration) / double(MAX_CHUNK * MAX_REPS) * 1000.0));
00891 }
00892 }
00893
00895
00896 int test_array::execute()
00897 {
00898 test_iteration_speed();
00899 LOG(isprintf("did iteration test."));
00900
00901 int_array checking_start;
00902 if (checking_start.length())
00903 deadly_error(class_name(), "int_array length",
00904 "has contents from empty constructor!");
00905
00906 float_plus<double> bogus4 = float(12.32);
00907 array_tester<float_plus<double> >(*this, bogus4,
00908 byte_array::SIMPLE_COPY | byte_array::EXPONE
00909 | byte_array::FLUSH_INVISIBLE);
00910 LOG(isprintf("did float array test."));
00911
00912 int bogus2 = 39;
00913 array_tester<int>(*this, bogus2,
00914 byte_array::SIMPLE_COPY | byte_array::EXPONE
00915 | byte_array::FLUSH_INVISIBLE);
00916 LOG(isprintf("did int array test."));
00917
00918 test_content bogus3(12);
00919 array_tester<test_content>(*this, bogus3, byte_array::EXPONE
00920 | byte_array::FLUSH_INVISIBLE);
00921 LOG(isprintf("did test_content array test."));
00922
00923 test_arrays_of_void_pointer();
00924 LOG(isprintf("did void * array test."));
00925
00926 byte bogus1 = 'c';
00927 array_tester<byte>(*this, bogus1,
00928 byte_array::SIMPLE_COPY | byte_array::EXPONE
00929 | byte_array::FLUSH_INVISIBLE);
00930 LOG(isprintf("did byte array test."));
00931
00932 guards::alert_message("array:: works for those functions tested.");
00933
00934 return 0;
00935 }
00936
00937 HOOPLE_MAIN(test_array, )
00938