text: // Copyright (C) 2005  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 <dlib/binary_search_tree.h>
  
  #include <dlib/static_map.h>
  #include "tester.h"
  
  namespace  
  {
  
      using namespace test;
      using namespace std;
      using namespace dlib;
  
      logger dlog("test.static_map");
  
      template <
          typename map
          >
      void static_map_kernel_test (
      )
      /*!
          requires
              - map is an implementation of static_map/static_map_kernel_abstract.h and
                is instantiated to map int to int
          ensures
              - runs tests on map for compliance with the specs 
      !*/
      {        
  
          print_spinner();
          srand(static_cast<unsigned int>(time(0)));
  
          typedef binary_search_tree<int,int>::kernel_2a_c bst;
          typedef hash_table<int,int>::kernel_1a_c ht;
  
          const unsigned long table_4_max_size = 100;
          const unsigned long tree_max_size = 50000;
          ht table_4(4);
          ht table_8(8);
          bst tree;
  
          ht table_4b(4);
          ht table_8b(8);
          bst treeb;
  
  
          // just do the following to make sure operator[] doesn't hang
          // under some instances
          {
              int g = 1, h = 1;
              treeb.add(g,h);
              map test;
              map test2;
  
              DLIB_TEST(test.size() == 0);
              DLIB_TEST(test.at_start());
              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);
  
              swap(test,test2);
              DLIB_TEST(test2.at_start() == false);
              DLIB_TEST(test.at_start() == true);
  
              swap(test,test2);
              DLIB_TEST(test.at_start() == false);
  
  
              DLIB_TEST(test.size() == 0);
              DLIB_TEST(test[1] == 0);
              DLIB_TEST(test[2] == 0);
              DLIB_TEST(test[3] == 0);
              DLIB_TEST(test[0] == 0);
  
              test.load(treeb);
              DLIB_TEST(test.at_start());
              DLIB_TEST(test[1] != 0);
              DLIB_TEST(test[2] == 0);
              DLIB_TEST(test[3] == 0);
              DLIB_TEST(test[0] == 0);
  
              test2.clear();
              swap(test2,test);
              DLIB_TEST(test2[1] != 0);
              DLIB_TEST(test2[2] == 0);
              DLIB_TEST(test2[3] == 0);
              DLIB_TEST(test2[0] == 0);
              DLIB_TEST(test[1] == 0);
              DLIB_TEST(test[2] == 0);
              DLIB_TEST(test[3] == 0);
              DLIB_TEST(test[0] == 0);
  
  
              DLIB_TEST(treeb.size() == 0);
              treeb.clear();
          }
  
  
          for (unsigned long i = 0; i < table_4_max_size; ++i)
          {
              int a = ::rand()&0xFF;
              int b = a + 1;
              int ab = a;
              int bb = b;
              table_4.add(a,b);
              table_4b.add(ab,bb);
          }
  
          for (unsigned long i = 0; i < table_4_max_size; ++i)
          {
              int a = ::rand()&0xF;
              int b = a + 1;
              int ab = a;
              int bb = b;
              table_8.add(a,b);
              table_8b.add(ab,bb);
          }
  
          for (unsigned long i = 0; i < tree_max_size; ++i)
          {
              int a = ::rand()&0xFFF;
              int b = a + 1;
              int ab = a;
              int bb = b;
              tree.add(a,b);
              treeb.add(ab,bb);
          }
  
          map m_4;
          m_4.load(table_4);
          map m_8;
          m_8.load(table_8);
          map m_t;
          m_t.load(tree);
          map e;
          e.load(table_4);
  
          DLIB_TEST(e.size() == 0);
          DLIB_TEST(e.at_start() == true);
          DLIB_TEST(e.current_element_valid() == false);     
          DLIB_TEST(e.move_next() == false);
          DLIB_TEST(e.at_start() == false);
          DLIB_TEST(e.current_element_valid() == false);            
  
          DLIB_TEST(m_4.size() == table_4b.size());
          DLIB_TEST(m_8.size() == table_8b.size());
          DLIB_TEST(m_t.size() == treeb.size());
  
          DLIB_TEST(m_4.at_start() == true);
          DLIB_TEST(m_8.at_start() == true);
          DLIB_TEST(m_t.at_start() == true);
          DLIB_TEST(m_4.current_element_valid() == false);            
          DLIB_TEST(m_8.current_element_valid() == false);            
          DLIB_TEST(m_t.current_element_valid() == false);     
  
  
          DLIB_TEST(m_4.move_next() == true);
          DLIB_TEST(m_4.at_start() == false);
          DLIB_TEST(m_4.current_element_valid() == true);
          DLIB_TEST(m_8.move_next() == true);
          DLIB_TEST(m_8.at_start() == false);
          DLIB_TEST(m_8.current_element_valid() == true);
          DLIB_TEST(m_t.move_next() == true);
          DLIB_TEST(m_t.at_start() == false);
          DLIB_TEST(m_t.current_element_valid() == true);
  
          m_4.reset();
          m_8.reset();
          m_t.reset();
  
          while (m_4.move_next())
          {
              DLIB_TEST( table_4b[m_4.element().key()] != 0);
              DLIB_TEST( *table_4b[m_4.element().key()] == m_4.element().value());
          }
  
          // serialize the state of m_4, then clear m_4, then
          // load the state back into m_4.
          ostringstream sout;
          serialize(m_4,sout);
          DLIB_TEST(m_4.at_start() == true);
          istringstream sin(sout.str());
          m_4.clear();
          deserialize(m_4,sin);
          DLIB_TEST(m_4.at_start() == true);
  
  
  
          while (table_4b.move_next())
          {
              DLIB_TEST( m_4[table_4b.element().key()] != 0);
              DLIB_TEST( *m_4[table_4b.element().key()] == table_4b.element().value());
          }
  
          // serialize the state of m_8, then clear m_8, then
          // load the state back into m_8.
          sout.str("");
          serialize(m_8,sout);
          DLIB_TEST(m_8.at_start() == true);
          sin.str(sout.str());
          m_8.clear();
          deserialize(m_8,sin);
          DLIB_TEST(m_8.at_start() == true);
  
          while (m_8.move_next())
          {
              DLIB_TEST( table_8b[m_8.element().key()] != 0);
              DLIB_TEST( *table_8b[m_8.element().key()] == m_8.element().value());
          }
  
          while (table_8b.move_next())
          {
              DLIB_TEST( m_8[table_8b.element().key()] != 0);
              DLIB_TEST( *m_8[table_8b.element().key()] == table_8b.element().value());
          }
  
  
          while (m_t.move_next())
          {
              DLIB_TEST( treeb[m_t.element().key()] != 0);
              DLIB_TEST( *treeb[m_t.element().key()] == m_t.element().value());
          }
  
          // make sure operator[] doesn't hang
          for (int l = 1; l < 10000; ++l)
          {
              DLIB_TEST(m_t[l+0xFFF] == 0);
          }
  
          while (treeb.move_next())
          {
              DLIB_TEST( m_t[treeb.element().key()] != 0);
              DLIB_TEST( *m_t[treeb.element().key()] == treeb.element().value());
          }
  
  
  
          m_4.reset();
          m_8.reset();
          m_t.reset();
  
          int last = 0;
          while (m_4.move_next())
          {
              DLIB_TEST(last <= m_4.element().key());
              DLIB_TEST(m_4.element().key() + 1 == m_4.element().value());
              last = m_4.element().key();
          }
  
          last = 0;
          while (m_8.move_next())
          {
              DLIB_TEST(last <= m_8.element().key());
              DLIB_TEST(m_8.element().key() + 1 == m_8.element().value());
              last = m_8.element().key();
          }
  
          last = 0;
          while (m_t.move_next())
          {
              DLIB_TEST(last <= m_t.element().key());
              DLIB_TEST(m_t.element().key() + 1 == m_t.element().value());
              last = m_t.element().key();
          }
  
  
  
  
  
  
          // this is just to test swap
          m_4.swap(m_8);
          m_4.reset();
          table_4b.reset();
          while (m_8.move_next())
          {
              DLIB_TEST( table_4b[m_8.element().key()] != 0);
              DLIB_TEST( *table_4b[m_8.element().key()] == m_8.element().value());
          }
  
          while (table_4b.move_next())
          {
              DLIB_TEST( m_8[table_4b.element().key()] != 0);
              DLIB_TEST( *m_8[table_4b.element().key()] == table_4b.element().value());
          }
  
      }
  
  
  
  
  
      class static_map_tester : public tester
      {
      public:
          static_map_tester (
          ) :
              tester ("test_static_map",
                      "Runs tests on the static_map component.")
          {}
  
          void perform_test (
          )
          {
              dlog << LINFO << "testing kernel_1a";
              static_map_kernel_test<static_map<int,int>::kernel_1a>  ();
              dlog << LINFO << "testing kernel_1a_c";
              static_map_kernel_test<static_map<int,int>::kernel_1a_c>();
          }
      } a;
  
  }
  
  