00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #define DEBUG_ARRAY
00020
00021
00022 #define DEBUG_AMORPH
00023
00024
00025
00026
00027
00028 #ifdef DEBUG_TEST_AMORPH
00029 #define LOG(to_print) EMERGENCY_LOG(program_wide_logger(), to_print)
00030 #else
00031 #define LOG(to_print) {}
00032 #endif
00033
00034 #include "bogon.cpp"
00035
00036
00037 #include <basis/chaos.h>
00038 #include <basis/function.h>
00039 #include <basis/guards.h>
00040 #include <data_struct/amorph.cpp>
00041 #include <mechanisms/time_stamp.h>
00042 #include <loggers/file_logger.h>
00043 #include <data_struct/static_memory_gremlin.h>
00044
00045 #include <memory.h>
00046 #include <stdlib.h>
00047
00048 using namespace basis;
00049
00050 HOOPLE_STARTUP_CODE;
00051
00052 #define static_class_name() "t_amorph"
00053
00054 const int default_test_iterations = 28;
00055
00056 const int MAX_LIMBS = 200;
00057
00058
00059 const int MIN_CHUBBY = 60;
00060
00061
00062 const int MAX_RANDO = 275;
00063
00064
00065 #define PROGRAM_NAME "test_amorph"
00066
00067 int compare(amorph<byte_array> &one, amorph<byte_array> &two)
00068 {
00069 FUNCDEF("compare amorph<byte_array>");
00070 if (one.elements() != two.elements()) return false;
00071 if (one.valid_fields() != two.valid_fields()) return false;
00072 for (int i = 0; i < one.elements(); i++) {
00073 if (!one.get(i) && !two.get(i)) continue;
00074 else if (!one.get(i) || !two.get(i)) {
00075 continuable_error(PROGRAM_NAME, func,
00076 istring(istring::SPRINTF, "one nil, one not, at %d!", i).s());
00077 return false;
00078 } else if (one.get(i)->length() != two.get(i)->length()) {
00079 continuable_error(PROGRAM_NAME, func,
00080 istring(istring::SPRINTF, "unequal sizes at %d!", i).s());
00081 return false;
00082 } else if (one.get(i)->length() > 0) {
00083 if (one[i]->observe() == two[i]->observe()) {
00084 continuable_error(PROGRAM_NAME, func,
00085 istring(istring::SPRINTF, "pointer in use twice at %d!", i).s());
00086 return false;
00087 }
00088 if (memcmp(one[i]->observe(), two[i]->observe(), one[i]->length())) {
00089 continuable_error(PROGRAM_NAME, func,
00090 istring(istring::SPRINTF, "unequal contents at %d!", i).s());
00091 LOG(istring(istring::SPRINTF, "a has: %s", one[i]->observe()));
00092 LOG(istring(istring::SPRINTF, "b has: %s", two[i]->observe()));
00093 return false;
00094 }
00095 }
00096 }
00097 return true;
00098 }
00099
00100 struct blob_hold { int size; int offset; };
00101 #define PACK_BLOB_SIZE(max_limbs) (max_limbs * sizeof(blob_hold))
00102
00103 byte_array fake_pack(amorph<byte_array> &me)
00104 {
00105
00106
00107 int amo_size = 0;
00108 amorph<byte_array> hold_packed_bits(me.elements());
00109
00110 for (int i = 0; i < me.elements(); i++)
00111 if (me.get(i) && me.get(i)->length()) {
00112 byte_array packed_item;
00113 attach(packed_item, *me[i]);
00114 byte_array *to_stuff = new byte_array(packed_item);
00115 hold_packed_bits.put(i, to_stuff);
00116 amo_size += packed_item.length();
00117 }
00118 int len = amo_size + sizeof(int) + PACK_BLOB_SIZE(me.elements());
00119
00120
00121 byte_array to_return(len);
00122 int temp = me.elements();
00123 object_assign((int *)to_return.access(), &temp);
00124
00125
00126 int current_offset = sizeof(int);
00127
00128 blob_hold *blob_array = (blob_hold *)(to_return.access() + current_offset);
00129 current_offset += PACK_BLOB_SIZE(me.elements());
00130
00131
00132 for (int j = 0; j < me.elements(); j++) {
00133
00134 blob_array[j].size
00135 = (hold_packed_bits[j]? hold_packed_bits[j]->length() : 0);
00136 blob_array[j].offset = current_offset;
00137 if (hold_packed_bits[j] && hold_packed_bits[j]->length()) {
00138
00139 memory_assign(to_return.access() + current_offset,
00140 (byte *)hold_packed_bits[j]->observe(),
00141 hold_packed_bits[j]->length());
00142
00143 current_offset += hold_packed_bits[j]->length();
00144 }
00145 }
00146 if (current_offset != len)
00147 deadly_error(static_class_name(), "pack", "offset is incorrect after packing");
00148 return to_return;
00149 }
00150
00151 amorph<byte_array> *fake_amorph_unpack(byte_array &packed_amorph)
00152 {
00153
00154 int max_limbs;
00155 object_assign(&max_limbs, (int *)packed_amorph.access());
00156 amorph<byte_array> *to_return = new amorph<byte_array>(max_limbs);
00157
00158 blob_hold *blob_array = new blob_hold[max_limbs];
00159 memory_assign(blob_array, (blob_hold *)(packed_amorph.access()
00160 + sizeof(int)), PACK_BLOB_SIZE(max_limbs));
00161 for (int i = 0; i < to_return->elements(); i++)
00162 if (blob_array[i].size) {
00163 byte *source = packed_amorph.access() + blob_array[i].offset;
00164 byte_array packed_byte_array(blob_array[i].size, source);
00165 byte_array *unpacked = new byte_array;
00166 detach(packed_byte_array, *unpacked);
00167 to_return->put(i, unpacked);
00168 }
00169 delete [] blob_array;
00170 return to_return;
00171 }
00172
00173 void test_byte_array_amorph()
00174 {
00175 FUNCDEF("test_byte_array_amorph");
00176 LOG("start of amorph of byte array test");
00177 for (int qq = 0; qq < default_test_iterations; qq++) {
00178 LOG(istring(istring::SPRINTF, "index %d", qq));
00179 {
00180
00181 amorph<byte_array> fred(20);
00182 amorph<byte_array> gen(10);
00183 for (int i=0; i < 10; i++) {
00184 byte_array *gens = new byte_array(8, (byte *)"goodbye");
00185 gen.put(i, gens);
00186 }
00187 for (int j = 0; j < 20; j++) {
00188 byte_array *freds = new byte_array(6, (byte *)"hello");
00189 fred.put(j, freds);
00190 }
00191 amorph_assign(gen, fred);
00192 LOG("done with fred & gen");
00193 }
00194
00195 LOG("before fred creation");
00196 chaos randomizer;
00197 amorph<byte_array> fred(MAX_LIMBS - 1);
00198 fred.append(NIL);
00199 LOG("after append nil");
00200 {
00201 for (int i = 0; i < fred.elements(); i++) {
00202 int size = MIN_CHUBBY + randomizer.inclusive(0, MAX_RANDO);
00203 istring text("bogus burfonium nuggets");
00204 istring burph(istring::SPRINTF, " ung %d ", i);
00205 text += burph;
00206 byte *temp = new byte[size];
00207 text.stuff((char *)temp, text.length()+1);
00208 byte_array *to_stuff = new byte_array(size, temp);
00209 fred.put(i, to_stuff);
00210 delete [] temp;
00211 }
00212 }
00213 LOG("after first loop");
00214 {
00215 amorph<byte_array> bungee3;
00216 amorph_assign(bungee3, fred);
00217 amorph<byte_array> burglar2;
00218 amorph_assign(burglar2, bungee3);
00219 amorph<byte_array> trunklid;
00220 amorph_assign(trunklid, burglar2);
00221 if (!trunklid.elements())
00222 deadly_error(static_class_name(), "const constructor test", "no elements!");
00223 }
00224 LOG("after copies performed");
00225 {
00226 istring text;
00227 text = "hello this is part one.";
00228 LOG(istring(istring::SPRINTF, "len is %d, content is %s",
00229 text.length(), text.observe()));
00230 char *tadr = text.access();
00231 byte *badr = (byte *)tadr;
00232 byte_array *to_stuff = new byte_array(text.length() + 1, badr);
00233 fred.put(183, to_stuff);
00234 text = "wonky tuniea bellowbop";
00235 byte_array *to_stuff1 = new byte_array(text.length()+1, (byte *)text.s());
00236 fred.put(90, to_stuff1);
00237
00238 text = "frunkwioioio";
00239 byte_array *to_stuff2 = new byte_array(text.length()+1, (byte *)text.s());
00240 fred.put(12, to_stuff2);
00241
00242 fred.clear(98); fred.clear(122); fred.clear(123);
00243 fred.clear(256);
00244 fred.clear(129);
00245 fred.zap(82, 90);
00246 fred.zap(93, 107);
00247 }
00248 LOG("after second loop");
00249 {
00250 byte_array packed = fake_pack(fred);
00251 LOG(istring(istring::SPRINTF, "done packing in %s, pack has %d "
00252 "elems.", static_class_name(), packed.length()));
00253 amorph<byte_array> *new_fred = fake_amorph_unpack(packed);
00254 LOG("done unpacking in test_amorph");
00255 if (!compare(fred, *new_fred))
00256 deadly_error(static_class_name(), "first pack test", "amorphs not the same");
00257 byte *cont1
00258 = (new_fred->get(14)? (*new_fred)[14]->access() : (byte *)"NIL");
00259 byte *cont2
00260 = (new_fred->get(20)? (*new_fred)[20]->access() : (byte *)"NIL");
00261 byte *cont3
00262 = (new_fred->get(36)? (*new_fred)[36]->access() : (byte *)"NIL");
00263
00264 if (cont1) LOG(istring(istring::SPRINTF, "14: %s", cont1));
00265 if (cont2) LOG(istring(istring::SPRINTF, "20: %s", cont2));
00266 if (cont3) LOG(istring(istring::SPRINTF, "36: %s", cont3));
00267 LOG("fields all compare identically after pack and unpack");
00268 byte_array packed_second = fake_pack(*new_fred);
00269 delete new_fred;
00270 amorph<byte_array> *newer_fred = fake_amorph_unpack(packed_second);
00271 if (!compare(*newer_fred, fred))
00272 deadly_error(static_class_name(), "second pack test", "amorphs not the same");
00273 delete newer_fred;
00274 }
00275
00276 {
00277 amorph<byte_array> fred(randomizer.inclusive(20, 30));
00278 int size = MIN_CHUBBY + randomizer.inclusive(0, MAX_RANDO);
00279 istring text("bogus burfonium nuggets");
00280 istring burph(istring::SPRINTF, " ung %d ", 2314);
00281 text += burph;
00282 byte_array intermed(size);
00283
00284 for (int i = 0; i < fred.elements(); i += 5) {
00285 byte_array *to_stuff = new byte_array(size, intermed.access());
00286 memory_assign(intermed.access(), (byte *)text.s(), text.length() + 1);
00287 fred.put(i, to_stuff);
00288 }
00289 fred.clear_all();
00290 for (int j = 0; j < fred.elements(); j += 5) {
00291 byte_array *to_stuff = new byte_array(size, intermed.access());
00292 memory_assign(intermed.access(), (byte *)text.s(), text.length() + 1);
00293 fred.put(j, to_stuff);
00294 }
00295 text = "frunkwioioio";
00296 byte_array *to_stuff = new byte_array(text.length()+1, (byte *)text.s());
00297 fred.put(12, to_stuff);
00298 fred.clear_all();
00299 }
00300 LOG("survived the clear_alls");
00301 {
00302 amorph<byte_array> *ted = new amorph<byte_array>(0);
00303 amorph_assign(*ted, fred);
00304 if (!compare(*ted, fred))
00305 deadly_error(static_class_name(), func, "ted and fred aren't the same");
00306 {
00307 amorph<byte_array> *george = new amorph<byte_array>(0);
00308 amorph_assign(*george, fred);
00309 if (!compare(*george, fred))
00310 deadly_error(static_class_name(), func, "fred and george aren't the same");
00311 ted->zap(3, 20);
00312 george->zap(3, 10);
00313 george->zap(3, 12);
00314 if (!compare(*ted, *george))
00315 deadly_error(static_class_name(), "after zap", "ted and george aren't the same");
00316 ted->adjust(ted->elements() - 20);
00317 george->adjust(george->elements() - 5);
00318 george->adjust(george->elements() - 5);
00319 george->adjust(george->elements() - 5);
00320 george->adjust(george->elements() - 5);
00321 if (!compare(*ted, *george))
00322 deadly_error(static_class_name(), "after zap", "ted and george aren't the same");
00323 delete george;
00324 }
00325 delete ted;
00326 }
00327 }
00328 }
00329
00330 int compare(const amorph<bogon> &one, const amorph<bogon> &two)
00331 {
00332 FUNCDEF("compare amorph<bogon>");
00333 if (one.elements() != two.elements()) return false;
00334 for (int i = 0; i < one.elements(); i++) {
00335 if (!one.get(i) && !two.get(i)) continue;
00336 else if (!one.get(i) || !two.get(i)) {
00337 continuable_error(PROGRAM_NAME, func, istring(istring::SPRINTF, "one nil, one not, at %d!", i).s());
00338 return false;
00339 } else if (one.get(i)->size() != two.get(i)->size()) {
00340 continuable_error(PROGRAM_NAME, func, istring(istring::SPRINTF, "unequal sizes at %d!", i).s());
00341 return false;
00342 } else if (one.get(i)->size() > 0) {
00343 if (one.get(i)->held() == two.get(i)->held()) {
00344 continuable_error(PROGRAM_NAME, func, istring(istring::SPRINTF, "pointer in use twice at %d!", i).s());
00345 return false;
00346 }
00347 if (memcmp(one.get(i)->held(), two.get(i)->held(), one.get(i)->size())) {
00348 continuable_error(PROGRAM_NAME, func, istring(istring::SPRINTF, "unequal contents at %d!", i).s());
00349 return false;
00350 }
00351 }
00352 }
00353 return true;
00354 }
00355
00356 void test_bogon_amorph()
00357 {
00358 FUNCDEF("test_bogon_amorph");
00359 LOG("start of amorph of bogon test");
00360 for (int qq = 0; qq < default_test_iterations; qq++) {
00361 LOG(istring(istring::SPRINTF, "index %d", qq));
00362 {
00363
00364 amorph<bogon> fred(20);
00365 amorph<bogon> gen(10);
00366 for (int i = 0; i < 10; i++) {
00367 bogon *gens = new bogon((byte *)"goodbye");
00368 gen.put(i, gens);
00369 }
00370 for (int j = 0; j < 20; j++) {
00371 bogon *freds = new bogon((byte *)"hello");
00372 fred.put(j, freds);
00373 }
00374 if (compare(fred, gen))
00375 deadly_error(static_class_name(), func, "fred and gen ARE the same");
00376 amorph_assign(gen, fred);
00377 if (!compare(gen, fred))
00378 deadly_error(static_class_name(), func, "gen and fred aren't the same");
00379 }
00380
00381 chaos randomizer;
00382
00383 amorph<bogon> fred(MAX_LIMBS);
00384
00385 LOG("after append nil");
00386 {
00387 for (int i = 0; i < fred.elements(); i++) {
00388 int size = MIN_CHUBBY + randomizer.inclusive(0, MAX_RANDO);
00389 istring text("bogus burfonium nuggets");
00390 istring burph(istring::SPRINTF, " ung %d ", i);
00391 text += burph;
00392 byte *temp = new byte[size];
00393 text.stuff((char *)temp, text.length()+1);
00394 bogon *to_stuff = new bogon(temp);
00395 fred.put(i, to_stuff);
00396 delete [] temp;
00397 }
00398 }
00399
00400 LOG("after first loop");
00401 {
00402 amorph<bogon> bungee3;
00403 amorph_assign(bungee3, fred);
00404 amorph<bogon> burglar2;
00405 amorph_assign(burglar2, bungee3);
00406 amorph_assign(burglar2, bungee3);
00407 amorph<bogon> trunklid;
00408 amorph_assign(trunklid, burglar2);
00409 if (!trunklid.elements())
00410 deadly_error(static_class_name(), "const constructor test", "no elements!");
00411 }
00412 {
00413 istring text;
00414 text = "hello this is part one.";
00415 bogon *to_stuff = new bogon((byte *)text.s());
00416 fred.put(32, to_stuff);
00417
00418 text = "wonky tuniea bellowbop";
00419 bogon *to_stuff1 = new bogon((byte *)text.s());
00420 fred.put(84, to_stuff1);
00421
00422 text = "frunkwioioio";
00423 bogon *to_stuff2 = new bogon((byte *)text.s());
00424 fred.put(27, to_stuff2);
00425
00426 fred.clear(98); fred.clear(122); fred.clear(123);
00427 fred.clear(256);
00428 fred.clear(129);
00429 fred.zap(82, 90);
00430 fred.zap(93, 107);
00431 }
00432 LOG("after second loop");
00433 {
00434 amorph<bogon> fred(randomizer.inclusive(20, 30));
00435 istring text("bogus burfonium nuggets");
00436 istring burph(istring::SPRINTF, " ung %d ", 2314);
00437 text += burph;
00438
00439 for (int i = 0; i < fred.elements(); i += 5) {
00440 bogon *to_stuff = new bogon((byte *)text.s());
00441 fred.put(i, to_stuff);
00442 }
00443 fred.clear_all();
00444 for (int j = 0; j < fred.elements(); j += 5) {
00445 bogon *to_stuff = new bogon((byte *)text.s());
00446 fred.put(j, to_stuff);
00447 }
00448 text = "frunkwioioio";
00449 bogon *to_stuff = new bogon((byte *)text.s());
00450 fred.put(6, to_stuff);
00451 fred.clear_all();
00452 }
00453 LOG("survived the clear_alls");
00454 {
00455 amorph<bogon> *ted = new amorph<bogon>();
00456 amorph_assign(*ted, fred);
00457 if (!compare(*ted, fred))
00458 deadly_error(static_class_name(), func, "ted and fred aren't the same");
00459 {
00460 amorph<bogon> *george = new amorph<bogon>();
00461 amorph_assign(*george, fred);
00462 if (!compare(*george, fred))
00463 deadly_error(static_class_name(), func, "fred and george aren't the same");
00464 ted->zap(3, 20);
00465 george->zap(3, 10);
00466 george->zap(3, 12);
00467 if (!compare(*ted, *george))
00468 deadly_error(static_class_name(), "after zap", "ted and george aren't the same");
00469 ted->adjust(ted->elements()-20);
00470 george->adjust(george->elements()-5);
00471 george->adjust(george->elements()-5);
00472 george->adjust(george->elements()-5);
00473 george->adjust(george->elements()-5);
00474 if (!compare(*ted, *george))
00475 deadly_error(static_class_name(), "after zap", "ted and george aren't the same");
00476 delete george;
00477 }
00478 delete ted;
00479 }
00480 }
00481 }
00482
00483 const int MAX_TEST_DURATION = 1 * MINUTE_ms;
00484
00485
00486 const int MAX_SIMULTANEOUS_OBJECTS = 42;
00487
00488
00489
00490 template <class contents>
00491 void test_amorph_of(const contents &bogus)
00492 {
00493 chaos rando;
00494
00495
00496
00497
00498 enum actions { first, do_zap = first, do_adjust, do_assign,
00499
00500
00501 do_borrow, last = do_borrow};
00502
00503 time_stamp exit_time(::MAX_TEST_DURATION);
00504 while (time_stamp() < exit_time) {
00505 int index = rando.inclusive(0, ::MAX_SIMULTANEOUS_OBJECTS - 1);
00506 int choice = rando.inclusive(first, last);
00507 switch (choice) {
00508 case do_zap: {
00509
00510 break;
00511 }
00512 case do_adjust: {
00513
00514 break;
00515 }
00516 case do_assign: {
00517
00518 break;
00519 }
00520 case do_borrow: {
00521
00522 break;
00523 }
00524 }
00525 }
00526 }
00527
00528 int main(int formal(argc), char *formal(argv)[])
00529 {
00530 SET_DEFAULT_COMBO_LOGGER;
00531 test_byte_array_amorph();
00532 test_bogon_amorph();
00533 guards::alert_message("amorph:: works for those functions tested.");
00534 return 0;
00535 }
00536
00537 #undef static_class_name
00538
00539