// Copyright (C) 2003 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #include <sstream> #include <string> #include <cstdlib> #include <ctime> #include <dlib/hash_table.h> #include "tester.h" namespace { using namespace test; using namespace std; using namespace dlib; logger dlog("test.hash_table"); template < typename hash_table > void hash_table_kernel_test ( ) /*! requires - hash_table is an implementation of hash_table/hash_table_kernel_abstract.h and is instantiated to map ints to ints ensures - runs tests on hash_table for compliance with the specs !*/ { srand(static_cast<unsigned int>(time(0))); { hash_table test(16); DLIB_TEST(test.count(3) == 0); enumerable<map_pair<int,int> >& e = test; DLIB_TEST(e.at_start() == true); hash_table test2(16); hash_table test3(0); hash_table test4(0); print_spinner(); int b; for (int j = 0; j < 4; ++j) { int a = 4; b = 5; test2.add(a,b); DLIB_TEST(test2.size() == 1); DLIB_TEST(*test2[4] == 5); DLIB_TEST(test2[99] == 0); DLIB_TEST(test2.move_next()); DLIB_TEST(test2.element().key() == 4); DLIB_TEST(test2.element().value() == 5); swap(test,test2); DLIB_TEST(test.size() == 1); DLIB_TEST(*test[4] == 5); DLIB_TEST(test[99] == 0); test.swap(test2); a = 99; b = 35; test2.add(a,b); DLIB_TEST(test2.size() == 2); DLIB_TEST(*test2[4] == 5); DLIB_TEST(*test2[99] == 35); DLIB_TEST(test2[99] != 0); DLIB_TEST(test2[949] == 0); test2.destroy(4); DLIB_TEST(test2.size() == 1); DLIB_TEST(test2[4] == 0); DLIB_TEST(*test2[99] == 35); DLIB_TEST(test2[99] != 0); DLIB_TEST(test2[949] == 0); test2.destroy(99); DLIB_TEST(test2.size() == 0); DLIB_TEST(test2[4] == 0); DLIB_TEST(test2[99] == 0); DLIB_TEST(test2[949] == 0); test2.clear(); } print_spinner(); for (int j = 0; j < 4; ++j) { DLIB_TEST(test.count(3) == 0); DLIB_TEST(test.size() == 0); DLIB_TEST(test.at_start() == true); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.move_next() == false); DLIB_TEST(test.at_start() == false); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.move_next() == false); DLIB_TEST(test.move_next() == false); int a; for (int i = 0; i < 10000; ++i) { a = ::rand()%1000; int temp = a; unsigned long count = test.count(a); test.add(a,b); DLIB_TEST(test.count(temp) == count+1); } { unsigned long count = test.count(3); a = 3; test.add(a,b); ++count; DLIB_TEST(test.count(3) == count); a = 3; test.add(a,b); ++count; DLIB_TEST(test.count(3) == count); a = 3; test.add(a,b); ++count; DLIB_TEST(test.count(3) == count); a = 3; test.add(a,b); ++count; DLIB_TEST(test.count(3) == count); } test.clear(); for (int i = 0; i < 10000; ++i) { a = b = i; unsigned long count = test.count(a); test.add(a,b); DLIB_TEST(test.count(i) == count+1); } DLIB_TEST(test.size() == 10000); DLIB_TEST(test.at_start() == true); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.move_next() == true); DLIB_TEST(test.at_start() == false); DLIB_TEST(test.current_element_valid() == true); DLIB_TEST(test.move_next() == true); DLIB_TEST(test.move_next() == true); DLIB_TEST(test.current_element_valid() == true); test.reset(); DLIB_TEST(test.size() == 10000); DLIB_TEST(test.at_start() == true); DLIB_TEST(test.current_element_valid() == false); if (test.size() > 0) { int* array = new int[test.size()]; int* tmp = array; int count = 0; while (test.move_next()) { ++count; *tmp = test.element().key(); DLIB_TEST(test[*tmp] != 0); DLIB_TEST(*tmp == test.element().key()); DLIB_TEST(*tmp == test.element().value()); DLIB_TEST(*tmp == test.element().key()); DLIB_TEST(test.current_element_valid() == true); ++tmp; } DLIB_TEST(count == 10000); DLIB_TEST(test.at_start() == false); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.move_next() == false); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.at_start() == false); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.size() == 10000); swap(test,test2); // serialize the state of test2, then clear test2, then // load the state back into test2. ostringstream sout; serialize(test2,sout); DLIB_TEST(test2.at_start() == true); istringstream sin(sout.str()); test2.clear(); deserialize(test2,sin); DLIB_TEST(test2.at_start() == true); tmp = array; for (int i = 0; i < 10000; ++i) { DLIB_TEST(*test2[*tmp] == *tmp); DLIB_TEST(*test2[*tmp] == *tmp); DLIB_TEST(*test2[*tmp] == *tmp); ++tmp; } test2.swap(test); test.reset(); DLIB_TEST(test.at_start() == true); count = 0; tmp = array; while (test.size() > 0) { test.remove(*tmp,a,b); ++tmp; ++count; } DLIB_TEST(count == 10000); DLIB_TEST(test.size() == 0); DLIB_TEST(count == 10000); delete [] array; } test.move_next(); for (int i = 0; i < 10000; ++i) { a = ::rand(); test.add(a,b); } DLIB_TEST(test.at_start() == true); DLIB_TEST(test.move_next() == true); DLIB_TEST(test.size() == 10000); for (int i = 0; i < 10000; ++i) { test.remove_any(a,b); } DLIB_TEST(test.at_start() == true); DLIB_TEST(test.move_next() == false); DLIB_TEST(test.size() == 0); test.clear(); int* dtmp = new int[10000]; int* rtmp = new int[10000]; int* d = dtmp; int* r = rtmp; for (unsigned long i = 0; i < 10000; ++i) { a = ::rand(); b = ::rand(); *d = a; *r = b; if (test[a] != 0) { --i; continue; } test.add(a,b); ++d; ++r; DLIB_TEST(test.size() == i+1); } DLIB_TEST(test.size() == 10000); for (int i = 0; i < 10000; ++i) { DLIB_TEST(*test[dtmp[i]] == rtmp[i]); } delete [] dtmp; delete [] rtmp; test.clear(); }} print_spinner(); // now do the same thing as above but with a much smaller hash table { hash_table test(13); DLIB_TEST(test.count(3) == 0); enumerable<map_pair<int,int> >& e = test; DLIB_TEST(e.at_start() == true); hash_table test2(16); hash_table test3(0); hash_table test4(0); int b; for (int j = 0; j < 4; ++j) { int a = 4; b = 5; test2.add(a,b); DLIB_TEST(test2.size() == 1); DLIB_TEST(*test2[4] == 5); DLIB_TEST(test2[99] == 0); DLIB_TEST(test2.move_next()); DLIB_TEST(test2.element().key() == 4); DLIB_TEST(test2.element().value() == 5); swap(test,test2); DLIB_TEST(test.size() == 1); DLIB_TEST(*test[4] == 5); DLIB_TEST(test[99] == 0); test.swap(test2); a = 99; b = 35; test2.add(a,b); DLIB_TEST(test2.size() == 2); DLIB_TEST(*test2[4] == 5); DLIB_TEST(*test2[99] == 35); DLIB_TEST(test2[99] != 0); DLIB_TEST(test2[949] == 0); test2.destroy(4); DLIB_TEST(test2.size() == 1); DLIB_TEST(test2[4] == 0); DLIB_TEST(*test2[99] == 35); DLIB_TEST(test2[99] != 0); DLIB_TEST(test2[949] == 0); test2.destroy(99); DLIB_TEST(test2.size() == 0); DLIB_TEST(test2[4] == 0); DLIB_TEST(test2[99] == 0); DLIB_TEST(test2[949] == 0); test2.clear(); } print_spinner(); for (int j = 0; j < 4; ++j) { DLIB_TEST(test.count(3) == 0); DLIB_TEST(test.size() == 0); DLIB_TEST(test.at_start() == true); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.move_next() == false); DLIB_TEST(test.at_start() == false); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.move_next() == false); DLIB_TEST(test.move_next() == false); int a; for (int i = 0; i < 10000; ++i) { a = ::rand()%1000; int temp = a; unsigned long count = test.count(a); test.add(a,b); DLIB_TEST(test.count(temp) == count+1); } { unsigned long count = test.count(3); a = 3; test.add(a,b); ++count; DLIB_TEST(test.count(3) == count); a = 3; test.add(a,b); ++count; DLIB_TEST(test.count(3) == count); a = 3; test.add(a,b); ++count; DLIB_TEST(test.count(3) == count); a = 3; test.add(a,b); ++count; DLIB_TEST(test.count(3) == count); } test.clear(); for (int i = 0; i < 10000; ++i) { a = b = i; unsigned long count = test.count(a); test.add(a,b); DLIB_TEST(test.count(i) == count+1); } DLIB_TEST(test.size() == 10000); DLIB_TEST(test.at_start() == true); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.move_next() == true); DLIB_TEST(test.at_start() == false); DLIB_TEST(test.current_element_valid() == true); DLIB_TEST(test.move_next() == true); DLIB_TEST(test.move_next() == true); DLIB_TEST(test.current_element_valid() == true); test.reset(); DLIB_TEST(test.size() == 10000); DLIB_TEST(test.at_start() == true); DLIB_TEST(test.current_element_valid() == false); if (test.size() > 0) { int* array = new int[test.size()]; int* tmp = array; int count = 0; while (test.move_next()) { ++count; *tmp = test.element().key(); DLIB_TEST(test[*tmp] != 0); DLIB_TEST(*tmp == test.element().key()); DLIB_TEST(*tmp == test.element().value()); DLIB_TEST(*tmp == test.element().key()); DLIB_TEST(test.current_element_valid() == true); ++tmp; } DLIB_TEST(count == 10000); DLIB_TEST(test.at_start() == false); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.move_next() == false); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.at_start() == false); DLIB_TEST(test.current_element_valid() == false); DLIB_TEST(test.size() == 10000); swap(test,test2); tmp = array; for (int i = 0; i < 10000; ++i) { DLIB_TEST(*test2[*tmp] == *tmp); DLIB_TEST(*test2[*tmp] == *tmp); DLIB_TEST(*test2[*tmp] == *tmp); ++tmp; } test2.swap(test); test.reset(); DLIB_TEST(test.at_start() == true); count = 0; tmp = array; while (test.size() > 0) { test.remove(*tmp,a,b); ++tmp; ++count; } DLIB_TEST(count == 10000); DLIB_TEST(test.size() == 0); DLIB_TEST(count == 10000); delete [] array; } test.move_next(); for (int i = 0; i < 10000; ++i) { a = ::rand(); test.add(a,b); } DLIB_TEST(test.at_start() == true); DLIB_TEST(test.move_next() == true); DLIB_TEST(test.size() == 10000); for (int i = 0; i < 10000; ++i) { test.remove_any(a,b); } DLIB_TEST(test.at_start() == true); DLIB_TEST(test.move_next() == false); DLIB_TEST(test.size() == 0); test.clear(); int* dtmp = new int[10000]; int* rtmp = new int[10000]; int* d = dtmp; int* r = rtmp; for (unsigned long i = 0; i < 10000; ++i) { a = ::rand(); b = ::rand(); *d = a; *r = b; if (test[a] != 0) { --i; continue; } test.add(a,b); ++d; ++r; DLIB_TEST(test.size() == i+1); } DLIB_TEST(test.size() == 10000); for (int i = 0; i < 10000; ++i) { DLIB_TEST(*test[dtmp[i]] == rtmp[i]); } delete [] dtmp; delete [] rtmp; test.clear(); }} } class hash_table_tester : public tester { public: hash_table_tester ( ) : tester ("test_hash_table", "Runs tests on the hash_table component.") {} void perform_test ( ) { dlog << LINFO << "testing kernel_1a"; hash_table_kernel_test<hash_table<int,int>::kernel_1a> (); dlog << LINFO << "testing kernel_1a_c"; hash_table_kernel_test<hash_table<int,int>::kernel_1a_c>(); dlog << LINFO << "testing kernel_2a"; hash_table_kernel_test<hash_table<int,int>::kernel_2a> (); dlog << LINFO << "testing kernel_2a_c"; hash_table_kernel_test<hash_table<int,int>::kernel_2a_c>(); } } a; }