diff options
author | Jesse Morgan <jesse@jesterpm.net> | 2016-12-17 21:28:53 -0800 |
---|---|---|
committer | Jesse Morgan <jesse@jesterpm.net> | 2016-12-17 21:28:53 -0800 |
commit | 54df2afaa61c6a03cbb4a33c9b90fa572b6d07b8 (patch) | |
tree | 18147b92b969d25ffbe61935fb63035cac820dd0 /db-4.8.30/test_stl/base/test_assoc.h |
Berkeley DB 4.8 with rust build script for linux.
Diffstat (limited to 'db-4.8.30/test_stl/base/test_assoc.h')
-rw-r--r-- | db-4.8.30/test_stl/base/test_assoc.h | 2470 |
1 files changed, 2470 insertions, 0 deletions
diff --git a/db-4.8.30/test_stl/base/test_assoc.h b/db-4.8.30/test_stl/base/test_assoc.h new file mode 100644 index 0000000..a4bca87 --- /dev/null +++ b/db-4.8.30/test_stl/base/test_assoc.h @@ -0,0 +1,2470 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2009 Oracle. All rights reserved. + * + * $Id$ + */ + +#include "test.h" +// This function tests all member functions in the four assocative +// containers and their iterators. The containers are db_map, +// db_multimap, db_set, db_multiset . They are equivalent to std::map, +// hash_map, std::multimap, hash_multimap, std::set, hash_set, +// std::multiset, hash_multiset respectively---passing btree db handles, +// they are equivalent to std assocative container; passing hash db handles +// they are hash associative containers +// +// This function tests the classes also in pair with std/hash counterparts, +// but the result of some operations are checked not by comparing contents +// after operation, but by self-check, often use another member function of +// the same class to verify. Also, only the four container types in std is +// used, the hash containers are not standarized, so not used, although +// hash db type can be passed in, so the db_containers can be of hash type +// +// Most of the algorithms in std are targeting at a sequential range, while +// ranges in associative containers are not, so only some read only +// algorithms are applied to the db_map container. +// +// This function also tests some advanced features, like using containers +// with secondary db, bulk retrieval, varying length records storage/load, +// storing native char*/wchar_t* strings, etc +// + +static int hcmp_def(Db *pdb, const Dbt *dbt1, const Dbt *dbt2) +{ + u_int32_t sz1 = dbt1->get_size(), sz2 = dbt2->get_size(); + + int ret = memcmp(dbt1->get_data(), dbt2->get_data(), sz1 < sz2 ? sz1 : sz2); + ret = (ret == 0) ? (sz1 - sz2) : ret; + + return ret; +} + +class TestAssoc +{ +public: + typedef map<int, int> m_int_t; + typedef ptint tpint; + ~TestAssoc(); + TestAssoc(void *param1); + void start_test() + { + tb.begin("db_map"); + test_map_member_functions(); + test_map_std_functions(); + test_hot_dbclose(); + test_arbitrary_object_storage(); + test_storing_std_strings(); + test_secondary_containers(); + tb.end(); + + tb.begin("db_multimap"); + test_mmap_member_functions(); + tb.end(); + + tb.begin("db_set"); + test_set_member_functions(); + tb.end(); + + tb.begin("db_multiset"); + test_mset_member_functions(); + tb.end(); + + tb.begin("Special functionalities of all dbstl containers."); + test_char_star_string_storage(); + test_fixed_len_obj_storage(); + test_arbitray_sequence_storage(); + test_bulk_retrieval_read(); + test_nested_txns(); + test_etc(); + tb.end(); + + + } +private: + // Test all member functions of db_map<> + void test_map_member_functions(); + + // Use std functions to manipulate db_map containers. + void test_map_std_functions(); + + // Close a live container's db handle then open it again and + // reassign to the same container, verify the container works. + void test_hot_dbclose(); + + // Use two ways to store an object of arbitrary length. The object + // contains some varying length members, char* string for example. + void test_arbitrary_object_storage(); + + void test_storing_std_strings(); + + // Open a secondary db H and associate it with an exisitng db handle + // which is being used by a container C1, then use H to create another + // container C2, verify we can get C1's data via C2. + // This technique works for all types of db and containers. + void test_secondary_containers(); + + // Test all member functions of db_multimap<>. + void test_mmap_member_functions(); + + // Test all member functions of db_set<>. + void test_set_member_functions(); + + // Test all member functions of db_multiset<>. + void test_mset_member_functions(); + + // Test direct storage of char* strings. + void test_char_star_string_storage(); + + // Testing storage of fixed length objects. + void test_fixed_len_obj_storage(); + + // Testing storage of arbitrary element type of sequence. + void test_arbitray_sequence_storage(); + + // Testing reading with bulk retrieval flag. + void test_bulk_retrieval_read(); + + // Testing nested transaction implementation. + void test_nested_txns(); + + // Testing miscellaneous functions. + void test_etc(); + + int flags, setflags, EXPLICIT_TXN, TEST_AUTOCOMMIT, n; + DBTYPE dbtype; + dm_int_t::difference_type oddcnt; + Db *dmdb1, *dmdb2, *dmmdb1, *dmmdb2, *dmsdb1, + *dmsdb2, *dmmsdb1, *dmmsdb2, *dbstrv; + Db *dbp3; + Db *dmdb6; + Db *dbp3sec; + Db *dmmdb4, *dbstrmap; + Db *dmstringdb; + DbEnv *penv; + u_int32_t dboflags; + + test_block tb; + map<int, int> m1; + multimap<int, int> mm1; +}; + +TestAssoc::~TestAssoc() +{ + dbstl::close_db_cursors(this->dmsdb2); + dbstl::close_db_cursors(this->dmdb1); + dbstl::close_db_cursors(this->dmdb2); + dbstl::close_db_cursors(this->dmdb6); + dbstl::close_db_cursors(this->dmmdb1); +} + +TestAssoc::TestAssoc(void *param1) +{ + check_expr(param1 != NULL); + TestParam *param = (TestParam*)param1; + TestParam *ptp = param; + + flags = 0, setflags = 0, EXPLICIT_TXN = 1, TEST_AUTOCOMMIT = 0; + dbtype = DB_BTREE; + penv = param->dbenv; + dmdb1 = dmdb2 = dmmdb1 = dmmdb2 = dmsdb1 = dmsdb2 = dmmsdb1 = + dmmsdb2 = dbstrv = NULL; + flags = param->flags; + dbtype = param->dbtype; + setflags = param->setflags; + TEST_AUTOCOMMIT = param->TEST_AUTOCOMMIT; + EXPLICIT_TXN = param->EXPLICIT_TXN; + dboflags = ptp->dboflags; + n = 10; + + dmdb1 = dbstl::open_db(penv, "db_map.db", + dbtype, DB_CREATE | ptp->dboflags, 0); + dmdb2 = dbstl::open_db(penv, "db_map2.db", + dbtype, DB_CREATE | ptp->dboflags, 0); + dmdb6 = dbstl::open_db(penv, "db_map6.db", + dbtype, DB_CREATE | ptp->dboflags, 0); + + dmmdb1 = dbstl::open_db(penv, + "db_multimap.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP); + dmmdb2 = dbstl::open_db(penv, + "db_multimap2.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP); + + dmsdb1 = dbstl::open_db(penv, "db_set.db", + dbtype, DB_CREATE | ptp->dboflags, 0); + dmsdb2 = dbstl::open_db(penv, "db_set2.db", + dbtype, DB_CREATE | ptp->dboflags, 0); + + dmmsdb1 = dbstl::open_db(penv, + "db_multiset.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP); + dmmsdb2 = dbstl::open_db(penv, + "db_multiset2.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP); + + dbstrv = dbstl::open_db(penv, "dbstr.db", + DB_RECNO, DB_CREATE | ptp->dboflags, DB_RENUMBER); + dbp3sec = dbstl::open_db(penv, "db_map_sec.db", + dbtype, DB_CREATE | ptp->dboflags, DB_DUP); + + dmmdb4 = dbstl::open_db(penv, + "db_multimap4.db", dbtype, DB_CREATE | dboflags, DB_DUPSORT); + dbstrmap = dbstl::open_db(penv, "dbstrmap.db", + DB_BTREE, DB_CREATE, 0); + + dmstringdb = dbstl::open_db(penv, "db_map_stringdb.db", + dbtype, DB_CREATE | dboflags, 0); + dbp3 = NULL; + +} + +void TestAssoc::test_map_member_functions() +{ + int i; + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + dm_int_t dm1(dmdb1, penv); + const dm_int_t& cnstdm1 = dm1; + dm_int_t simple_map; + map<ptint, ptint> ssimple_map; + map<ptint, ptint>::iterator sitr, sitr1; + + for (i = 0; i < n; i++) { + dm1[i] = ptint(i); + ssimple_map[i] = ptint(i); + } + + for (i = 0; i < n; i++) { + dm_int_t::const_iterator citr, citr1; + dm_int_t::iterator itr; + + citr = dm1.find(i); + check_expr(citr->second == dm1.find(i)->second); + itr = citr; + check_expr(*citr == *itr); + itr->second = i * 2 + 1; + citr1 = itr; + check_expr(*citr == *itr); + check_expr(*citr == *citr1); + check_expr(citr->second == dm1.find(i)->second); + } + + for (i = 0; i < n; i++) { + dm_int_t::const_iterator citr = dm1.find(i); + check_expr(citr->second == dm1.find(i)->second); + dm_int_t::iterator itr = citr; + check_expr(*citr == *itr); + itr->second = i * 2 + 1; + dm_int_t::const_iterator citr1 = itr; + check_expr(*citr == *itr); + check_expr(*citr == *citr1); + check_expr(citr->second == dm1.find(i)->second); + } + + for (i = 0; i < n; i++) { + dm_int_t::iterator ncitr, ncitr1; + dm_int_t::const_iterator citr, citr1; + + ncitr = cnstdm1.find(i); + check_expr(ncitr->second == cnstdm1.find(i)->second); + citr = ncitr; + check_expr(*citr == *ncitr); + //*ncitr = i * 2 + 1; + citr1 = ncitr; + ncitr1 = citr1; + check_expr(*citr == *ncitr); + check_expr(*citr == *ncitr1); + check_expr(*citr == *citr1); + check_expr(citr->second == cnstdm1.find(i)->second); + } + + for (i = 0; i < n; i++) { + + dm_int_t::iterator ncitr = cnstdm1.find(i); + check_expr(ncitr->second == cnstdm1.find(i)->second); + dm_int_t::const_iterator citr = ncitr; + check_expr(*citr == *ncitr); + //*itr = i * 2 + 1; + dm_int_t::const_iterator citr1 = ncitr; + dm_int_t::iterator ncitr1 = citr1; + + check_expr(*citr == *ncitr); + check_expr(*citr == *ncitr1); + check_expr(*citr == *citr1); + check_expr(citr->second == cnstdm1.find(i)->second); + } + + if (dm1.is_hash() == false) + { + dm1.clear(); + ssimple_map.clear(); + for (i = 0; i < n; i++) { + dm1[i] = ptint(i); + ssimple_map[i] = ptint(i); + } + dm_int_t::iterator ncitr = dm1.end(); + dm_int_t::iterator ncrend = --dm1.begin(); + map<ptint, ptint>::iterator sitr = ssimple_map.end(); + for (sitr--, --ncitr; ncitr != ncrend; ncitr--, sitr--) { + ncitr.refresh(true); // not needed because by default we are using direct db get, only for test purpose. + check_expr(*sitr == *ncitr); + } + ncitr.close_cursor(); + + const dm_int_t&cnstdm1 = dm1; + dm_int_t::const_iterator citr = cnstdm1.end(); + dm_int_t::const_iterator crend = --cnstdm1.begin(); + map<ptint, ptint>::iterator sitr2; + map<ptint, ptint>::reverse_iterator rsitr; + + sitr = ssimple_map.end(); + for (sitr--, --citr; citr!= crend; sitr--, citr--) { + citr.refresh(true); // not needed because by default we are using direct db get, only for test purpose. + check_expr(*sitr == *citr); + } + + for (sitr2 = --ssimple_map.begin(), citr = crend; citr != cnstdm1.end();) { + citr++; + sitr2++; + check_expr(*sitr2 == *citr); + } + + simple_map.insert(simple_map.begin(), *ssimple_map.begin()); + check_expr(*simple_map.begin() == *ssimple_map.begin()); + crend = --cnstdm1.begin(); + --(--crend); + ++crend; + check_expr(*crend == *cnstdm1.begin()); + citr.close_cursor(); + + simple_map.clear(); + simple_map.insert(cnstdm1.begin(), cnstdm1.end()); + rsitr = ssimple_map.rbegin(); + for (dm_int_t::reverse_iterator itrr1 = simple_map.rbegin(); itrr1 != simple_map.rend(); ++itrr1, ++rsitr) + check_expr(*itrr1 == *rsitr); + + const dm_int_t &csimple_map = simple_map; + rsitr = ssimple_map.rbegin(); + for (dm_int_t::const_reverse_iterator citrr1 = csimple_map.rbegin(); citrr1 != csimple_map.rend(); ++citrr1, ++rsitr) + check_expr((citrr1->first == rsitr->first) && (citrr1->second == rsitr->second)); + + for (sitr = ssimple_map.begin(); sitr != ssimple_map.end(); ++sitr) + check_expr(csimple_map[sitr->first] == sitr->second); + + simple_map.erase(simple_map.end()); + check_expr(simple_map.size() == ssimple_map.size()); + check_expr(csimple_map.find(123) == csimple_map.end()); + + check_expr(*csimple_map.lower_bound(1) == *ssimple_map.lower_bound(1)); + check_expr(*csimple_map.upper_bound(5) == *ssimple_map.upper_bound(5)); + pair<dm_int_t::const_iterator, dm_int_t::const_iterator> cnsteqrg = csimple_map.equal_range(3); + check_expr(cnsteqrg.first->first == 3 && cnsteqrg.second->first == ssimple_map.equal_range(3).second->first); + + } + dm1.clear(); + ssimple_map.clear(); + + if (!dm1.is_hash()) { + for (i = 0; i < n; i++) { + dm1[i] = ptint(i); + ssimple_map[i] = ptint(i); + } + dm_int_t::iterator itr, itr1; + + itr = dm1.find(3); + itr1 = dm1.find(8); + sitr = ssimple_map.find(3); + sitr1 = ssimple_map.find(8); + + dm1.erase(itr, itr1); + ssimple_map.erase(sitr, sitr1); + pprint(dm1, "dm1 after erasing range: "); + check_expr(is_equal(dm1, ssimple_map)); + dm1.clear(); + ssimple_map.clear(); + } + for (i = 0; i < 10; i++) { + simple_map.insert(make_pair(ptint(i), ptint(i))); + ssimple_map.insert(make_pair(ptint(i), ptint(i))); + } + for (i = 0; i < 10; i++) + check_expr(simple_map[i] == ssimple_map[i]); + + dm1.clear(); + // db_map<>::empty + check_expr(dm1.empty()); + fill(dm1, m1, i = 3, n = 5); + check_expr(!dm1.empty()); + + dm_int_t::iterator dmi, dmi2; + m_int_t::iterator mi; + dm_int_t::reverse_iterator dmri; + m_int_t::reverse_iterator mri; + ptint ptmp; + int itmp; + + + // db_map<>::find, count + for (dmi = dm1.begin(), mi = m1.begin(), i = 3; dmi != dm1.end() && + mi !=m1.end(); dmi++, mi++, i++) { + // check_expr both contain + check_expr((dm1.find(i) != dm1.end()) && + (m1.find(i) != m1.end())); + + pair<dm_int_t::iterator, dm_int_t::iterator> erp = + dm1.equal_range(i); + int jc = 0; + dm_int_t::iterator jj; + for (jj = erp.first, jc = 0; + jj != erp.second; jj++, jc++) + check_expr((*jj).second == ptint(i)); + check_expr(jc == 1); + if (i < 7 && !dm1.is_hash()) {// 7 is last element + check_expr((*(dm1.upper_bound(i))).second == i + 1); + check_expr((*(dm1.lower_bound(i))).second == i); + } + else if (i == 7 && !dm1.is_hash()) { + check_expr(dm1.upper_bound(i) == dm1.end()); + check_expr((*(dm1.lower_bound(i))).second == i); + } else if (!dm1.is_hash()) + check_expr(false); + + check_expr(dm1.count(i) == 1); + check_expr(dm1.count(-i) == 0); + check_expr((ptmp = dm1[i]) == (itmp = m1[i])); + + // order of elements in hash can not be expected + if (!dm1.is_hash()) + check_expr((*dmi).second == (*mi).second); + if (i == 3 + n - 1) {// last element + + for (; dmi != dm1.end(); mi--, i--) { + // check_expr both contains + check_expr((*(dm1.find(i))).second == i); + check_expr((ptmp = dm1[i]) == (itmp = m1[i])); + // order of elements in hash can not be + // expected + if (!dm1.is_hash()) + check_expr((*dmi).second == (*mi).second); + if (i % 2) + dmi--; + else + --dmi; + } + break; + } + + } + for (dmri = dm1.rbegin(), mri = m1.rbegin(), i = 3; + dmri != dm1.rend() && mri != m1.rend(); dmri++, mri++, i++) { + check_expr((dm1.find(i) != dm1.end()) && + (m1.find(i) != m1.end()));// check_expr both contain + + check_expr(dm1[i] == m1[i]); + if (!dm1.is_hash()) + check_expr((*dmri).second == (*mri).second); + if (i == 3 + n - 1) {// last element + + for (; dmri != dm1.rend(); mri--, i--) { + // check_expr both contain + check_expr((*(dm1.find(i))).second == i); + // order of elements in hash can not be expected + if (!dm1.is_hash()) + check_expr((*dmri).second == (*mri).second); + check_expr((ptmp = dm1[i]) == (itmp = m1[i])); + if (i % 2) + dmri--; + else + --dmri; + if (i == 3) + break; + } + break; + } + + } + for (dmi = dm1.begin(), mi = m1.begin(), i = 3; dmi != dm1.end() && + mi !=m1.end(); ++dmi, mi++) + i++; + check_expr(i == 3 + n);// i must have been incremented to 8 + for (dmri = dm1.rbegin(), mri = m1.rbegin(), i = 3; + dmri != dm1.rend() && mri !=m1.rend(); ++dmri, mri++) + i++; + check_expr(i == 3 + n);// i must have been incremented to 8 + + + if (EXPLICIT_TXN) + commit_txn(penv); + if (!TEST_AUTOCOMMIT) + begin_txn(0, penv); + dm_int_t dm2(dmdb2, penv); + dm2.clear(); + if (!TEST_AUTOCOMMIT) + commit_txn(penv); + if (EXPLICIT_TXN) + begin_txn(0, penv); + dm2.insert(dm1.begin(), dm1.end()); + if (EXPLICIT_TXN) + commit_txn(penv); + if (!TEST_AUTOCOMMIT) + begin_txn(0, penv); + dm_int_t dm3 = dm2; + if (!TEST_AUTOCOMMIT) + commit_txn(penv); + if (EXPLICIT_TXN) + begin_txn(0, penv); + check_expr(dm3 == dm2); + if (EXPLICIT_TXN) + commit_txn(penv); + if (!TEST_AUTOCOMMIT) + begin_txn(0, penv); + dm3 = dm1; + if (!TEST_AUTOCOMMIT) + commit_txn(penv); + if (EXPLICIT_TXN) + begin_txn(0, penv); + check_expr(dm3 == dm1); + // this test case should be fine for hash because hash config is + // identical in dm1 and dm2 + for (dmi = dm1.begin(), dmi2 = dm2.begin(); dmi != dm1.end() && + dmi2 != dm2.end(); ++dmi, dmi2++) + check_expr(*dmi == *dmi2); + int arr1[] = {33, 44, 55, 66, 77}; + + for (dmi = dm1.begin(), i = 0; dmi != dm1.end(); dmi++, i++) + (*dmi).second = tpint(arr1[i]); + + for (dmi = dm1.begin(), dmi2 = dm2.begin(), i = 0; + dmi != dm1.end() && dmi2 != dm2.end(); dmi++, i++, dmi2++) { + check_expr((*dmi).second == tpint(arr1[i])); + dmi2->second = dmi->second; + check_expr(*dmi == *dmi2); + } + // db_map<>::insert(const value_type&). the range insert is already + // tested in fill + // + pair<dm_int_t::iterator, bool> res = + dm1.insert(make_pair(3, tpint(33))); + check_expr((*(res.first)).first == 3 && res.second == false); + // we don't know which value is assigned to key 3 on hash + if (!dm1.is_hash()) + check_expr((*(res.first)).second == 33); + + // db_map<>::count, insert, erase, find + check_expr(dm1.count(3) == 1); + check_expr(dm1.size() == (size_t)n);// n is 5 + check_expr(dm1.count(9) == 0); + res = dm1.insert(make_pair(9, tpint(99))); + check_expr((*(res.first)).second == 99 && (*(res.first)).first == 9 && + res.second == true); + check_expr(dm1.count(9) == 1); + check_expr(dm1.size() == (size_t)n + 1); + + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dm1.erase(9); + if (!TEST_AUTOCOMMIT) + commit_txn(penv); + if (EXPLICIT_TXN) + begin_txn(0, penv); + + check_expr(dm1.size() == (size_t)n); + check_expr(dm1.count(9) == 0); + dm1.erase(dm1.find(3)); + check_expr(dm1.size() == (size_t)n - 1); + check_expr(dm1.count(3) == 0); + dm2.erase(dm2.begin(), dm2.end()); + check_expr(dm2.size() == 0); + check_expr(dm2.empty()); + + dmi = dm1.begin(); + dmi++; + dmi2 = dmi; + dmi2++; + dmi2++; + + if (dm1.is_hash()) { + check_expr(dm1.key_eq()(3, 4) == false); + check_expr(dm1.key_eq()(3, 3) == true); + check_expr(dm1.bucket_count() != 0); + } else + check_expr(dm1.key_comp()(3, 4)); + + if (dm1.is_hash()) { + check_expr(dm1.key_eq()(3, 4) == false); + check_expr(dm1.key_eq()(3, 3) == true); + } else { + check_expr(dm1.key_comp()(3, 4)); + } + + check_expr(dm1.value_comp()(*dmi, *dmi2)); + if (dm1.is_hash()) + cout<<"hash value for key = 3 is: " + <<dm1.hash_funct()(3); + + dm2.insert(dmi, dmi2);// 2 recs inserted, [dmi, dmi2) + check_expr(dm2.size() == 2); + for (dmi = dm1.begin(); dmi != dm1.end(); dmi++) + cout<<'\t'<<dmi->first<<'\t'<<dmi->second<<endl; + if (EXPLICIT_TXN) + commit_txn(penv); + + if (!TEST_AUTOCOMMIT) { + begin_txn(0, penv); + } + dm1.swap(dm2); + if (!TEST_AUTOCOMMIT) { + commit_txn(penv); + } + if (EXPLICIT_TXN) + begin_txn(0, penv); + size_t dm1sz, dm2sz; + check_expr((dm1sz = dm1.size()) == 2 && + (dm2sz = dm2.size()) == (size_t)n - 1); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) { + begin_txn(0, penv); + } + dm1.clear(); + dm2.clear(); + dm3.clear(); + if (!TEST_AUTOCOMMIT) { + commit_txn(penv); + } + if (EXPLICIT_TXN) + begin_txn(0, penv); + fill(dm1, m1, i = 3, n = 5); + dm1sz = dm1.size(); + for (i = (int)dm1sz -1; i >0; i--) { + dm1[i - 1] = dm1[i]; + m1[i - 1] = m1[i]; + } + if (!dm1.is_hash()) + check_expr (is_equal(dm1, m1)); + dm1[421] = 421; + check_expr(dm1.count(421) == 1); + m1[421] = 421; + int j; + for (i = 0; i < 100; i++) { + j = rand() ; + dm1[i] = i * j; +#ifdef TEST_PRIMITIVE + m1[i] = ((ptint)dm1[i]); +#else + m1[i] = ((ptint)dm1[i]).v; +#endif + } + check_expr(dm1.size() == m1.size()); + if (!dm1.is_hash()) + check_expr (is_equal(dm1, m1)); + + for (i = 0; i < 99; i++) { + dm1[i] = dm1[i + 1]; + m1[i] = m1[i + 1]; + } + if (!dm1.is_hash()) + check_expr (is_equal(dm1, m1)); + dm1.clear(); + m1.clear(); + if (EXPLICIT_TXN) + commit_txn(penv); +} // test_map_member_functions + +void TestAssoc::test_map_std_functions() +{ + int i; + + if (EXPLICIT_TXN) + begin_txn(0, penv); + dm_int_t dm1(dmdb1, penv); + // the following test assumes dm1 and m1 contains + // (6,6), (7,7),...(14,14) + for(i = 6; i < 15; i++) { + dm1[i] = i; + m1[i] = i; + } + dm_int_t::iterator mpos, mpos2; + dm_int_t::reverse_iterator mrpos, mrpos2; +// for_each + cout<<"\n_testing std algorithms applied to db_map...\n"; + cout<<"\nfor_each begin to end\n"; + for_each(dm1.begin(), dm1.end(), square_pair<dm_int_t::value_type_wrap>); + cout<<endl; + for_each(m1.begin(), m1.end(), square_pair2<map<int, int>::value_type>); + cout<<"\nfor_each begin +1 to end\n"; + for_each(dm1.begin() ++, (dm1.begin()--)--, square_pair<dm_int_t::value_type_wrap>); + cout<<endl; + for_each(m1.begin() ++, (m1.begin() --)--, square_pair2<map<int, int>::value_type>); + + //find + ptint tgt(12); + mpos = find(dm1.begin(), dm1.end(), make_pair(tgt, tgt)); + check_expr(mpos != dm1.end() && ((mpos->second) == tgt)); + mpos = find(++(dm1.begin() ++), --(dm1.end() --), make_pair(tgt, tgt)); + check_expr(mpos != dm1.end() && ((mpos->second) == tgt)); + tgt = -123; + mpos = find(dm1.begin(), dm1.end(), make_pair(tgt, tgt)); + check_expr(mpos == dm1.end()); + pair<int, int>* subseq3 = new pair<int, int>[3]; + subseq3[0] = make_pair(8, 8); + subseq3[1] = make_pair(9, 9); + subseq3[2] = make_pair(10, 10); + pair<int, int>* subseq4 = new pair<int, int>[4]; + subseq4[0] = make_pair(9, 9); + subseq4[1] = make_pair(8, 8); + subseq4[2] = make_pair(10, 10); + subseq4[3] = make_pair(11, 11); + // find_end + if (!dm1.is_hash()) { +#ifdef WIN32 + mpos = find_end(dm1.begin(), dm1.end(), dm1.begin(), ++(dm1.begin()) ); + check_expr(mpos == dm1.begin()); + mpos = find_end(dm1.begin(), dm1.end(), mpos2 = ++(++(dm1.begin()++)), + --(--(dm1.end()--))); + check_expr(mpos == mpos2); + + mpos = find_end(++dm1.begin(), dm1.end(), subseq3, subseq3 + 3); + check_expr(mpos == ++(++(dm1.begin()))); +#endif + // find_first_of + mpos = find_first_of(dm1.begin(), dm1.end(), dm1.begin(), + ++dm1.begin()); + check_expr(mpos == dm1.begin()); + + mpos = find_first_of(++dm1.begin(), --dm1.end(), + subseq4, subseq4 + 4); + check_expr(mpos == ++(++dm1.begin())); + mpos = find_first_of(--(--dm1.end()), dm1.end(), + subseq4, subseq4 + 4); + check_expr(mpos == dm1.end()); + + // mismatch + + pair<dm_int_t::iterator , pair<int, int>*> resmm2 = mismatch(dm1.begin(), + ++(++(++dm1.begin())), subseq3); + check_expr(resmm2.first == dm1.begin() && resmm2.second == subseq3); + + //search + mpos = search(dm1.begin(), dm1.end(), dm1.begin(), ++dm1.begin()); + check_expr(mpos == dm1.begin()); + mpos = search(++dm1.begin(), dm1.end(), subseq3, subseq3 + 3); + check_expr(mpos == ++(++dm1.begin())); + //equal + mpos2 = dm1.begin(); + mpos2.move_to(8); + check_expr (equal(dm1.begin(), mpos2, subseq3) == false); + mpos = mpos2; mpos.move_to(11); + check_expr(equal(mpos2, mpos, subseq3) == true); + mpos.move_to(10); + check_expr(equal(mpos2, mpos, subseq3) == true); + } + delete [] subseq4; + delete [] subseq3; + //find_if + mpos = find_if(dm1.begin(), dm1.end(), is2digits_pair); + check_expr(ptint(mpos->second) == 10); + + // count_if + oddcnt = count_if(dm1.begin(), dm1.end(), is_odd_pair); + check_expr(oddcnt == 4); + oddcnt = count_if(dm1.begin(), dm1.begin(), is_odd_pair); + check_expr(oddcnt == 0); + + + if ( EXPLICIT_TXN) + dbstl::commit_txn(penv); + + +} // test_map_std_functions + +void TestAssoc::test_hot_dbclose() +{ + int i; + map<ptint, ptint> m2; + dm_int_t dm2(dmdb2, penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dm2.clear();// can be auto commit + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + begin_txn(0, penv); + for (i = 0; i < 5; i++) { + dm2[i] = i; + m2[i] = i; + } + + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + dm_int_t dm1(dmdb1, penv); + dbstl::close_db(dm1.get_db_handle()); + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + dm1.set_db_handle(dbp3 = dbstl::open_db(penv, "db_map.db", + dbtype, DB_CREATE | dboflags, 0)); + if (!dm1.is_hash()) + check_expr (is_equal(dm1, m1)); + dm1.clear(); + if (EXPLICIT_TXN) + commit_txn(penv); +} // test_hot_dbclose + +void TestAssoc::test_arbitrary_object_storage() +{ + int i; + + if (EXPLICIT_TXN) + begin_txn(0, penv); + // varying length objects test + cout<<"\n_testing arbitary object storage using Dbt..\n"; + + rand_str_dbt smsdbt; + DbstlDbt dbt, dbtmsg; + string msgstr; + SMSMsg *smsmsgs[10]; + + dbtmsg.set_flags(DB_DBT_USERMEM); + dbt.set_data(DbstlMalloc(256)); + dbt.set_flags(DB_DBT_USERMEM); + dbt.set_ulen(256); + db_map<int, DbstlDbt> msgmap(dbp3, penv); + for (i = 0; i < 10; i++) { + smsdbt(dbt, msgstr, 10, 200); + SMSMsg *pmsg = SMSMsg::make_sms_msg(time(NULL), + (char *)dbt.get_data(), i); + smsmsgs[i] = SMSMsg::make_sms_msg(time(NULL), + (char *)dbt.get_data(), i); + dbtmsg.set_data(pmsg); + dbtmsg.set_ulen((u_int32_t)(pmsg->mysize)); + dbtmsg.set_size((u_int32_t)(pmsg->mysize)); + dbtmsg.set_flags(DB_DBT_USERMEM); + msgmap.insert(make_pair(i, dbtmsg)); + free(pmsg); + memset(&dbtmsg, 0, sizeof(dbtmsg)); + } + dbtmsg.set_data(NULL); + // check that retrieved data is identical to stored data + SMSMsg *psmsmsg; + for (i = 0; i < 10; i++) { + db_map<int, DbstlDbt>::data_type_wrap msgref = msgmap[i]; + psmsmsg = (SMSMsg *)msgref.get_data(); + + check_expr(memcmp(smsmsgs[i], psmsmsg, + smsmsgs[i]->mysize) == 0); + } + + i = 0; + for (db_map<int, DbstlDbt>::iterator msgitr = msgmap.begin(ReadModifyWriteOption:: + read_modify_write()); msgitr != msgmap.end(); ++msgitr, i++) { + db_map<int, DbstlDbt>::reference smsmsg = *msgitr; + (((SMSMsg*)(smsmsg.second.get_data())))->when = time(NULL); + smsmsg.second._DB_STL_StoreElement(); + + } + + for (i = 0; i < 10; i++) + free(smsmsgs[i]); + + msgmap.clear(); + + + cout<<"\n_testing arbitary object(sparse, varying length) storage support using registered callbacks...\n"; + db_map<int, SMSMsg2> msgmap2(dbp3, penv); + SMSMsg2 smsmsgs2[10]; + DbstlElemTraits<SMSMsg2>::instance()->set_copy_function(SMSMsgCopy); + DbstlElemTraits<SMSMsg2>::instance()->set_size_function(SMSMsgSize); + DbstlElemTraits<SMSMsg2>::instance()->set_restore_function(SMSMsgRestore); + // use new technique to store varying length and inconsecutive objs + for (i = 0; i < 10; i++) { + smsdbt(dbt, msgstr, 10, 200); + SMSMsg2 msg2(time(NULL), msgstr.c_str(), i); + smsmsgs2[i] = msg2; + + msgmap2.insert(make_pair(i, msg2)); + + } + + // check that retrieved data is identical to stored data + SMSMsg2 tmpmsg2; + for (i = 0; i < 10; i++) { + tmpmsg2 = msgmap2[i]; + check_expr(smsmsgs2[i] == tmpmsg2); + } + for (db_map<int, SMSMsg2>::iterator msgitr = msgmap2.begin(ReadModifyWriteOption:: + read_modify_write()); msgitr != msgmap2.end(); msgitr++) { + db_map<int, SMSMsg2>::reference smsmsg = *msgitr; + smsmsg.second.when = time(NULL); + smsmsg.second._DB_STL_StoreElement(); + + } + msgmap2.clear(); + if (EXPLICIT_TXN) + commit_txn(penv); +} // test_arbitrary_object_storage + +// std::string persistent test. +void TestAssoc::test_storing_std_strings() +{ + string kstring = "hello world", *sstring = new string("hi there"); + if (EXPLICIT_TXN) + begin_txn(0, penv); + + db_map<string, string> pmap(dmstringdb, NULL); + + pmap[kstring] = *sstring + "!"; + *sstring = pmap[kstring]; + map<string, string> spmap; + spmap.insert(make_pair(kstring, *sstring)); + cout<<"sstring append ! is : "<<pmap[kstring]<<" ; *sstring is : "<<*sstring; + delete sstring; + for (db_map<string, string>::iterator ii = pmap.begin(); + ii != pmap.end(); + ++ii) { + cout << (*ii).first << ": " << (*ii).second << endl; + } + close_db(dmstringdb); + + dmstringdb = dbstl::open_db(penv, "db_map_stringdb.db", + dbtype, DB_CREATE | dboflags, 0); + db_map<string, string> pmap2(dmstringdb, NULL); + for (db_map<string, string>::iterator ii = pmap2.begin(); + ii != pmap2.end(); + ++ii) { + cout << (*ii).first << ": " << (*ii).second << endl; + // assert key/data pair set equal + check_expr((spmap.count(ii->first) == 1) && (spmap[ii->first] == ii->second)); + } + if (EXPLICIT_TXN) + commit_txn(penv); + + db_vector<string> strvctor(10); + vector<string> sstrvctor(10); + for (int i = 0; i < 10; i++) { + strvctor[i] = "abc"; + sstrvctor[i] = strvctor[i]; + } + check_expr(is_equal(strvctor, sstrvctor)); +} + +void TestAssoc::test_secondary_containers() +{ + int i; + + if (EXPLICIT_TXN) + begin_txn(0, penv); + // test secondary db + cout<<"\n_testing db container backed by secondary database..."; + + dbp3->associate(dbstl::current_txn(penv), dbp3sec, + get_dest_secdb_callback, DB_CREATE); + typedef db_multimap<int, BaseMsg> sec_mmap_t; + sec_mmap_t secmmap(dbp3sec, penv);// index "to" field + db_map<int, BaseMsg> basemsgs(dbp3, penv); + basemsgs.clear(); + BaseMsg tmpmsg; + multiset<BaseMsg> bsmsgs, bsmsgs2; + multiset<BaseMsg>::iterator bsitr1, bsitr2; + // populate primary and sec db + for (i = 0; i < 10; i++) { + tmpmsg.when = time(NULL); + tmpmsg.to = 100 - i % 3;// sec index multiple + tmpmsg.from = i + 20; + bsmsgs.insert( tmpmsg); + basemsgs.insert(make_pair(i, tmpmsg)); + + } + check_expr(basemsgs.size() == 10); + // check retrieved data is identical to those fed in + sec_mmap_t::iterator itrsec; + for (itrsec = secmmap.begin(ReadModifyWriteOption::no_read_modify_write(), true); + itrsec != secmmap.end(); itrsec++) { + bsmsgs2.insert(itrsec->second); + } + for (bsitr1 = bsmsgs.begin(), bsitr2 = bsmsgs2.begin(); + bsitr1 != bsmsgs.end() && bsitr2 != bsmsgs2.end(); bsitr1++, bsitr2++) { + check_expr(*bsitr1 == *bsitr2); + } + check_expr(bsitr1 == bsmsgs.end() && bsitr2 == bsmsgs2.end()); + + // search using sec index, check the retrieved data is expected + // and exists in bsmsgs + check_expr(secmmap.size() == 10); + pair<sec_mmap_t::iterator, sec_mmap_t::iterator> secrg = + secmmap.equal_range(98); + + for (itrsec = secrg.first; itrsec != secrg.second; itrsec++) { + check_expr(itrsec->second.to == 98 && + bsmsgs.count(itrsec->second) > 0); + } + // delete via sec db + size_t nersd = secmmap.erase(98); + check_expr(10 - nersd == basemsgs.size()); + secrg = secmmap.equal_range(98); + check_expr(secrg.first == secrg.second); + + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + +} // test_secondary_containers + +void TestAssoc::test_mmap_member_functions() +{ + // db_multimap<> + int i; + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + dmm_int_t dmm1(dmmdb1, penv); + + dmm1.clear(); + // db_multimap<>::empty + check_expr(dmm1.empty()); + { + size_t sz0, szeq1, szeq2; + + fill(dmm1, mm1, i = 3, n = 5, 4); + const dmm_int_t &cdmm1 = dmm1; + dmm_int_t dmmn(NULL, penv); + dmmn.insert(cdmm1.begin(), cdmm1.end()); + check_expr(!(dmmn != cdmm1)); + + pair<dmm_int_t::const_iterator, dmm_int_t::const_iterator> cnstrg, ceqrgend; + pair<dmm_int_t::iterator, dmm_int_t::iterator> nceqrg, eqrgend; + + for (i = 3; i < 8; i++) { + cnstrg = cdmm1.equal_range(i); + nceqrg = dmm1.equal_range(i); + dmm_int_t::const_iterator cmmitr; + dmm_int_t::iterator mmitr; + for (sz0 = 0, cmmitr = cnstrg.first, mmitr = nceqrg.first; mmitr != nceqrg.second; mmitr++, cmmitr++, sz0++) + check_expr(*cmmitr == *mmitr); + check_expr(cmmitr == cnstrg.second); + if (i < 7) + check_expr(*(cdmm1.upper_bound(i)) == *(dmm1.upper_bound(i))); + cnstrg = cdmm1.equal_range_N(i, szeq1); + nceqrg = dmm1.equal_range_N(i, szeq2); + check_expr(szeq1 == szeq2 && szeq2 == sz0); + } + eqrgend = dmm1.equal_range(65535); + check_expr(eqrgend.first == dmm1.end() && eqrgend.second == dmm1.end()); + eqrgend = dmm1.equal_range_N(65535, szeq1); + check_expr(eqrgend.first == dmm1.end() && eqrgend.second == dmm1.end() && szeq1 == 0); + ceqrgend = cdmm1.equal_range(65535); + check_expr(ceqrgend.first == cdmm1.end() && ceqrgend.second == cdmm1.end()); + ceqrgend = cdmm1.equal_range_N(65535, szeq1); + check_expr(ceqrgend.first == cdmm1.end() && ceqrgend.second == cdmm1.end() && szeq1 == 0); + if (!dmm1.is_hash()) { + eqrgend = dmm1.equal_range(2); + check_expr((((eqrgend.first))->first == 3) && ((eqrgend.second))->first == 3); + ceqrgend = cdmm1.equal_range(2); + check_expr(((ceqrgend.first))->first == 3 && ((ceqrgend.second))->first == 3); + eqrgend = dmm1.equal_range_N(2, szeq1); + check_expr((eqrgend.first)->first == 3 && ((eqrgend.second))->first == 3 && szeq1 == 0); + ceqrgend = cdmm1.equal_range_N(2, szeq1); + check_expr((ceqrgend.first)->first == 3 && ((ceqrgend.second))->first == 3 && szeq1 == 0); + + check_expr(((dmm1.upper_bound(2)))->first == 3); + check_expr(((cdmm1.upper_bound(2)))->first == 3); + check_expr(dmm1.upper_bound(65535) == dmm1.end()); + check_expr(cdmm1.upper_bound(65535) == cdmm1.end()); + check_expr(dmm1.lower_bound(65535) == dmm1.end()); + check_expr(cdmm1.lower_bound(65535) == cdmm1.end()); + check_expr(dmm1.count(65535) == 0); + check_expr(dmm1.find(65535) == dmm1.end()); + check_expr(cdmm1.find(65535) == cdmm1.end()); + + dmm_int_t tmpdmm0(dmm1); + dmm1.erase(dmm1.end()); + check_expr(dmm1 == tmpdmm0); + nceqrg = tmpdmm0.equal_range(5); + + for (dmm_int_t::iterator itr0 = nceqrg.first; itr0 != nceqrg.second; ++itr0) + itr0->second *= 2; + check_expr(tmpdmm0 != dmm1); + tmpdmm0.insert(dmm1.begin(), ++(++dmm1.begin())); + check_expr(tmpdmm0 != dmm1); + } + dmm1.clear(); + mm1.clear(); + } + fill(dmm1, mm1, i = 3, n = 5, 4); + check_expr(!dmm1.empty()); + + typedef multimap<int, int> mm_int_t; + dmm_int_t::iterator dmmi, dmmi2; + mm_int_t::iterator mmi; + dmm_int_t::reverse_iterator dmmri; + mm_int_t::reverse_iterator mmri; + + print_mm(dmm1, dmmi); + // db_multimap<>::find, count + for (dmmi = dmm1.begin(), mmi = mm1.begin(), i = 3; + dmmi != dmm1.end() && + mmi !=mm1.end(); dmmi++, mmi++, i++) { + // check_expr both contain + check_expr((*(dmm1.find(i))).second == i); + + pair<dmm_int_t::iterator, dmm_int_t::iterator> erp1 = + dmm1.equal_range(i); + int jc = 0; + dmm_int_t::iterator jj; + for (jj = erp1.first, jc = 0; + jj != erp1.second; jj++, jc++) + check_expr((*jj).second == ptint(i)); + + check_expr((size_t)jc == g_count[i]); // g_count[i] duplicates + if (i < 7 && !dmm1.is_hash()) {// 7 is last element + check_expr((*(dmm1.upper_bound(i))).second == i + 1); + check_expr((*(dmm1.lower_bound(i))).second == i); + } + else if (i == 7 && !dmm1.is_hash()) { + check_expr(dmm1.upper_bound(i) == dmm1.end()); + check_expr((*(dmm1.lower_bound(i))).second == i); + } else if (!dmm1.is_hash()) + check_expr(false); + + check_expr(dmm1.count(i) == g_count[i]); + check_expr(dmm1.count(-i) == 0); + if (!dmm1.is_hash()) + check_expr((*dmmi).second == (*mmi).second); + if (i == 3 + n - 1) {// last element + + for (; dmmi != dmm1.end(); mmi--, i--) { + // check_expr both contains + check_expr((*(dmm1.find(i))).second == i); + if (!dmm1.is_hash()) + check_expr((*dmmi).second == (*mmi).second); + if (i % 2) + dmmi--; + else + --dmmi; + } + break; + } + + } + for (dmmri = dmm1.rbegin(), mmri = mm1.rbegin(), i = 3; + dmmri != dmm1.rend() && mmri !=mm1.rend(); dmmri++, mmri++, i++) { + check_expr((dmm1.find(i) != dmm1.end()) && + (mm1.find(i) != mm1.end()));// check_expr both contain + if (dmm1.is_hash() == false) + check_expr((*dmmri).second == (*mmri).second); + if (i == 3 + n - 1) {// last element + + for (; dmmri != dmm1.rend() && mmri != mm1.rend(); i--) { + // check_expr both contain + check_expr((*(dmm1.find(i))).second == i); + if (!dmm1.is_hash()) + check_expr((*dmmri).second == (*mmri).second); + if (i % 2) + dmmri--; + else + --dmmri; + if (i > 3) // MS STL bug: when msri points to last element, it can not go back + mmri--; + + } + break; + } + + } + for (dmmi = dmm1.begin(), mmi = mm1.begin(), i = 3; + dmmi != dmm1.end() && + mmi !=mm1.end(); ++dmmi, mmi++) + i++; + check_expr((size_t)i == 3 + g_sum(3, 8)); + for (dmmri = dmm1.rbegin(), mmri = mm1.rbegin(), i = 3; + dmmri != dmm1.rend() && mmri !=mm1.rend(); ++dmmri, mmri++) + i++; + check_expr((size_t)i == 3 + g_sum(3, 8)); + + dmm_int_t dmm2(dmmdb2, penv); + dmm2.clear(); + dmmi = dmm1.begin(); + dmmi2 = dmm1.end(); + dmm2.insert(dmmi, dmmi2); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dmm_int_t dmm3 = dmm2; + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + check_expr(dmm3 == dmm2); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dmm3 = dmm1; + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + check_expr(dmm3 == dmm1); + + for (dmmi = dmm1.begin(), dmmi2 = dmm2.begin(); dmmi != dmm1.end() && + dmmi2 != dmm2.end(); ++dmmi, dmmi2++) + check_expr(*dmmi == *dmmi2); + + // content of dmm1 and dmm2 are changed since now + int arr1[] = {33, 44, 55, 66, 77}; + int arr11[] = {33, 44, 55, 66, 77}; + for (dmmi = dmm1.begin(), i = 0; dmmi != dmm1.end(); dmmi++, i++) + (*dmmi).second = tpint(arr11[i % 5]); + + for (dmmi = dmm1.begin(), dmmi2 = dmm2.begin(), i = 0; + dmmi != dmm1.end() && dmmi2 != dmm2.end(); + dmmi++, i++, dmmi2++) { + check_expr((*dmmi).second == tpint(arr1[i % 5])); + dmmi2->second = dmmi->second; + check_expr(*dmmi == *dmmi2); + } + + // db_multimap<>::insert(const value_type&). the range insert is already + // tested in fill + // + dmm_int_t::iterator iitr = dmm1.insert(make_pair(3, tpint(33))); + check_expr(iitr->first == 3); + // the returned iitr points to any rec with key==3, not necessarily + // the newly inserted rec, so not sure of the value on hash + if (dmm1.is_hash() == false) + check_expr(iitr->second == 33); + + dmm1.clear(); + mm1.clear(); + fill(dmm1, mm1, i = 3, n = 5, 4); + // db_multimap<>::count, insert, erase, find + size_t sizet1; + check_expr(dmm1.count(3) == g_count[3]); + check_expr(dmm1.size() == (sizet1 = g_sum(3, 8)));// sum of recs from 3 to 8 + check_expr(dmm1.count(9) == 0); + dmm_int_t::iterator iitr2 = dmm1.insert(make_pair(9, tpint(99))); + check_expr(iitr2->first == 9 && iitr2->second == 99); + check_expr(dmm1.count(9) == 1); + check_expr(dmm1.size() == sizet1 + 1); + dmm1.erase(9); + check_expr(dmm1.size() == (sizet1 = g_sum(3, 8))); + check_expr(dmm1.count(9) == 0); + dmm1.erase(dmm1.find(3)); + check_expr(dmm1.size() == g_sum(3, 8) - 1); + check_expr(dmm1.count(3) == (g_count[3] - 1 > 0 ? g_count[3] - 1 : 0)); + dmm2.erase(dmm2.begin(), dmm2.end()); + check_expr(dmm2.size() == 0); + check_expr(dmm2.empty()); + + dmmi = dmm1.begin(); + dmmi++; + dmmi2 = dmmi; + dmmi2++; + dmmi2++; + size_t sizet2; + dmm2.insert(dmmi, dmmi2);// 2 recs inserted, [dmi, dmi2) + check_expr((sizet2 = dmm2.size()) == 2); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + + dmm1.swap(dmm2); + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + size_t dmm1sz, dmm2sz; + check_expr((dmm1sz = dmm1.size()) == 2 && (dmm2sz = + dmm2.size()) == sizet1 - 1); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dmm1.clear(); + dmm2.clear(); + dmm3.clear(); + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + dmm_int_t dmm4(dmmdb4, penv); + dmm4.clear(); + multimap<ptint, ptint> mm4; + int jj; + for (i = 0; i < 10; i++) { + sizet2 = abs(rand() % 20) + 1; + for (jj = 0; jj < (int)sizet2; jj++) { + dmm4.insert(make_pair(i, jj)); + mm4.insert(make_pair(i, jj)); + } + } + pair<dmm_int_t::iterator, dmm_int_t::iterator> eqrgdmm; + pair<multimap<ptint, ptint>::iterator, multimap<ptint, ptint>::iterator> + eqrgmm; + dmm_int_t::iterator dmmitr; + multimap<ptint, ptint>::iterator mmitr; + for (i = 0; i < 10; i++) { + eqrgdmm = dmm4.equal_range(i); + eqrgmm = mm4.equal_range(i); + for (dmmitr = eqrgdmm.first, mmitr = eqrgmm.first; dmmitr != + eqrgdmm.second && mmitr != eqrgmm.second; dmmitr++, mmitr++) + check_expr(*dmmitr == *mmitr); + check_expr((dmmitr == eqrgdmm.second) && (mmitr == eqrgmm.second)); + } + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + +} // test_mmap_member_functions + +void TestAssoc::test_set_member_functions() +{ +// db_set<> + int i; + int arr1[] = {33, 44, 55, 66, 77}; + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + dms_int_t dms1(dmsdb1, penv); + const dms_int_t& cnstdms1 = dms1; + set<ptint> ms1; + + n = 10; + for (i = 0; i < n; i++) + dms1.insert(i); + + for (i = 0; i < n; i++) { + dms_int_t::const_iterator citr, citr1; + citr = dms1.find(i); + check_expr(*citr == *dms1.find(i)); + dms_int_t::iterator itr = citr; + check_expr(*citr == *itr); + *itr = i; + itr = dms1.find(i); + citr = itr; + citr1 = itr; + check_expr(*citr == *itr); + check_expr(*citr == *citr1); + check_expr(*citr == *dms1.find(i)); + } + + for (i = 0; i < n; i++) { + dms_int_t::const_iterator citr = dms1.find(i); + check_expr(*citr == *dms1.find(i)); + dms_int_t::iterator itr = citr; + check_expr(*citr == *itr); + *itr = i; + itr = dms1.find(i); + citr = itr; + dms_int_t::const_iterator citr1 = itr; + check_expr(*citr == *itr); + check_expr(*citr == *citr1); + check_expr(*citr == *dms1.find(i)); + } + + for (i = 0; i < n; i++) { + dms_int_t::iterator ncitr, ncitr1; + dms_int_t::const_iterator citr, citr1; + + ncitr = cnstdms1.find(i); + check_expr(*ncitr == *cnstdms1.find(i)); + citr = ncitr; + check_expr(*citr == *ncitr); + //*ncitr = i * 2 + 1; + citr1 = ncitr; + ncitr1 = citr1; + check_expr(*citr == *ncitr); + check_expr(*citr == *ncitr1); + check_expr(*citr == *citr1); + check_expr(*citr == *cnstdms1.find(i)); + } + + for (i = 0; i < n; i++) { + + dms_int_t::iterator ncitr = cnstdms1.find(i); + check_expr(*ncitr == *cnstdms1.find(i)); + dms_int_t::const_iterator citr = ncitr; + check_expr(*citr == *ncitr); + //*itr = i * 2 + 1; + dms_int_t::const_iterator citr1 = ncitr; + dms_int_t::iterator ncitr1 = citr1; + + check_expr(*citr == *ncitr); + check_expr(*citr == *ncitr1); + check_expr(*citr == *citr1); + check_expr(*citr == *cnstdms1.find(i)); + } + + if (dms1.is_hash() == false) + { + ms1.clear(); + dms1.clear(); + for (i = 0; i < n; i++) { + dms1.insert(ptint(i)); + ms1.insert(ptint(i)); + } + + const dms_int_t &cnstdms1 = dms1; + dms_int_t tmpdms0; + + tmpdms0.insert(cnstdms1.begin(), cnstdms1.end()); + dms_int_t::const_iterator citr = dms1.end(), citr2 = --dms1.begin(), itr2; + set<ptint>::const_iterator scitr = ms1.end(), scitr2 = --ms1.begin(); + for (citr--, scitr--; citr != citr2; --citr, --scitr) { + check_expr(*citr == *scitr); + } + check_expr(scitr == scitr2); + + db_set<ptype<int> > dmspt; + dmspt.insert(cnstdms1.begin(), cnstdms1.end()); + + db_set<ptype<int> >::const_iterator itrpt; + db_set<ptype<int> >::iterator itrpt2; + + for (itrpt = dmspt.begin(), citr = dms1.begin(); itrpt != dmspt.end(); ++itrpt, ++citr) { + itrpt.refresh(true); + check_expr(itrpt->v == *citr); + } + + for (itrpt2 = dmspt.begin(), itr2 = dms1.begin(); itrpt2 != dmspt.end(); ++itrpt2, ++itr2) { + itrpt2.refresh(true); + check_expr(itrpt2->v == *itr2); + } + + dms_int_t dmstmp(dms1); + check_expr(dms1 == dmstmp); + dms1.insert(dms1.begin(), 101); + check_expr(dms1 != dmstmp); + + ms1.clear(); + dms1.clear(); + } + dms1.clear(); + // db_map<>::empty + check_expr(dms1.empty()); + fill(dms1, ms1, i = 3, n = 5); + check_expr(!dms1.empty()); + + typedef set<int> ms_int_t; + dms_int_t::iterator dmsi, dmsi2; + ms_int_t::iterator msi; + dms_int_t::reverse_iterator dmsri; + ms_int_t::reverse_iterator msri; + + // db_set<>::find, count + for (dmsi = dms1.begin(), msi = ms1.begin(), i = 3; dmsi != dms1.end() && + msi !=ms1.end(); dmsi++, msi++, i++) { + // check_expr both contain + check_expr(*(dms1.find(i)) == i); + + pair<dms_int_t::iterator, dms_int_t::iterator> erp = + dms1.equal_range(i); + int jc = 0; + dms_int_t::iterator jj; + for (jj = erp.first, jc = 0; + jj != erp.second; jj++, jc++) + check_expr((*jj) == ptint(i)); + check_expr(jc == 1); + if (i < 7 && !dms1.is_hash()) {// 7 is last element + check_expr((*(dms1.upper_bound(i))) == i + 1); + check_expr((*(dms1.lower_bound(i))) == i); + } + else if (i == 7 && !dms1.is_hash()) { + check_expr(dms1.upper_bound(i) == dms1.end()); + check_expr((*(dms1.lower_bound(i))) == i); + } else if (!dms1.is_hash()) + check_expr(false); + + check_expr(dms1.count(i) == 1); + check_expr(dms1.count(-i) == 0); + if (!dms1.is_hash()) { + check_expr((*dmsi) == (*msi)); + check_expr((*dmsi) == (*msi)); + } + if (i == 3 + n - 1) {// last element + if (!dms1.is_hash()) + check_expr((*dmsi) == (*msi)); + for (; dmsi != dms1.end() && (*dmsi) == (*msi); i--) { + // check_expr both contains + if (!dms1.is_hash()) + check_expr((*dmsi) == (*msi)); + check_expr((*(dms1.find(i)) == i)); + + if (i % 2) + dmsi--; + else + --dmsi; + msi--; + } + break; + } + + } + for (dmsri = dms1.rbegin(), msri = ms1.rbegin(), i = 3; + dmsri != dms1.rend() && msri != ms1.rend(); dmsri++, msri++, i++) { + check_expr((*(dms1.find(i)) == i)); + if (!dms1.is_hash()) + check_expr((*dmsri) == (*msri)); + if (i == 3 + n - 1) {// last element + + for (; dmsri != dms1.rend() && msri != ms1.rend(); i--) { + // check_expr both contain + check_expr((dms1.find(i) != dms1.end()) && + (ms1.find(i) != ms1.end())); + if (!dms1.is_hash()) + check_expr((*dmsri) == (*msri)); + + if (i % 2) + dmsri--; + else + --dmsri; + if (i > 3) // MS STL bug: when msri points to last element, it can not go back + msri--; + + } + break; + } + + } + for (dmsi = dms1.begin(), msi = ms1.begin(), i = 3; dmsi != dms1.end() && + msi !=ms1.end(); ++dmsi, msi++) + i++; + check_expr(i == 3 + n); + + for (dmsri = dms1.rbegin(), msri = ms1.rbegin(), i = 3; + dmsri != dms1.rend() && msri !=ms1.rend(); ++dmsri, msri++) + i++; + check_expr(i == 3 + n); + + dms_int_t dms2(dmsdb2, penv); + dms2.clear(); + dms2.insert(dms1.begin(), dms1.end()); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dms_int_t dms3 = dms2; + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + check_expr(dms3 == dms2); + dms3 = dms1; + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + check_expr(dms3 == dms1); + + for (dmsi = dms1.begin(), dmsi2 = dms2.begin(); dmsi != dms1.end() && + dmsi2 != dms2.end(); ++dmsi, dmsi2++) + check_expr(*dmsi == *dmsi2); + + /* !!!XXX + set keys are not supposed to be mutated, so this is an extra functionality, just like + the set iterator assignment in ms's stl library. Here we must use i < dms1.size() to + limit the number of loops because after each assignment, dmsi will be positioned to + the element which is immediately next to the old key it sits on before the assignment, + thus it may take more loops to go to the end() position. + */ + pprint(dms1, "dms1 before iterator assignment : \n"); + dms_int_t::size_type ui; + for (dmsi = dms1.begin(), ui = 0; dmsi != dms1.end() && ui < dms1.size(); dmsi++, ui++) { + (*dmsi) = tpint(arr1[ui]); + pprint(dms1, "\ndms1 after one element assignment : "); + } + if (dms1.is_hash() == false) { + pprint(dms1, "dms1 after iterator assignment : \n"); + for (dmsi = dms1.begin(), dmsi2 = dms2.begin(), i = 0; + dmsi != dms1.end() && dmsi2 != dms2.end(); dmsi++, i++, dmsi2++) { + check_expr((*dmsi) == tpint(arr1[i])); + *dmsi2 = *dmsi; + // check_expr(*dmsi == *dmsi2); dmsi2 is invalidated by the assignment, so can't compare here. + } + // Compare here. + for (dmsi = dms1.begin(), dmsi2 = dms2.begin(), i = 0; + dmsi != dms1.end() && dmsi2 != dms2.end(); dmsi++, i++, dmsi2++) + check_expr(*dmsi2 == *dmsi); + } + + dms1.clear(); + //dms2.clear(); + fill(dms1, ms1, i = 3, n = 5); + // db_set<>::insert(const value_type&). the range insert is already + // tested in fill + // + pair<dms_int_t::iterator, bool> ress = + dms1.insert(tpint(3)); + check_expr((*(ress.first)) == 3 && ress.second == false); + + // db_set<>::count, insert, erase, find + check_expr(dms1.count(3) == 1); + check_expr(dms1.size() == (size_t)n);// n is 5 + check_expr(dms1.count(9) == 0); + ress = dms1.insert(tpint(9)); + check_expr((*(ress.first)) == 9 && ress.second == true); + check_expr(dms1.count(9) == 1); + check_expr(dms1.size() == (size_t)n + 1); + dms1.erase(9); + check_expr(dms1.size() == (size_t)n); + check_expr(dms1.count(9) == 0); + dms1.erase(dms1.find(3)); + check_expr(dms1.size() == (size_t)n - 1); + check_expr(dms1.count(3) == 0); + dms2.erase(dms2.begin(), dms2.end()); + check_expr(dms2.size() == 0); + check_expr(dms2.empty()); + + dmsi = dms1.begin(); + dmsi++; + dmsi2 = dmsi; + dmsi2++; + dmsi2++; + dms2.insert(dmsi, dmsi2);// 2 recs inserted, [dmsi, dmsi2) + check_expr(dms2.size() == 2); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dms1.swap(dms2); + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + size_t dms1sz, dms2sz; + check_expr((dms1sz = dms1.size()) == 2 && (dms2sz = dms2.size()) == (size_t)n - 1); + dms1.clear(); + dms2.clear(); + dms3.clear(); + + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + +} // test_set_member_functions + +void TestAssoc::test_mset_member_functions() +{ +// db_multiset<> + int i; + size_t sizet1; + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + dmms_int_t dmms1(dmmsdb1, penv); + multiset<int> mms1; + + dmms1.clear(); + // db_multiset<>::empty + check_expr(dmms1.empty()); + fill(dmms1, mms1, i = 3, n = 5, 4); + check_expr(!dmms1.empty()); + dmms_int_t tmpmms0; + const dmms_int_t &cnstmms = dmms1; + dmms_int_t tmpmms1; + tmpmms1.insert(dmms1.begin(), dmms1.end()); + tmpmms0.insert(cnstmms.begin(), cnstmms.end()); + tmpmms0.insert(tmpmms0.begin(), *(--tmpmms0.end())); + check_expr(tmpmms0 != tmpmms1); + + typedef multiset<int> mms_int_t; + dmms_int_t::iterator dmmsi, dmmsi2; + mms_int_t::iterator mmsi; + dmms_int_t::reverse_iterator dmmsri; + mms_int_t::reverse_iterator mmsri; + + // db_multiset<>::find, count + for (dmmsi = dmms1.begin(), mmsi = mms1.begin(), i = 3; + dmmsi != dmms1.end() && + mmsi !=mms1.end(); dmmsi++, mmsi++, i++) { + // check_expr both contain + check_expr((*(dmms1.find(i))) == i); + + pair<dmms_int_t::iterator, dmms_int_t::iterator> erp1 = + dmms1.equal_range(i); + int jc = 0; + dmms_int_t::iterator jj; + for (jj = erp1.first, jc = 0; + jj != erp1.second; jj++, jc++) { + // there is bug so this line can be reached + if ((size_t)jc == g_count[i]) { + jj == erp1.second;// cmp again to debug it + dmms1.get_db_handle()->stat_print(DB_STAT_ALL); + } + check_expr((*jj) == ptint(i)); + } + check_expr((size_t)jc == g_count[i]); // g_count[i] duplicates + if (i < 7 && !dmms1.is_hash()) {// 7 is last element + check_expr((*(dmms1.upper_bound(i))) == i + 1); + check_expr((*(dmms1.lower_bound(i))) == i); + } + else if (i == 7 && !dmms1.is_hash()) { + check_expr(dmms1.upper_bound(i) == dmms1.end()); + check_expr((*(dmms1.lower_bound(i))) == i); + } else if (!dmms1.is_hash()) + check_expr(false); + + check_expr(dmms1.count(i) == g_count[i]); + check_expr(dmms1.count(-i) == 0); + if (!dmms1.is_hash()) + check_expr((*dmmsi) == (*mmsi)); + if (i == 3 + n - 1) {// last element + + for (; dmmsi != dmms1.end(); mmsi--, i--) { + // check_expr both contains + check_expr((*(dmms1.find(i))) == i); + if (!dmms1.is_hash()) + check_expr((*dmmsi) == (*mmsi)); + if (i % 2) + dmmsi--; + else + --dmmsi; + } + break; + } + + } + for (dmmsri = dmms1.rbegin(), mmsri = mms1.rbegin(), i = 3; + dmmsri != dmms1.rend() && mmsri !=mms1.rend(); dmmsri++, mmsri++, i++) { + check_expr((dmms1.find(i) != dmms1.end()) && + (mms1.find(i) != mms1.end()));// check_expr both contain + if (dmms1.is_hash() == false) + check_expr((*dmmsri) == (*mmsri)); + if (i == 3 + n - 1) {// last element + + for (; dmmsri != dmms1.rend() && mmsri != mms1.rend(); i--) { + // check_expr both contain + check_expr((*(dmms1.find(i))) == i); + if (!dmms1.is_hash()) + check_expr((*dmmsri) == (*mmsri)); + if (i % 2) + dmmsri--; + else + --dmmsri; + if (i > 3) // MS STL bug: when msri points to last element, it can not go back + mmsri--; + } + break; + } + + } + for (dmmsi = dmms1.begin(), mmsi = mms1.begin(), i = 3; + dmmsi != dmms1.end() && + mmsi !=mms1.end(); ++dmmsi, mmsi++) + i++; + check_expr((size_t)i == 3 + g_sum(3, 8)); + for (dmmsri = dmms1.rbegin(), mmsri = mms1.rbegin(), i = 3; + dmmsri != dmms1.rend() && mmsri !=mms1.rend(); ++dmmsri, mmsri++) + i++; + check_expr((size_t)i == 3 + g_sum(3, 8)); + + + + + dmms_int_t dmms2(dmmsdb2, penv); + dmms2.clear(); + dmms2.insert(dmms1.begin(), dmms1.end()); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dmms_int_t dmms3 = dmms2; + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + cout<<"\ndmms2: \n"; + for (dmms_int_t::iterator itr = dmms2.begin(); itr != dmms2.end(); ++itr) + cout<<"\t"<<*itr; + cout<<"\ndmms3: \n"; + for (dmms_int_t::iterator itr = dmms3.begin(); itr != dmms3.end(); ++itr) + cout<<"\t"<<*itr; + + check_expr(dmms3 == dmms2); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dmms3 = dmms1; + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + check_expr(dmms3 == dmms1); + + for (dmmsi = dmms1.begin(), dmmsi2 = dmms2.begin(); dmmsi != dmms1.end() && + dmmsi2 != dmms2.end(); ++dmmsi, dmmsi2++) + check_expr(*dmmsi == *dmmsi2); + + // content of dmms1 and dmms2 are changed since now + // int arr11[] = {33, 44, 55, 66, 77}; + + // db_multiset<>::insert(const value_type&). the range insert is already + // tested in fill + // + dmms_int_t::iterator iitrms = dmms1.insert(ptint (3)); + check_expr(*iitrms == 3); + + dmms1.clear(); + mms1.clear(); + fill(dmms1, mms1, i = 3, n = 5, 4); + // db_multiset<>::count, insert, erase, find + check_expr(dmms1.count(3) == g_count[3]); + check_expr(dmms1.size() == (sizet1 = g_sum(3, 8)));// sum of recs from 3 to 8 + check_expr(dmms1.count(9) == 0); + dmms_int_t::iterator iitrms2 = dmms1.insert(ptint (9)); + check_expr(*iitrms2 == 9); + check_expr(dmms1.count(9) == 1); + check_expr(dmms1.size() == sizet1 + 1); + dmms1.erase(9); + check_expr(dmms1.size() == g_sum(3, 8)); + check_expr(dmms1.count(9) == 0); + dmms1.erase(dmms1.find(3)); + check_expr(dmms1.size() == g_sum(3, 8) - 1); + check_expr(dmms1.count(3) == (g_count[3] - 1 > 0 ? g_count[3] - 1 : 0)); + dmms2.erase(dmms2.begin(), dmms2.end()); + check_expr(dmms2.size() == 0); + check_expr(dmms2.empty()); + + dmmsi = dmms1.begin(); + dmmsi++; + dmmsi2 = dmmsi; + dmmsi2++; + dmmsi2++; + dmms2.insert(dmmsi, dmmsi2);// 2 recs inserted, [dmi, dmi2) + size_t sssz; + check_expr((sssz = dmms2.size()) == 2); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dmms1.swap(dmms2); + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + size_t dmms1sz, dmms2sz; + check_expr((dmms1sz = dmms1.size()) == 2 && (dmms2sz = dmms2.size()) == sizet1 - 1); + + dmms1.clear(); + dmms2.clear(); + dmms3.clear(); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + +} // test_mset_member_functions + +void TestAssoc::test_char_star_string_storage() +{ + int i; + // testing varying length data element storage/retrieval + cout<<"\n_testing char*/wchar_t* string storage support...\n"; + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + // Use Dbt to wrap any object and store them. This is rarely needed, + // so this piece of code is only for test purpose. + db_vector<DbstlDbt> strv(dbstrv, penv); + vector<string> strsv; + vector<DbstlDbt> strvdbts; + strv.clear(); + + int strlenmax = 256, strlenmin = 64; + string str; + DbstlDbt dbt; + rand_str_dbt rand_str_maker; + dbt.set_flags(DB_DBT_USERMEM); + dbt.set_data(DbstlMalloc(strlenmax + 10)); + dbt.set_ulen(strlenmax + 10); + + for (int jj = 0; jj < 10; jj++) { + rand_str_maker(dbt, str, strlenmin, strlenmax); + strsv.push_back(str); + strv.push_back(dbt); + } + + cout<<"\nstrings:\n"; + for (i = 0; i < 10; i++) { + + db_vector<DbstlDbt>::value_type_wrap elemref = strv[i]; + strvdbts.push_back(elemref); + printf("\n%s\n%s", (char*)(strvdbts[i].get_data()), strsv[i].c_str()); + check_expr(strcmp((char*)(elemref.get_data()), strsv[i].c_str()) == 0); + check_expr(strcmp((char*)(strvdbts[i].get_data()), strsv[i].c_str()) == 0); + } + strv.clear(); + + if (EXPLICIT_TXN) { + dbstl::commit_txn(penv); + dbstl::begin_txn(0, penv); + } + + // Use ordinary way to store strings. + TCHAR cstr1[32], cstr2[32], cstr3[32]; + strcpy(cstr1, "abc"); + strcpy(cstr2, "defcd"); + strcpy(cstr3, "edggsefcd"); +// = _T("abc"), *cstr2 = _T("defcd"), *cstr3 = _T("edggsefcd"); + typedef db_map<int, TCHAR*, ElementHolder<TCHAR*> > strmap_t; + strmap_t strmap(dmdb6, penv); + strmap.clear(); + strmap.insert(make_pair(1, cstr1)); + strmap.insert(make_pair(2, cstr2)); + strmap.insert(make_pair(3, cstr3)); + cout<<"\n strings in strmap:\n"; + for (strmap_t::const_iterator citr = strmap.begin(); citr != strmap.end(); citr++) + cout<<(*citr).second<<'\t'; + cout<<strmap[1]<<strmap[2]<<strmap[3]; + TCHAR cstr4[32], cstr5[32], cstr6[32]; + _tcscpy(cstr4, strmap[1]); + _tcscpy(cstr5, strmap[2]); + _tcscpy(cstr6, strmap[3]); + _tprintf(_T("%s, %s, %s"), cstr4, cstr5, cstr6); + strmap_t::value_type_wrap::second_type vts = strmap[1]; + using_charstr(vts); + vts._DB_STL_StoreElement(); + _tcscpy(cstr4, _T("hello world")); + vts = cstr4; + vts._DB_STL_StoreElement(); + cout<<"\n\nstrmap[1]: "<<strmap[1]; + check_expr(_tcscmp(strmap[1], cstr4) == 0); + vts[0] = _T('H');// itis wrong to do it this way + vts._DB_STL_StoreElement(); + check_expr(_tcscmp(strmap[1], _T("Hello world")) == 0); + TCHAR *strbase = vts._DB_STL_value(); + strbase[6] = _T('W'); + vts._DB_STL_StoreElement(); + check_expr(_tcscmp(strmap[1], _T("Hello World")) == 0); + strmap.clear(); + + typedef db_map<const char *, const char *, ElementHolder<const char *> > cstrpairs_t; + cstrpairs_t strpairs(dmdb6, penv); + strpairs["abc"] = "def"; + strpairs["ghi"] = "jkl"; + strpairs["mno"] = "pqrs"; + strpairs["tuv"] = "wxyz"; + cstrpairs_t::const_iterator ciitr; + cstrpairs_t::iterator iitr; + for (ciitr = strpairs.begin(), iitr = strpairs.begin(); iitr != strpairs.end(); ++iitr, ++ciitr) { + cout<<"\n"<<iitr->first<<"\t"<<iitr->second; + cout<<"\n"<<ciitr->first<<"\t"<<ciitr->second; + check_expr(strcmp(ciitr->first, iitr->first) == 0 && strcmp(ciitr->second, iitr->second) == 0); + } + + typedef db_map<char *, char *, ElementHolder<char *> > strpairs_t; + typedef std::map<string, string> sstrpairs_t; + sstrpairs_t sstrpairs2; + strpairs_t strpairs2; + rand_str_dbt randstr; + + for (i = 0; i < 100; i++) { + string rdstr, rdstr2; + randstr(dbt, rdstr); + randstr(dbt, rdstr2); + strpairs2[(char *)rdstr.c_str()] = (char *)rdstr2.c_str(); + sstrpairs2[rdstr] = rdstr2; + } + strpairs_t::iterator itr; + strpairs_t::const_iterator citr; + + for (itr = strpairs2.begin(); itr != strpairs2.end(); ++itr) { + check_expr(strcmp(strpairs2[itr->first], itr->second) == 0); + check_expr(string(itr->second) == sstrpairs2[string(itr->first)]); + strpairs_t::value_type_wrap::second_type&secref = itr->second; + std::reverse((char *)secref, (char *)secref + strlen(secref)); + secref._DB_STL_StoreElement(); + std::reverse(sstrpairs2[itr->first].begin(), sstrpairs2[itr->first].end()); + } + + check_expr(strpairs2.size() == sstrpairs2.size()); + for (citr = strpairs2.begin(ReadModifyWriteOption::no_read_modify_write(), + true, BulkRetrievalOption::bulk_retrieval()); citr != strpairs2.end(); ++citr) { + check_expr(strcmp(strpairs2[citr->first], citr->second) == 0); + check_expr(string(citr->second) == sstrpairs2[string(citr->first)]); + } + + + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + db_vector<const char *, ElementHolder<const char *> > csvct(10); + vector<const char *> scsvct(10); + const char *pconststr = "abc"; + for (i = 0; i < 10; i++) { + scsvct[i] = pconststr; + csvct[i] = pconststr; + csvct[i] = scsvct[i]; + // scsvct[i] = csvct[i]; assignment won't work because scsvct + // only stores pointer but do not copy the sequence, thus it + // will refer to an invalid pointer when i changes. + } + for (i = 0; i < 10; i++) { + check_expr(strcmp(csvct[i], scsvct[i]) == 0); + cout<<endl<<(const char *)(csvct[i]); + } + + db_vector<const wchar_t *, ElementHolder<const wchar_t *> > wcsvct(10); + vector<const wchar_t *> wscsvct(10); + const wchar_t *pconstwstr = L"abc"; + for (i = 0; i < 10; i++) { + wscsvct[i] = pconstwstr; + wcsvct[i] = pconstwstr; + wcsvct[i] = wscsvct[i]; + // scsvct[i] = csvct[i]; assignment won't work because scsvct + // only stores pointer but do not copy the sequence, thus it + // will refer to an invalid pointer when i changes. + } + for (i = 0; i < 10; i++) { + check_expr(wcscmp(wcsvct[i], wscsvct[i]) == 0); + + } + +} // test_char_star_string_storage + +void TestAssoc::test_fixed_len_obj_storage() +{ + int i; + map<int, sms_t> ssmsmap; + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + typedef db_map<int, sms_t> smsmap_t; + smsmap_t smsmap(dmdb6, penv); + + sms_t smsmsg; + time_t now; + for (i = 0; i < 2008; i++) { + smsmsg.from = 1000 + i; + smsmsg.to = 10000 - i; + smsmsg.sz = sizeof(smsmsg); + time(&now); + smsmsg.when = now; + ssmsmap.insert(make_pair(i, smsmsg)); + smsmap.insert(make_pair(i, smsmsg)); + } + smsmap.clear(); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); +} //test_var_len_obj_storage + +void TestAssoc::test_arbitray_sequence_storage() +{ + int i, j; + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + // storing arbitary sequence test . + cout<<endl<<"Testing arbitary type of sequence storage support...\n"; + RGBB *rgbs[10], *prgb1, *prgb2; + typedef db_map<int, RGBB *, ElementHolder<RGBB *> > rgbmap_t; + rgbmap_t rgbsmap(dmdb6, penv); + + map<int, RGBB *> srgbsmap; + + DbstlElemTraits<RGBB>::instance()->set_sequence_len_function(rgblen); + DbstlElemTraits<RGBB>::instance()->set_sequence_copy_function(rgbcpy); + // populate srgbsmap and rgbsmap + for (i = 0; i < 10; i++) { + n = abs(rand()) % 10 + 2; + rgbs[i] = new RGBB[n]; + memset(&rgbs[i][n - 1], 0, sizeof(RGBB));//make last element 0 + for (j = 0; j < n - 1; j++) { + rgbs[i][j].r_ = i + 128; + rgbs[i][j].g_ = 256 - i; + rgbs[i][j].b_ = 128 - i; + rgbs[i][j].bright_ = 256 / (i + 1); + + } + rgbsmap.insert(make_pair(i, rgbs[i])); + srgbsmap.insert(make_pair(i, rgbs[i])); + } + + // retrieve and assert equal, then modify and store + for (i = 0; i < 10; i++) { + rgbmap_t::value_type_wrap::second_type rgbelem = rgbsmap[i]; + prgb1 = rgbelem; + check_expr(memcmp(prgb1, prgb2 = srgbsmap[i], + (n = (int)rgblen(srgbsmap[i])) * sizeof(RGBB)) == 0); + for (j = 0; j < n - 1; j++) { + prgb1[j].r_ = 256 - prgb1[j].r_; + prgb1[j].g_ = 256 - prgb1[j].g_; + prgb1[j].b_ = 256 - prgb1[j].b_; + prgb2[j].r_ = 256 - prgb2[j].r_; + prgb2[j].g_ = 256 - prgb2[j].g_; + prgb2[j].b_ = 256 - prgb2[j].b_; + } + rgbelem._DB_STL_StoreElement(); + } + + // retrieve again and assert equal + for (i = 0; i < 10; i++) { + rgbmap_t::value_type_wrap::second_type rgbelem = rgbsmap[i]; + prgb1 = rgbelem;// Can't use rgbsmap[i] here because container::operator[] is an temporary value.; + check_expr(memcmp(prgb1, prgb2 = srgbsmap[i], + sizeof(RGBB) * rgblen(srgbsmap[i])) == 0); + } + + rgbmap_t::iterator rmitr; + map<int, RGBB *>::iterator srmitr; + + for (rmitr = rgbsmap.begin(); + rmitr != rgbsmap.end(); ++rmitr) { + rgbmap_t::value_type_wrap::second_type rgbelem2 = (*rmitr).second; + prgb1 = (*rmitr).second; + srmitr = srgbsmap.find(rmitr->first); + check_expr(memcmp(prgb1, prgb2 = srmitr->second, + sizeof(RGBB) * rgblen(srmitr->second)) == 0); + rmitr.refresh(); + } + + for (i = 0; i < 10; i++) + delete []rgbs[i]; + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); +} // test_arbitray_sequence_storage + +void TestAssoc::test_bulk_retrieval_read() +{ + + int i; + + typedef db_map<int, sms_t> smsmap_t; + smsmap_t smsmap(dmdb6, penv); + map<int, sms_t> ssmsmap; + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + cout<<"\n_testing bulk retrieval support:\n"; + sms_t smsmsg; + time_t now; + smsmap.clear(); + for (i = 0; i < 2008; i++) { + smsmsg.from = 1000 + i; + smsmsg.to = 10000 - i; + smsmsg.sz = sizeof(smsmsg); + time(&now); + smsmsg.when = now; + ssmsmap.insert(make_pair(i, smsmsg)); + smsmap.insert(make_pair(i, smsmsg)); + } + + // bulk retrieval test. + map<int, sms_t>::iterator ssmsitr = ssmsmap.begin(); + i = 0; + const smsmap_t &rosmsmap = smsmap; + smsmap_t::const_iterator smsitr; + for (smsitr = rosmsmap.begin( + BulkRetrievalOption::bulk_retrieval()); + smsitr != smsmap.end(); i++) { + // The order may be different, so if the two key set are + // identical, it is right. + check_expr((ssmsmap.count(smsitr->first) == 1)); + check_expr((smsitr->second == ssmsmap[smsitr->first])); + if (i % 2) + smsitr++; + else + ++smsitr; // Exercise both pre/post increment. + if (i % 100 == 0) + smsitr.set_bulk_buffer((u_int32_t)(smsitr.get_bulk_bufsize() * 1.1)); + } + + smsmap.clear(); + ssmsmap.clear(); + + // Using db_vector. when moving its iterator sequentially to end(), + // bulk retrieval works, if moving randomly, it dose not function + // for db_vector iterators. Also, note that we can create a read only + // iterator when using db_vector<>::iterator rather than + // db_vector<>::const_iterator. + db_vector<sms_t> vctsms; + db_vector<sms_t>::iterator itrv; + vector<sms_t>::iterator sitrv; + vector<sms_t> svctsms; + for (i = 0; i < 2008; i++) { + smsmsg.from = 1000 + i; + smsmsg.to = 10000 - i; + smsmsg.sz = sizeof(smsmsg); + time(&now); + smsmsg.when = now; + vctsms.push_back(smsmsg); + svctsms.push_back(smsmsg); + } + + for (itrv = vctsms.begin(ReadModifyWriteOption::no_read_modify_write(), + true, BulkRetrievalOption::bulk_retrieval(64 * 1024)), + sitrv = svctsms.begin(), i = 0; itrv != vctsms.end(); + ++itrv, ++sitrv, ++i) { + check_expr(*itrv == *sitrv); + if (i % 100 == 0) + itrv.set_bulk_buffer((u_int32_t)(itrv.get_bulk_bufsize() * 1.1)); + } + + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + + +} //test_bulk_retrieval_read + +void TestAssoc::test_nested_txns() +{ + int i; + size_t sizet1; + + if (!EXPLICIT_TXN) + return;// nested txn tests can't be run if container not txnal + + // nested transaction test + // 1. many external txns nested, no internal txn. + + typedef db_map<char*, char*, ElementHolder<char*> > strstrmap_t; + DbTxn *txn1 = NULL, *txn2, *txn3; + char kstr[10], dstr[10]; + std::map<int, string> kstrs; + int commit_or_abort = 0; + set<int> idxset; + char *keystr; + + strstrmap_t smap(dbstrmap, penv); +commit_abort: + +#define _DB_STL_TEST_SET_TXN_NAME(txn) \ + txn->set_name(commit_or_abort == 0 ? #txn"_commit" : #txn"_abort") + + txn1 = begin_txn(0, penv); + smap.clear(); + //txn1->set_name(commit_or_abort == 0 ? "txn1_commit" : "txn1_abort"); + _DB_STL_TEST_SET_TXN_NAME(txn1); + memset(kstr, 0, sizeof(kstr)); + memset(dstr, 0, sizeof(dstr)); + for (char cc = 'a'; cc <= 'z'; cc++) { + _snprintf(kstr, 10, "%c%c%c", cc, cc, cc); + for (int kk = 0; kk < 9; kk++) + dstr[kk] = cc; + + i = cc - 'a'; + kstrs.insert(make_pair(i, string(kstr))); + switch (i) { + case 3: + txn2 = begin_txn(0, penv);// nest txn2 into txn1 + _DB_STL_TEST_SET_TXN_NAME(txn2); + break; + case 6:// + abort_txn(penv); // abort txn2 + + for (int kk = 3; kk < 6; kk++) { + keystr = const_cast<char*>(kstrs[kk].c_str()); + check_expr(smap.count(keystr) == 0); + } + + txn2 = begin_txn(0, penv);// nest txn2 into txn1 + _DB_STL_TEST_SET_TXN_NAME(txn2); + break; + case 9:// 6--11: txn3 abort and txn2 commit + txn3 = begin_txn(0, penv);// nest txn3 into txn2, txn2 is in txn1 + _DB_STL_TEST_SET_TXN_NAME(txn3); + break; + case 12: + abort_txn(penv);// abort txn3 + commit_txn(penv);// commit txn2, its txn3 part is not applied + for (int kk = 6; kk < 12; kk++) { + keystr = const_cast<char*>(kstrs[kk].c_str()); + if (kk < 9) + check_expr((sizet1 = smap.count(keystr)) > 0); + if (kk >= 9) + check_expr(smap.count(keystr) == 0); + } + + break; + case 15:// 15--18: txn3 commit and txn2 abort + txn2 = begin_txn(0, penv); + _DB_STL_TEST_SET_TXN_NAME(txn2); + break; + case 17: + txn3 = begin_txn(0, penv); + _DB_STL_TEST_SET_TXN_NAME(txn3); + break; + case 19: + commit_txn(penv);// commit txn3 + abort_txn(penv);// abort txn2; + for (int kk = 15; kk < 19; kk++) { + keystr = const_cast<char*>(kstrs[kk].c_str()); + check_expr(smap.count(keystr) == 0); + } + txn2 = begin_txn(0, penv); + _DB_STL_TEST_SET_TXN_NAME(txn2); + break; + case 20: + txn3 = begin_txn(0, penv); + _DB_STL_TEST_SET_TXN_NAME(txn3); + break; + case 22: + // txn3 is unresolved, after commit txn2, txn3 should have been commited + commit_txn(penv, txn2); + for (int kk = 19; kk < 22; kk++) { + keystr = const_cast<char*>(kstrs[kk].c_str()); + check_expr(smap.count(keystr) > 0); + } + txn2 = begin_txn(0, penv); + _DB_STL_TEST_SET_TXN_NAME(txn2); + break; + case 23: + txn3 = begin_txn(0, penv); + _DB_STL_TEST_SET_TXN_NAME(txn3); + break; + case 25: + // txn3 is unresolved, after abort txn2, txn3 should have been aborted + abort_txn(penv, txn2); + for (int kk = 22; kk < 24; kk++) { + keystr = const_cast<char*>(kstrs[kk].c_str()); + check_expr(smap.count(keystr) == 0); + } + + break; + + default: + break; + + }//switch + + smap.insert(make_pair(kstr, dstr)); + }// for + + if (commit_or_abort == 0) { + + // if txn1 commits, 0 1 2 6 7 8 12 13 14 19 20 21 25, 26 + idxset.insert(0); + idxset.insert(1); + idxset.insert(2); + idxset.insert(6); + idxset.insert(7); + idxset.insert(8); + idxset.insert(12); + idxset.insert(13); + idxset.insert(14); + idxset.insert(19); + idxset.insert(20); + idxset.insert(21); + idxset.insert(25); + + + + for (int kk = 0; kk < 26; kk++) { + keystr = const_cast<char*>(kstrs[kk].c_str()); + sizet1 = smap.count(keystr); + if (idxset.count(kk) > 0) { + check_expr(sizet1 > 0); + } else { + check_expr(sizet1 == 0); + } + } + + commit_or_abort = 1; + smap.clear(); + commit_txn(penv, txn1); + goto commit_abort; + } + + if (commit_or_abort != 0){ + abort_txn(penv, txn1);// non could have been inserted + begin_txn(0, penv);// put this call in a txnal context + check_expr((sizet1 = smap.size()) == 0); + commit_txn(penv); + } + + if (TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + + return; +} // test_nested_txns + + +// Testing miscellaneous functions. +void TestAssoc::test_etc() +{ + set_global_dbfile_suffix_number(65536); + DbEnv *penvtmp = dbstl::open_env(".", 0, DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL); + dbstl::close_db_env(penvtmp); + db_mutex_t mtxhdl = dbstl::alloc_mutex(); + lock_mutex(mtxhdl); + unlock_mutex(mtxhdl); + free_mutex(mtxhdl); + + try { + throw_bdb_exception("test_assoc::test_etc()", DB_LOCK_DEADLOCK); + } catch (DbDeadlockException e1) + {} + + try { + throw_bdb_exception("test_assoc::test_etc()", DB_LOCK_NOTGRANTED); + } catch (DbLockNotGrantedException e2) + {} + + try { + throw_bdb_exception("test_assoc::test_etc()", DB_REP_HANDLE_DEAD); + } catch (DbRepHandleDeadException e13) + {} + + try { + throw_bdb_exception("test_assoc::test_etc()", DB_RUNRECOVERY); + } catch (DbRunRecoveryException e4) + {} + + try { + throw_bdb_exception("test_assoc::test_etc()", 12345); + } catch (DbException e1) + {} + + try { + throw_bdb_exception("test_assoc::test_etc()", 54321); + } catch (DbException e1) + {} + + ptint_vector vctr; + vctr.set_all_flags(1, 1, 1); + check_expr(vctr.get_commit_flags() == 1); + check_expr(vctr.get_cursor_open_flags() == 1); + check_expr(vctr.get_db_open_flags() & DB_CREATE); + check_expr(vctr.get_txn_begin_flags() == 1); + vctr.get_db_set_flags(); + vctr.set_commit_flags(2); + check_expr(vctr.get_commit_flags() == 2); + vctr.set_cursor_open_flags(2); + check_expr(vctr.get_cursor_open_flags() == 2); + vctr.set_txn_begin_flags(2); + check_expr(vctr.get_txn_begin_flags() == 2); + + +} + + |