// Copyright (C) 2003 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #include #include #include #include #include #include #include "tester.h" // This is called an unnamed-namespace and it has the effect of making everything inside this file "private" // so that everything you declare will have static linkage. Thus we won't have any multiply // defined symbol errors coming out of the linker when we try to compile the test suite. namespace { using namespace test; using namespace dlib; using namespace std; // Declare the logger we will use in this test. The name of the tester // should start with "test." logger dlog("test.queue"); template < typename queue > void queue_sort_test ( ) /*! requires - queue is an implementation of queue/queue_sort_abstract.h is instantiated with int ensures - runs tests on queue for compliance with the specs !*/ { print_spinner(); srand(static_cast(time(0))); queue q,q2; enumerable& e = q; // I will use these DLIB_TEST_MSG macros to assert that conditions are true. If they are // false then it means we have detected an error in the queue object. CASSERT // will then throw an exception which we will catch at the end of this function and // report as an error/failed test. DLIB_TEST(e.at_start() == true); int a = 0; DLIB_TEST(q.size() == 0); DLIB_TEST(q.at_start() == true); DLIB_TEST(q.current_element_valid() == false); q.sort(); DLIB_TEST(q.size() == 0); DLIB_TEST(q.at_start() == true); DLIB_TEST(q.current_element_valid() == false); DLIB_TEST (q.move_next() == false); DLIB_TEST (q.move_next() == false); DLIB_TEST (q.move_next() == false); DLIB_TEST (q.move_next() == false); DLIB_TEST (q.move_next() == false); DLIB_TEST (q.move_next() == false); DLIB_TEST(q.size() == 0); DLIB_TEST(q.at_start() == false); DLIB_TEST(q.current_element_valid() == false); q.reset(); DLIB_TEST(q.size() == 0); DLIB_TEST(q.at_start() == true); DLIB_TEST(q.current_element_valid() == false); q.clear(); q2.clear(); DLIB_TEST(q.size() == 0); DLIB_TEST(q2.size() == 0); for (int i = 0; i < 10000; ++i) { int a = i; q.enqueue(a); } q2.cat(q); DLIB_TEST(q.size() == 0); DLIB_TEST(q2.size() == 10000); int g = 0; while (q2.move_next()) { DLIB_TEST_MSG(q2.element() == g,g); ++g; } for (int i = 0;i < 10000; ++i) { int a = 0; q2.dequeue(a); DLIB_TEST(a == i); } DLIB_TEST(q.size() == 0); DLIB_TEST(q2.size() == 0); q.clear(); q2.clear(); print_spinner(); dlog << LTRACE << "creating big pre-sorted queue"; q.clear(); DLIB_TEST(q.size() == 0); for (int i = 0; i < 10000; ++i) { int a = i; q.enqueue(a); } dlog << LTRACE << "sorting already sorted queue"; q.sort(); dlog << LTRACE << "done sorting, checking the results"; for (int i = 0; i < 10000; ++i) { q.dequeue(a); DLIB_TEST(a == i); } q.clear(); dlog << LTRACE << "done with the big pre-sorted queue test"; q.clear(); q2.clear(); DLIB_TEST(q.size() == 0); DLIB_TEST(q2.size() == 0); for (int i = 0; i < 1; ++i) { int a = i; q.enqueue(a); } q2.cat(q); DLIB_TEST(q.size() == 0); DLIB_TEST(q2.size() == 1); g = 0; while (q2.move_next()) { DLIB_TEST_MSG(q2.element() == g,g); ++g; } for (int i = 0;i < 1; ++i) { int a = 0; q2.dequeue(a); DLIB_TEST(a == i); } DLIB_TEST(q.size() == 0); DLIB_TEST(q2.size() == 0); q.clear(); q2.clear(); print_spinner(); for (int j = 0; j < 3; ++j) { for (int i = 0; i < 10000; ++i) { a = ::rand(); q.enqueue(a); } while (q.move_next()) ; DLIB_TEST(q.at_start() == false); q.sort(); DLIB_TEST(q.at_start() == true); // serialize the state of q, then clear q, then // load the state back into q. ostringstream sout; serialize(q,sout); DLIB_TEST(q.at_start() == true); istringstream sin(sout.str()); q.clear(); deserialize(q,sin); DLIB_TEST(q.at_start() == true); a = 0; int last = 0; while (q.move_next()) { ++a; DLIB_TEST_MSG(last <= q.element(),"items weren't actually sorted"); last = q.element(); DLIB_TEST(q.current_element_valid() == true); DLIB_TEST(q.at_start() == false); DLIB_TEST(q.current_element_valid() == true); } DLIB_TEST_MSG(a == 10000,"some items were lost between the sorting and iterating"); DLIB_TEST(q.size() == 10000); swap(q,q2); DLIB_TEST(q2.at_start() == false); DLIB_TEST(q2.current_element_valid() == false); DLIB_TEST (q2.move_next() == false); DLIB_TEST (q2.move_next() == false); DLIB_TEST (q2.move_next() == false); DLIB_TEST (q2.move_next() == false); DLIB_TEST (q2.move_next() == false); DLIB_TEST (q2.move_next() == false); DLIB_TEST(q2.size() == 10000); DLIB_TEST(q2.at_start() == false); DLIB_TEST(q2.current_element_valid() == false); q2.clear(); q.swap(q2); DLIB_TEST(q.size() == 0); DLIB_TEST(q.at_start() == true); DLIB_TEST(q.current_element_valid() == false); } print_spinner(); // try the above code but this time with just one element // in the queue for (int j = 0; j < 3; ++j) { for (int i = 0; i < 1; ++i) { a = ::rand(); q.enqueue(a); } q.sort(); a = 0; int last = 0; while (q.move_next()) { ++a; DLIB_TEST_MSG(last <= q.element(),"items weren't actually sorted"); DLIB_TEST(q.current_element_valid() == true); } DLIB_TEST_MSG(a == 1,"some items were lost between the sorting and iterating"); DLIB_TEST(q.size() == 1); DLIB_TEST(q.at_start() == false); DLIB_TEST(q.current_element_valid() == false); q.clear(); DLIB_TEST(q.size() == 0); DLIB_TEST(q.at_start() == true); DLIB_TEST(q.current_element_valid() == false); } print_spinner(); { q.clear(); remover& go = q; for (int i = 0; i < 100; ++i) { int a = 3; q.enqueue(a); } DLIB_TEST(go.size() == 100); for (int i = 0; i < 100; ++i) { int a = 9; q.remove_any(a); DLIB_TEST(a == 3); } DLIB_TEST(go.size() == 0); } } struct factory { template struct return_type { typedef typename memory_manager::kernel_3c type; }; template static typename return_type::type* get_instance ( ) { static typename return_type::type a; return &a; } }; class queue_tester : public tester { /*! WHAT THIS OBJECT REPRESENTS This object represents a test for the queue object. When it is constructed it adds itself into the testing framework. The command line switch is specified as test_queue by passing that string to the tester constructor. !*/ public: queue_tester ( ) : tester ("test_queue", "Runs tests on the queue component.") {} void perform_test ( ) { // There are multiple implementations of the queue object so use // the templated function defined above to test them all and report // a failed test if any of them don't pass. typedef dlib::memory_manager_global::kernel_1a mm; dlog << LINFO << "testing sort_1a_c"; queue_sort_test::sort_1a_c> (); dlog << LINFO << "testing sort_1a"; queue_sort_test::sort_1a>(); dlog << LINFO << "testing sort_1b"; queue_sort_test::sort_1b> (); dlog << LINFO << "testing sort_1b_c"; queue_sort_test::sort_1b_c>(); dlog << LINFO << "testing sort_1c"; queue_sort_test::sort_1c> (); dlog << LINFO << "testing sort_1c_c"; queue_sort_test::sort_1c_c>(); } } a; }