⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hash_test.cpp

📁 stl的源码
💻 CPP
字号:
//Has to be first for StackAllocator swap overload to be taken//into account (at least using GCC 4.0.1)#include "stack_allocator.h"#include <vector>#include <algorithm>#include <map>#include <set>#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)#  include <hash_map>#  include <hash_set>#  include <rope>#endif#include <string>#include "cppunit/cppunit_proxy.h"#if defined (__MVS__)const char star = 92;#elseconst char star = 42;#endif#if !defined (STLPORT) || defined (_STLP_USE_NAMESPACES)using namespace std;#endif//// TestCase class//class HashTest : public CPPUNIT_NS::TestCase{  CPPUNIT_TEST_SUITE(HashTest);#if !defined (STLPORT) || defined (_STLP_NO_EXTENSIONS)  CPPUNIT_IGNORE;#endif  CPPUNIT_TEST(hmap1);  CPPUNIT_TEST(hmmap1);  CPPUNIT_TEST(hmmap2);  CPPUNIT_TEST(hmset1);  CPPUNIT_TEST(hset2);  CPPUNIT_TEST(insert_erase);  CPPUNIT_TEST(allocator_with_state);  //CPPUNIT_TEST(equality);  CPPUNIT_TEST_SUITE_END();#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)  typedef hash_multiset<char, hash<char>, equal_to<char> > hmset;#endifprotected:  void hmap1();  void hmmap1();  void hmmap2();  void hmset1();  void hset2();  void insert_erase();  //void equality();  void allocator_with_state();#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)  typedef hash_multimap<int, int> hashType;  typedef multimap<int, int> mapType;  void check_keys( hashType& h, mapType& m );#endif};CPPUNIT_TEST_SUITE_REGISTRATION(HashTest);//// tests implementation//void HashTest::hmap1(){#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)  typedef hash_map<char, crope, hash<char>, equal_to<char> > maptype;  maptype m;  // Store mappings between roman numerals and decimals.  m['l'] = "50";  m['x'] = "20"; // Deliberate mistake.  m['v'] = "5";  m['i'] = "1";  CPPUNIT_ASSERT( !strcmp(m['x'].c_str(),"20") );  m['x'] = "10"; // Correct mistake.  CPPUNIT_ASSERT( !strcmp(m['x'].c_str(),"10") );  CPPUNIT_ASSERT( !strcmp(m['z'].c_str(),"") );  CPPUNIT_ASSERT( m.count('z')==1 );  pair<maptype::iterator, bool> p = m.insert(pair<const char, crope>('c', crope("100")));  CPPUNIT_ASSERT(p.second);  p = m.insert(pair<const char, crope>('c', crope("100")));  CPPUNIT_ASSERT(!p.second);  //Some iterators compare check, really compile time checks  maptype::iterator ite(m.begin());  maptype::const_iterator cite(m.begin());  cite = m.begin();  maptype const& cm = m;  cite = cm.begin();  CPPUNIT_ASSERT( ite == cite );  CPPUNIT_ASSERT( !(ite != cite) );  CPPUNIT_ASSERT( cite == ite );  CPPUNIT_ASSERT( !(cite != ite) );#endif}void HashTest::hmmap1(){#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)  typedef hash_multimap<char, int, hash<char>,equal_to<char> > mmap;  mmap m;  CPPUNIT_ASSERT(m.count('X')==0);  m.insert(pair<const char,int>('X', 10)); // Standard way.  CPPUNIT_ASSERT(m.count('X')==1);//  m.insert('X', 20); // Non-standard, but very convenient!  m.insert(pair<const char,int>('X', 20));  // jbuck: standard way  CPPUNIT_ASSERT(m.count('X')==2);//  m.insert('Y', 32);  m.insert(pair<const char,int>('Y', 32));  // jbuck: standard way  mmap::iterator i = m.find('X'); // Find first match.  CPPUNIT_ASSERT((*i).first=='X');  CPPUNIT_ASSERT((*i).second==10);  i++;  CPPUNIT_ASSERT((*i).first=='X');  CPPUNIT_ASSERT((*i).second==20);  i++;  CPPUNIT_ASSERT((*i).first=='Y');  CPPUNIT_ASSERT((*i).second==32);  i++;  CPPUNIT_ASSERT(i==m.end());  size_t count = m.erase('X');  CPPUNIT_ASSERT(count==2);  //Some iterators compare check, really compile time checks  mmap::iterator ite(m.begin());  mmap::const_iterator cite(m.begin());  CPPUNIT_ASSERT( ite == cite );  CPPUNIT_ASSERT( !(ite != cite) );  CPPUNIT_ASSERT( cite == ite );  CPPUNIT_ASSERT( !(cite != ite) );  typedef hash_multimap<size_t, size_t> HMapType;  HMapType hmap;  //We fill the map to implicitely start a rehash.  for (size_t counter = 0; counter < 3077; ++counter)    hmap.insert(HMapType::value_type(1, counter));  hmap.insert(HMapType::value_type(12325, 1));  hmap.insert(HMapType::value_type(12325, 2));  CPPUNIT_ASSERT( hmap.count(12325) == 2 );  //At this point 23 goes to the same bucket as 12325, it used to reveal a bug.  hmap.insert(HMapType::value_type(23, 0));  CPPUNIT_ASSERT( hmap.count(12325) == 2 );#endif}#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)// Short demonstrator that helps reproducing a bug in the hash-table implementation// of STLPort 5.0.1/5.0.2.//// Problem: Fill a hash_multimap with entries of which many have the same key//          Internally, entries with the same key are kept as one block within the same bucket.//          Thus, when calling equal_range(key) the begin/end of that block is returned.//          However, this code shows that for key =3, that block is destroyed after inserting the 194th element.//          According to _hashtable.c we will have a rehash from size 193 to size 389 in that situation.//          After that rehash,  equal_range only returns 2 elements with key = 3 whereas there are 65 in it.// Reproduction://          In the main()-method we fill a hash_multimap as well as a multi_map with the same <key, data> pairs//          After each insertion we call check_keys(...) to assure validity of these two containers.//          This works fine up to the 193th insertion. Insertion 194 generates the bug.////          check_keys() works as follows://          (a) we check whether both containers contain the same number of elements.//          (b) Assuming that the multi_map works correctly, we iterate over all its elements and check//              whether we can find that key also in the hash_multimap. We collect all data for that specific//              key in in a set ("collection"). Notice that data is unique by construction in main(), thus the//              number of elements in the set must equal the number of entries in the hash_multimap and in the multimap//          (c) We check if we have seen as many data elements in collection as we have seen in the multimap.//              if so, we print "OK", otherwise we print a detailed key/data overview and assert.// Caution://        There are several configurations of the program that will NOT fail. (see comment in code below)//        E.g. it seems that whenever the keys are more or less sorted, the problem does not occur.//        Also, using numbers from 200 downto 1 or from 300 downto 1 cannot generate the problem,//        whereas using 400 downto 1 will fail.//        Finally, if we use key 1 (rather than key 3) we cannot generate a problem.void HashTest::check_keys( HashTest::hashType& h, HashTest::mapType& m ){  set<int> collection;  // (a) check sizes  CPPUNIT_CHECK( h.size() == m.size() );  // (b) iterate over multi_map  for ( mapType::iterator i = m.begin(); i != m.end(); ++i ) {    // look up that key in hash-table and keep all data in the set    pair<hashType::iterator,hashType::iterator> range = h.equal_range( i->first );    for ( hashType::iterator j = range.first; j != range.second; ++j ) {      collection.insert( j->second );    }  }  // (c) we should have seen as many elements as there are in the hash-table#if 0  if (collection.size() == h.size()) cout << " OK" << endl;  else {    // if not, please report    cout << " FAILED: " << endl;    int lastKey  = -1;    // iterate over all elements in multi_map    for (mapType::iterator mIter = m.begin(); mIter != m.end(); mIter++) {      // new key? print a new status line      if (mIter->first != lastKey) {        cout << endl << "Key : " << mIter->first << endl;        lastKey = mIter->first;        // print all hashed values for that key        cout << " data in hash: ";        pair<hashType::iterator,hashType::iterator> range = h.equal_range(mIter->first);        for (hashType::iterator h = range.first; h != range.second; h++) {          assert (h->first == lastKey);          cerr << h->second << ", "; // print all data for that key in Hash-Table        }        cout << endl << " data in map:  ";      }      // and print all member in multi-map until the next key occurs      cout << mIter->second << ", " ;  // print all data for that key in Map    }  }#endif  CPPUNIT_CHECK( collection.size() == h.size() );}#endifvoid HashTest::hmmap2(){#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)  hashType h;  mapType m;  // CAUTION the following configurations WORKS in our setting  //      for (int id = 1; id != 400; id ++)   and int key = (id %3 == 0 ? 3 : id)  //      for (int id = 200; id != 1; id --)   and int key = (id %3 == 0 ? 3 : id)  //      for (int id = 300; id != 1; id --)   and int key = (id %3 == 0 ? 3 : id)  //      for (int id = 400; id != 1; id --)   and int key = (id %3 == 0 ? 1 : id)  //      for (int id = 4000; id != 1; id --)  and int key = (id %3 == 0 ? 1 : id)  //  // whereas these will FAIL  //      for (int id = 400; id != 1; id --)   and int key = (id %3 == 0 ? 3 : id)  //      for (int id = 4000; id != 1; id --)  and int key = (id %3 == 0 ? 3 : id)  //  for ( int id = 400; id != 1; id-- ) {    // generate many entries with key 3, fill up with unique keys. Data is unique (needed in check_keys())    int key = (id % 3 == 0 ? 3 : id);    // keep hash_multi_map and multimap in sync    h.insert(make_pair(key, id));    m.insert(make_pair(key, id));    // check whether both contain the same elements    check_keys( h, m );  }#endif}void HashTest::hmset1(){#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)  hmset s;  CPPUNIT_ASSERT( s.count(star) == 0 );  s.insert(star);  CPPUNIT_ASSERT( s.count(star) == 1 );  s.insert(star);  CPPUNIT_ASSERT( s.count(star) == 2 );  hmset::iterator i = s.find(char(40));  CPPUNIT_ASSERT( i == s.end() );  i = s.find(star);  CPPUNIT_ASSERT( i != s.end() )  CPPUNIT_ASSERT( *i == '*' );  CPPUNIT_ASSERT( s.erase(star) == 2 );#endif}void HashTest::hset2(){#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)  hash_set<int, hash<int>, equal_to<int> > s;  pair<hash_set<int, hash<int>, equal_to<int> >::iterator, bool> p = s.insert(42);  CPPUNIT_ASSERT( p.second );  CPPUNIT_ASSERT( *(p.first) == 42 );  p = s.insert(42);  CPPUNIT_ASSERT( !p.second );#endif}void HashTest::insert_erase(){#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)  typedef hash_map<string, size_t, hash<string>, equal_to<string> > hmap;  typedef hmap::value_type val_type;  {    hmap values;#  if !defined (__BORLANDC__) || (__BORLANDC__ >= 0x564)    CPPUNIT_ASSERT( values.insert(val_type("foo", 0)).second );    CPPUNIT_ASSERT( values.insert(val_type("bar", 0)).second );    CPPUNIT_ASSERT( values.insert(val_type("abc", 0)).second );#  else    CPPUNIT_ASSERT( values.insert(hmap::value_type("foo", 0)).second );    CPPUNIT_ASSERT( values.insert(hmap::value_type("bar", 0)).second );    CPPUNIT_ASSERT( values.insert(hmap::value_type("abc", 0)).second );#  endif    CPPUNIT_ASSERT( values.erase("foo") == 1 );    CPPUNIT_ASSERT( values.erase("bar") == 1 );    CPPUNIT_ASSERT( values.erase("abc") == 1 );  }  {    hmap values;#  if !defined (__BORLANDC__) || (__BORLANDC__ >= 0x564)    CPPUNIT_ASSERT( values.insert(val_type("foo", 0)).second );    CPPUNIT_ASSERT( values.insert(val_type("bar", 0)).second );    CPPUNIT_ASSERT( values.insert(val_type("abc", 0)).second );#  else    CPPUNIT_ASSERT( values.insert(hmap::value_type("foo", 0)).second );    CPPUNIT_ASSERT( values.insert(hmap::value_type("bar", 0)).second );    CPPUNIT_ASSERT( values.insert(hmap::value_type("abc", 0)).second );#  endif    CPPUNIT_ASSERT( values.erase("abc") == 1 );    CPPUNIT_ASSERT( values.erase("bar") == 1 );    CPPUNIT_ASSERT( values.erase("foo") == 1 );  }#endif}/* * Here is the test showing why equality operator on hash containers * has no meaning:struct equality_hash_func {  size_t operator () (size_t val) const {    return val % 10;  }};void HashTest::equality(){  hash_set<size_t, equality_hash_func, equal_to<size_t> > s1, s2;  s1.insert(10);  s1.insert(20);  s2.insert(20);  s2.insert(10);  //s1 and s2 contains both 10 and 20:  CPPUNIT_ASSERT( s1 == s2 );}*/void HashTest::allocator_with_state(){#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)  char buf1[2048];  StackAllocator<int> stack1(buf1, buf1 + sizeof(buf1));  char buf2[2048];  StackAllocator<int> stack2(buf2, buf2 + sizeof(buf2));  {    typedef hash_set<int, hash<int>, equal_to<int>, StackAllocator<int> > HashSetInt;    HashSetInt hint1(10, hash<int>(), equal_to<int>(), stack1);    int i;    for (i = 0; i < 5; ++i)      hint1.insert(i);    HashSetInt hint1Cpy(hint1);    HashSetInt hint2(10, hash<int>(), equal_to<int>(), stack2);    for (; i < 10; ++i)      hint2.insert(i);    HashSetInt hint2Cpy(hint2);    hint1.swap(hint2);    CPPUNIT_ASSERT( hint1.get_allocator().swaped() );    CPPUNIT_ASSERT( hint2.get_allocator().swaped() );    CPPUNIT_ASSERT( hint1.get_allocator() == stack2 );    CPPUNIT_ASSERT( hint2.get_allocator() == stack1 );  }  CPPUNIT_ASSERT( stack1.ok() );  CPPUNIT_ASSERT( stack2.ok() );#endif}#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS) && \   (!defined (_STLP_USE_PTR_SPECIALIZATIONS) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION))#  if !defined (__DMC__)/* Simple compilation test: Check that nested types like iterator * can be access even if type used to instanciate container is not * yet completely defined. */class IncompleteClass{  hash_set<IncompleteClass> hsinstances;  typedef hash_set<IncompleteClass>::iterator hsit;  hash_multiset<IncompleteClass> hsminstances;  typedef hash_multiset<IncompleteClass>::iterator hsmit;  hash_map<IncompleteClass, IncompleteClass> hminstances;  typedef hash_map<IncompleteClass, IncompleteClass>::iterator hmit;  hash_multimap<IncompleteClass, IncompleteClass> hmminstances;  typedef hash_multimap<IncompleteClass, IncompleteClass>::iterator hmmit;};#  endif#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -