28 using namespace basis;
40 #define EXTREME_CHECKING
104 : snacky_string(string_manipulation::make_random_name()),
105 chunk(chao.
inclusive(100, 10000)), food_bar(0), hungry(
false) {}
126 static bool equivalence_applier(
const int &key, data_shuttle &item,
void *dlink);
131 int unused_random_id();
141 bool test_find_zap_add();
142 bool test_acquire_add_zap();
143 bool test_find_add_find();
144 bool test_reset(
bool always_do_it =
false);
145 bool test_check_sanity();
162 test_int_hash::test_int_hash()
171 int test_int_hash::execute()
179 #ifdef DEBUG_INT_HASH
180 log(
a_sprintf(
"did %d tests.\n", _tested));
181 log(
astring(
"Test Activity:"));
185 log(
a_sprintf(
"note that test %d will seldom be executed.",
RESET));
187 return final_report();
193 case ADD:
return "ADD";
194 case ADD_ADD:
return "ADD_ADD";
195 case ZAP:
return "ZAP";
196 case ADD_ZAP:
return "ADD_ZAP";
197 case ZAP_ADD:
return "ZAP_ADD";
198 case FIND:
return "FIND";
199 case ACQUIRE:
return "ACQUIRE";
203 case RESET:
return "RESET";
204 case COPY:
return "COPY";
205 case REHASH:
return "REHASH";
207 default:
return "UnknownTest";
211 bool test_int_hash::perform_a_test(
test_actions test_type)
218 case ADD:
return test_add();
219 case ADD_ADD:
return test_add_add();
220 case ZAP:
return test_zap();
221 case ADD_ZAP:
return test_add_zap();
222 case ZAP_ADD:
return test_zap_add();
223 case FIND:
return test_find();
224 case ACQUIRE:
return test_acquire();
228 case RESET:
return test_reset();
229 case COPY:
return test_copy();
230 case REHASH:
return test_rehash();
233 ASSERT_TRUE(
false,
"there should be no missing case seen!");
238 bool test_int_hash::pick_a_test()
244 int test_int_hash::raw_random_id()
249 int test_int_hash::unused_random_id()
252 int checking = raw_random_id();
253 if (!_keys_in_use.member(checking))
return checking;
258 bool test_int_hash::test_add()
262 int random_id = raw_random_id();
263 data_shuttle *to_add =
new data_shuttle;
264 to_add->snacky_string = string_manipulation::make_random_name();
265 to_add->food_bar = random_id;
266 outcome wanting = common::IS_NEW;
267 if (_keys_in_use.member(random_id)) wanting = common::EXISTING;
269 "adding key should work with right expectation");
270 if (_keys_in_use.member(random_id))
272 _keys_in_use.add(random_id);
278 #undef UNIT_BASE_THIS_OBJECT
279 #define UNIT_BASE_THIS_OBJECT (*dynamic_cast<unit_base *>(application_shell::single_instance()))
284 bool test_int_hash::equivalence_applier(
const int &key, data_shuttle &item,
void *dlink)
286 FUNCDEF(
"equivalence_applier");
288 if (!dlink)
return false;
295 if (!found)
return false;
300 ASSERT_EQUAL(item.snacky_string, found->snacky_string,
test_name +
": snacky_string should not differ");
305 #undef UNIT_BASE_THIS_OBJECT
306 #define UNIT_BASE_THIS_OBJECT (*this)
310 bool test_int_hash::test_rehash()
323 _the_table.apply(equivalence_applier, (
void *)func);
324 astring second_test_name(func);
325 second_test_name +=
" try 2";
326 table_copy.
apply(equivalence_applier, (
void *)second_test_name.
s());
328 if (!_the_table.elements())
return true;
337 _the_table.rehash(
randomizer().inclusive(1, 20));
343 third_test_name +=
" try 3";
344 table_copy.
apply(equivalence_applier, (
void *)third_test_name.
s());
350 bool test_int_hash::test_copy()
368 table_copy.apply(equivalence_applier, (
void *)func);
376 bool test_int_hash::test_add_add()
380 int random_id = unused_random_id();
381 data_shuttle *to_add =
new data_shuttle;
382 to_add->snacky_string = string_manipulation::make_random_name();
383 to_add->food_bar = random_id;
384 ASSERT_EQUAL(_the_table.add(random_id, to_add).value(), common::IS_NEW,
"key should be new");
385 _keys_in_use.add(random_id);
388 data_shuttle *next_add =
new data_shuttle;
389 next_add->snacky_string = string_manipulation::make_random_name();
390 next_add->food_bar = random_id;
391 ASSERT_EQUAL(_the_table.add(random_id, next_add).value(), our_hash::EXISTING,
392 "second add should not say first failed");
397 bool test_int_hash::test_zap()
401 if (maybe > 500)
return true;
402 if (!_keys_in_use.elements())
return false;
404 int rand_indy =
randomizer().inclusive(0, _keys_in_use.elements() - 1);
405 int dead_key = _keys_in_use[rand_indy];
406 _keys_in_use.remove(dead_key);
407 ASSERT_TRUE(_the_table.zap(dead_key),
"zap should work on key");
411 bool test_int_hash::test_add_zap()
416 int random_id = unused_random_id();
417 data_shuttle *to_add =
new data_shuttle;
418 to_add->snacky_string = string_manipulation::make_random_name();
419 to_add->food_bar = random_id;
420 ASSERT_EQUAL(_the_table.add(random_id, to_add).value(), common::IS_NEW,
"key is new before zap");
422 ASSERT_TRUE(_the_table.zap(random_id),
"add then zap should remove the key");
426 bool test_int_hash::test_zap_add()
429 if (!_keys_in_use.elements())
return false;
431 int rand_indy =
randomizer().inclusive(0, _keys_in_use.elements() - 1);
433 int dead_key = _keys_in_use[rand_indy];
434 ASSERT_TRUE(_the_table.zap(dead_key),
"key should be there for zapping");
436 data_shuttle *to_add =
new data_shuttle;
437 to_add->snacky_string = string_manipulation::make_random_name();
438 to_add->food_bar = dead_key;
439 outcome ret = _the_table.add(dead_key, to_add);
440 ASSERT_EQUAL(ret.
value(), our_hash::IS_NEW,
"key should not already be present somehow");
448 bool test_int_hash::test_find()
451 if (!_keys_in_use.elements())
return false;
453 int rand_indy =
randomizer().inclusive(0, _keys_in_use.elements() - 1);
454 int find_key = _keys_in_use[rand_indy];
457 "key should be there when we look");
459 ASSERT_TRUE(found,
"when key is found contents should not be null");
460 ASSERT_EQUAL(found->food_bar, find_key,
"stored key should be same as real key");
461 ASSERT_TRUE(found->snacky_string.length(),
"stored string should have some length");
465 bool test_int_hash::test_acquire()
469 if (maybe > 750)
return true;
470 if (!_keys_in_use.elements())
return false;
472 int rand_indy =
randomizer().inclusive(0, _keys_in_use.elements() - 1);
473 int find_key = _keys_in_use[rand_indy];
474 _keys_in_use.remove(find_key);
475 data_shuttle *found = _the_table.acquire(find_key);
476 ASSERT_TRUE(found,
"key should be there like clockwork");
477 ASSERT_EQUAL(found->food_bar, find_key,
"stored key should be same as real key");
478 ASSERT_TRUE(found->snacky_string.length(),
"stored string should have some length");
480 found = _the_table.acquire(find_key);
485 bool test_int_hash::test_find_zap_add()
489 if (!_keys_in_use.elements())
return false;
491 int rand_indy =
randomizer().inclusive(0, _keys_in_use.elements() - 1);
493 int find_key = _keys_in_use[rand_indy];
495 ASSERT_TRUE(_the_table.find(find_key, found),
"key should be there when sought");
496 ASSERT_TRUE(_the_table.find(find_key),
"find2: key should be there for us to find");
497 ASSERT_TRUE(found,
"found key should have non-null contents");
498 ASSERT_EQUAL(found->food_bar, find_key,
"stored key should have no differences from real key");
499 ASSERT_TRUE(found->snacky_string.length(),
"stored string should have non-zero length");
501 ASSERT_TRUE(_the_table.zap(find_key),
"should be able to zap the item we had found");
503 data_shuttle *to_add =
new data_shuttle;
504 to_add->snacky_string = string_manipulation::make_random_name();
505 to_add->food_bar = find_key;
506 ASSERT_EQUAL(_the_table.add(find_key, to_add).value(), our_hash::IS_NEW,
507 "the item we zapped should not still be there");
511 bool test_int_hash::test_reset(
bool always_do_it)
517 if ( (maybe > 372) || (maybe < 368) )
return true;
523 for (
int i = _keys_in_use.elements() - 1; i >= 0; i--) {
524 int dead_key = _keys_in_use[i];
525 ASSERT_FALSE(_the_table.acquire(dead_key),
"after reset, we should not find an item");
526 _keys_in_use.remove(dead_key);
533 bool test_int_hash::test_acquire_add_zap()
539 bool test_int_hash::test_find_add_find()
545 bool test_int_hash::test_check_sanity()
The application_shell is a base object for console programs.
a_sprintf is a specialization of astring that provides printf style support.
Provides a dynamically resizable ASCII character string.
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
A very common template for a dynamic array of bytes.
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".
int elements() const
the number of valid items we found by traversing the hash table.
bool find(const key_type &key, contents *&item_found) const
locates the item specified by the "key", if possible.
void apply(apply_function *to_apply, void *data_link)
operates on every item in the int_hash table.
A simple object that wraps a templated set of ints.
Represents a point in time relative to the operating system startup time.
#define NULL_POINTER
The value representing a pointer to nothing.
#define MAXINT32
Maximum 32-bit integer value.
#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.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
const int SECOND_ms
Number of milliseconds in a second.
A platform independent way to obtain the timestamp of a file.
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
A dynamic container class that holds any kind of object via pointers.
void copy_hash_table(hash_table< key_type, contents > &target, const hash_table< key_type, contents > &source)
Copies the entire hash table, given a contents type that supports copying.
Useful support functions for unit testing, especially within hoople.
int_hash< data_shuttle > our_hash
const double TEST_DURATION
int functional_return(int to_pass)
const int MAX_DEFAULT_BITS
int_hash< data_shuttle > * _hang_on
#define ASSERT_EQUAL(a, b, test_name)
#define ASSERT_TRUE(a, test_name)
#define ASSERT_FALSE(a, test_name)
#define ASSERT_INEQUAL(a, b, test_name)