• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/db-4.8.30/test_stl/base/
1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2009 Oracle.  All rights reserved.
5 *
6 * $Id$
7 */
8
9#include "test.h"
10// This function tests all member functions in the four assocative
11// containers and their iterators. The containers are db_map,
12// db_multimap, db_set, db_multiset . They are equivalent to std::map,
13// hash_map, std::multimap, hash_multimap, std::set, hash_set,
14// std::multiset, hash_multiset respectively---passing btree db handles,
15// they are equivalent to std assocative container; passing hash db handles
16// they are hash associative containers
17//
18// This function tests the classes also in pair with std/hash counterparts,
19// but the result of some operations are checked not by comparing contents
20// after operation, but by self-check, often use another member function of
21// the same class to verify. Also, only the four container types in std is
22// used, the hash containers are not standarized, so not used, although
23// hash db type can be passed in, so the db_containers can be of hash type
24//
25// Most of the algorithms in std are targeting at a sequential range, while
26// ranges in associative containers are not, so only some read only
27// algorithms are applied to the db_map container.
28//
29// This function also tests some advanced features, like using containers
30// with secondary db, bulk retrieval, varying length records storage/load,
31// storing native char*/wchar_t* strings, etc
32//
33
34static int hcmp_def(Db *pdb, const Dbt *dbt1, const Dbt *dbt2)
35{
36	u_int32_t sz1 = dbt1->get_size(), sz2 = dbt2->get_size();
37
38	int ret = memcmp(dbt1->get_data(), dbt2->get_data(), sz1 < sz2 ? sz1 : sz2);
39	ret = (ret == 0) ? (sz1 - sz2) : ret;
40
41	return ret;
42}
43
44class TestAssoc
45{
46public:
47	typedef map<int, int> m_int_t;
48	typedef ptint tpint;
49	~TestAssoc();
50	TestAssoc(void *param1);
51	void start_test()
52	{
53		tb.begin("db_map");
54		test_map_member_functions();
55		test_map_std_functions();
56		test_hot_dbclose();
57		test_arbitrary_object_storage();
58		test_storing_std_strings();
59		test_secondary_containers();
60		tb.end();
61
62		tb.begin("db_multimap");
63		test_mmap_member_functions();
64		tb.end();
65
66		tb.begin("db_set");
67		test_set_member_functions();
68		tb.end();
69
70		tb.begin("db_multiset");
71		test_mset_member_functions();
72		tb.end();
73
74		tb.begin("Special functionalities of all dbstl containers.");
75		test_char_star_string_storage();
76		test_fixed_len_obj_storage();
77		test_arbitray_sequence_storage();
78		test_bulk_retrieval_read();
79		test_nested_txns();
80		test_etc();
81		tb.end();
82
83
84	}
85private:
86	// Test all member functions of db_map<>
87	void test_map_member_functions();
88
89	// Use std functions to manipulate db_map containers.
90	void test_map_std_functions();
91
92	// Close a live container's db handle then open it again and
93	// reassign to the same container, verify the container works.
94	void test_hot_dbclose();
95
96	// Use two ways to store an object of arbitrary length. The object
97	// contains some varying length members, char* string for example.
98	void test_arbitrary_object_storage();
99
100	void test_storing_std_strings();
101
102	// Open a secondary db H and associate it with an exisitng db handle
103	// which is being used by a container C1, then use H to create another
104	// container C2, verify we can get C1's data via C2.
105	// This technique works for all types of db and containers.
106	void test_secondary_containers();
107
108	// Test all member functions of db_multimap<>.
109	void test_mmap_member_functions();
110
111	// Test all member functions of db_set<>.
112	void test_set_member_functions();
113
114	// Test all member functions of db_multiset<>.
115	void test_mset_member_functions();
116
117	// Test direct storage of char* strings.
118	void test_char_star_string_storage();
119
120	// Testing storage of fixed length objects.
121	void test_fixed_len_obj_storage();
122
123	// Testing storage of arbitrary element type of sequence.
124	void test_arbitray_sequence_storage();
125
126	// Testing reading with bulk retrieval flag.
127	void test_bulk_retrieval_read();
128
129	// Testing nested transaction implementation.
130	void test_nested_txns();
131
132	// Testing miscellaneous functions.
133	void test_etc();
134
135	int flags, setflags, EXPLICIT_TXN, TEST_AUTOCOMMIT, n;
136	DBTYPE dbtype;
137	dm_int_t::difference_type oddcnt;
138	Db *dmdb1, *dmdb2, *dmmdb1, *dmmdb2, *dmsdb1,
139	    *dmsdb2, *dmmsdb1, *dmmsdb2, *dbstrv;
140	Db *dbp3;
141	Db *dmdb6;
142	Db *dbp3sec;
143	Db *dmmdb4, *dbstrmap;
144	Db *dmstringdb;
145	DbEnv *penv;
146	u_int32_t dboflags;
147
148	test_block tb;
149	map<int, int> m1;
150	multimap<int, int> mm1;
151};
152
153TestAssoc::~TestAssoc()
154{
155	dbstl::close_db_cursors(this->dmsdb2);
156	dbstl::close_db_cursors(this->dmdb1);
157	dbstl::close_db_cursors(this->dmdb2);
158	dbstl::close_db_cursors(this->dmdb6);
159	dbstl::close_db_cursors(this->dmmdb1);
160}
161
162TestAssoc::TestAssoc(void *param1)
163{
164	check_expr(param1 != NULL);
165	TestParam *param = (TestParam*)param1;
166	TestParam *ptp = param;
167
168	flags = 0, setflags = 0, EXPLICIT_TXN = 1, TEST_AUTOCOMMIT = 0;
169	dbtype = DB_BTREE;
170	penv = param->dbenv;
171	dmdb1 = dmdb2 = dmmdb1 = dmmdb2 = dmsdb1 = dmsdb2 = dmmsdb1 =
172	    dmmsdb2 = dbstrv = NULL;
173	flags = param->flags;
174	dbtype = param->dbtype;
175	setflags = param->setflags;
176	TEST_AUTOCOMMIT = param->TEST_AUTOCOMMIT;
177	EXPLICIT_TXN = param->EXPLICIT_TXN;
178	dboflags = ptp->dboflags;
179	n = 10;
180
181	dmdb1 = dbstl::open_db(penv, "db_map.db",
182	    dbtype, DB_CREATE | ptp->dboflags, 0);
183	dmdb2 = dbstl::open_db(penv, "db_map2.db",
184	    dbtype, DB_CREATE | ptp->dboflags, 0);
185	dmdb6 = dbstl::open_db(penv, "db_map6.db",
186	    dbtype, DB_CREATE | ptp->dboflags, 0);
187
188	dmmdb1 = dbstl::open_db(penv,
189	    "db_multimap.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP);
190	dmmdb2 = dbstl::open_db(penv,
191	    "db_multimap2.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP);
192
193	dmsdb1 = dbstl::open_db(penv, "db_set.db",
194	    dbtype, DB_CREATE | ptp->dboflags, 0);
195	dmsdb2 = dbstl::open_db(penv, "db_set2.db",
196	    dbtype, DB_CREATE | ptp->dboflags, 0);
197
198	dmmsdb1 = dbstl::open_db(penv,
199	    "db_multiset.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP);
200	dmmsdb2 = dbstl::open_db(penv,
201	    "db_multiset2.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP);
202
203	dbstrv = dbstl::open_db(penv, "dbstr.db",
204	    DB_RECNO, DB_CREATE | ptp->dboflags, DB_RENUMBER);
205	dbp3sec = dbstl::open_db(penv, "db_map_sec.db",
206	    dbtype, DB_CREATE | ptp->dboflags, DB_DUP);
207
208	dmmdb4 = dbstl::open_db(penv,
209	    "db_multimap4.db", dbtype, DB_CREATE | dboflags, DB_DUPSORT);
210	dbstrmap = dbstl::open_db(penv, "dbstrmap.db",
211	    DB_BTREE, DB_CREATE, 0);
212
213	dmstringdb = dbstl::open_db(penv, "db_map_stringdb.db",
214	    dbtype, DB_CREATE | dboflags, 0);
215	dbp3 = NULL;
216
217}
218
219void TestAssoc::test_map_member_functions()
220{
221	int i;
222
223	if (EXPLICIT_TXN)
224		dbstl::begin_txn(0, penv);
225
226	dm_int_t dm1(dmdb1, penv);
227	const dm_int_t& cnstdm1 = dm1;
228	dm_int_t simple_map;
229	map<ptint, ptint> ssimple_map;
230	map<ptint, ptint>::iterator sitr, sitr1;
231
232	for (i = 0; i < n; i++) {
233		dm1[i] = ptint(i);
234		ssimple_map[i] = ptint(i);
235	}
236
237	for (i = 0; i < n; i++) {
238		dm_int_t::const_iterator citr, citr1;
239		dm_int_t::iterator itr;
240
241		citr = dm1.find(i);
242		check_expr(citr->second == dm1.find(i)->second);
243		itr = citr;
244		check_expr(*citr == *itr);
245		itr->second = i * 2 + 1;
246		citr1 = itr;
247		check_expr(*citr == *itr);
248		check_expr(*citr == *citr1);
249		check_expr(citr->second == dm1.find(i)->second);
250	}
251
252	for (i = 0; i < n; i++) {
253		dm_int_t::const_iterator citr = dm1.find(i);
254		check_expr(citr->second == dm1.find(i)->second);
255		dm_int_t::iterator itr = citr;
256		check_expr(*citr == *itr);
257		itr->second = i * 2 + 1;
258		dm_int_t::const_iterator citr1 = itr;
259		check_expr(*citr == *itr);
260		check_expr(*citr == *citr1);
261		check_expr(citr->second == dm1.find(i)->second);
262	}
263
264	for (i = 0; i < n; i++) {
265		dm_int_t::iterator ncitr, ncitr1;
266		dm_int_t::const_iterator citr, citr1;
267
268		ncitr = cnstdm1.find(i);
269		check_expr(ncitr->second == cnstdm1.find(i)->second);
270		citr = ncitr;
271		check_expr(*citr == *ncitr);
272		//*ncitr = i * 2 + 1;
273		citr1 = ncitr;
274		ncitr1 = citr1;
275		check_expr(*citr == *ncitr);
276		check_expr(*citr == *ncitr1);
277		check_expr(*citr == *citr1);
278		check_expr(citr->second == cnstdm1.find(i)->second);
279	}
280
281	for (i = 0; i < n; i++) {
282
283		dm_int_t::iterator ncitr = cnstdm1.find(i);
284		check_expr(ncitr->second == cnstdm1.find(i)->second);
285		dm_int_t::const_iterator citr = ncitr;
286		check_expr(*citr == *ncitr);
287		//*itr = i * 2 + 1;
288		dm_int_t::const_iterator citr1 = ncitr;
289		dm_int_t::iterator ncitr1 = citr1;
290
291		check_expr(*citr == *ncitr);
292		check_expr(*citr == *ncitr1);
293		check_expr(*citr == *citr1);
294		check_expr(citr->second == cnstdm1.find(i)->second);
295	}
296
297	if (dm1.is_hash() == false)
298	{
299		dm1.clear();
300		ssimple_map.clear();
301		for (i = 0; i < n; i++) {
302			dm1[i] = ptint(i);
303			ssimple_map[i] = ptint(i);
304		}
305		dm_int_t::iterator ncitr = dm1.end();
306		dm_int_t::iterator ncrend = --dm1.begin();
307		map<ptint, ptint>::iterator sitr = ssimple_map.end();
308		for (sitr--, --ncitr; ncitr != ncrend; ncitr--, sitr--) {
309			ncitr.refresh(true); // not needed because by default we are using direct db get, only for test purpose.
310			check_expr(*sitr == *ncitr);
311		}
312		ncitr.close_cursor();
313
314		const dm_int_t&cnstdm1 = dm1;
315		dm_int_t::const_iterator citr = cnstdm1.end();
316		dm_int_t::const_iterator crend = --cnstdm1.begin();
317		map<ptint, ptint>::iterator sitr2;
318		map<ptint, ptint>::reverse_iterator rsitr;
319
320		sitr = ssimple_map.end();
321		for (sitr--, --citr; citr!= crend; sitr--, citr--) {
322			citr.refresh(true); // not needed because by default we are using direct db get, only for test purpose.
323			check_expr(*sitr == *citr);
324		}
325
326		for (sitr2 = --ssimple_map.begin(), citr = crend; citr != cnstdm1.end();) {
327			citr++;
328			sitr2++;
329			check_expr(*sitr2 == *citr);
330		}
331
332		simple_map.insert(simple_map.begin(), *ssimple_map.begin());
333		check_expr(*simple_map.begin() == *ssimple_map.begin());
334		crend = --cnstdm1.begin();
335		--(--crend);
336		++crend;
337		check_expr(*crend == *cnstdm1.begin());
338		citr.close_cursor();
339
340		simple_map.clear();
341		simple_map.insert(cnstdm1.begin(), cnstdm1.end());
342		rsitr = ssimple_map.rbegin();
343		for (dm_int_t::reverse_iterator itrr1 = simple_map.rbegin(); itrr1 != simple_map.rend(); ++itrr1, ++rsitr)
344			check_expr(*itrr1 == *rsitr);
345
346		const dm_int_t &csimple_map = simple_map;
347		rsitr = ssimple_map.rbegin();
348		for (dm_int_t::const_reverse_iterator citrr1 = csimple_map.rbegin(); citrr1 != csimple_map.rend(); ++citrr1, ++rsitr)
349			check_expr((citrr1->first == rsitr->first) && (citrr1->second == rsitr->second));
350
351		for (sitr = ssimple_map.begin(); sitr != ssimple_map.end(); ++sitr)
352			check_expr(csimple_map[sitr->first] == sitr->second);
353
354		simple_map.erase(simple_map.end());
355		check_expr(simple_map.size() == ssimple_map.size());
356		check_expr(csimple_map.find(123) == csimple_map.end());
357
358		check_expr(*csimple_map.lower_bound(1) == *ssimple_map.lower_bound(1));
359		check_expr(*csimple_map.upper_bound(5) == *ssimple_map.upper_bound(5));
360		pair<dm_int_t::const_iterator, dm_int_t::const_iterator> cnsteqrg = csimple_map.equal_range(3);
361		check_expr(cnsteqrg.first->first == 3 && cnsteqrg.second->first == ssimple_map.equal_range(3).second->first);
362
363	}
364	dm1.clear();
365	ssimple_map.clear();
366
367	if (!dm1.is_hash()) {
368		for (i = 0; i < n; i++) {
369			dm1[i] = ptint(i);
370			ssimple_map[i] = ptint(i);
371		}
372		dm_int_t::iterator itr, itr1;
373
374		itr = dm1.find(3);
375		itr1 = dm1.find(8);
376		sitr = ssimple_map.find(3);
377		sitr1 = ssimple_map.find(8);
378
379		dm1.erase(itr, itr1);
380		ssimple_map.erase(sitr, sitr1);
381		pprint(dm1, "dm1 after erasing range: ");
382		check_expr(is_equal(dm1, ssimple_map));
383		dm1.clear();
384		ssimple_map.clear();
385	}
386	for (i = 0; i < 10; i++) {
387		simple_map.insert(make_pair(ptint(i), ptint(i)));
388		ssimple_map.insert(make_pair(ptint(i), ptint(i)));
389	}
390	for (i = 0; i < 10; i++)
391		check_expr(simple_map[i] == ssimple_map[i]);
392
393	dm1.clear();
394	// db_map<>::empty
395	check_expr(dm1.empty());
396	fill(dm1, m1, i = 3, n = 5);
397	check_expr(!dm1.empty());
398
399	dm_int_t::iterator dmi, dmi2;
400	m_int_t::iterator mi;
401	dm_int_t::reverse_iterator dmri;
402	m_int_t::reverse_iterator mri;
403	ptint ptmp;
404	int itmp;
405
406
407	// db_map<>::find, count
408	for (dmi = dm1.begin(), mi = m1.begin(), i = 3; dmi != dm1.end() &&
409	    mi !=m1.end(); dmi++, mi++, i++) {
410		// check_expr both contain
411		check_expr((dm1.find(i) != dm1.end()) &&
412		    (m1.find(i) != m1.end()));
413
414		pair<dm_int_t::iterator, dm_int_t::iterator> erp =
415		    dm1.equal_range(i);
416		int jc = 0;
417		dm_int_t::iterator jj;
418		for (jj = erp.first, jc = 0;
419		    jj != erp.second; jj++, jc++)
420		    check_expr((*jj).second == ptint(i));
421		check_expr(jc == 1);
422		if (i < 7 && !dm1.is_hash()) {// 7 is last element
423			check_expr((*(dm1.upper_bound(i))).second == i + 1);
424			check_expr((*(dm1.lower_bound(i))).second == i);
425		}
426		else if (i == 7 && !dm1.is_hash()) {
427			check_expr(dm1.upper_bound(i) == dm1.end());
428			check_expr((*(dm1.lower_bound(i))).second == i);
429		} else if (!dm1.is_hash())
430			check_expr(false);
431
432		check_expr(dm1.count(i) == 1);
433		check_expr(dm1.count(-i) == 0);
434		check_expr((ptmp = dm1[i]) == (itmp = m1[i]));
435
436		// order of elements in hash can not be expected
437		if (!dm1.is_hash())
438			check_expr((*dmi).second == (*mi).second);
439		if (i == 3 + n - 1) {// last element
440
441			for (; dmi != dm1.end(); mi--, i--) {
442				// check_expr both contains
443				check_expr((*(dm1.find(i))).second == i);
444				check_expr((ptmp = dm1[i]) == (itmp = m1[i]));
445				// order of elements in hash can not be
446				// expected
447				if (!dm1.is_hash())
448					check_expr((*dmi).second == (*mi).second);
449				if (i % 2)
450					dmi--;
451				else
452					--dmi;
453			}
454			break;
455		}
456
457	}
458	for (dmri = dm1.rbegin(), mri = m1.rbegin(), i = 3;
459	    dmri != dm1.rend() && mri != m1.rend(); dmri++, mri++, i++) {
460		check_expr((dm1.find(i) != dm1.end()) &&
461		    (m1.find(i) != m1.end()));// check_expr both contain
462
463		check_expr(dm1[i] == m1[i]);
464		if (!dm1.is_hash())
465			check_expr((*dmri).second == (*mri).second);
466		if (i == 3 + n - 1) {// last element
467
468			for (; dmri != dm1.rend(); mri--, i--) {
469				// check_expr both contain
470				check_expr((*(dm1.find(i))).second == i);
471				// order of elements in hash can not be expected
472				if (!dm1.is_hash())
473					check_expr((*dmri).second == (*mri).second);
474				check_expr((ptmp = dm1[i]) == (itmp = m1[i]));
475				if (i % 2)
476					dmri--;
477				else
478					--dmri;
479				if (i == 3)
480					break;
481			}
482			break;
483		}
484
485	}
486	for (dmi = dm1.begin(), mi = m1.begin(), i = 3; dmi != dm1.end() &&
487	    mi !=m1.end(); ++dmi, mi++)
488		i++;
489	check_expr(i == 3 + n);// i must have been incremented to 8
490	for (dmri = dm1.rbegin(), mri = m1.rbegin(), i = 3;
491	    dmri != dm1.rend() && mri !=m1.rend(); ++dmri, mri++)
492		i++;
493	check_expr(i == 3 + n);// i must have been incremented to 8
494
495
496	if (EXPLICIT_TXN)
497		commit_txn(penv);
498	if (!TEST_AUTOCOMMIT)
499		begin_txn(0, penv);
500	dm_int_t dm2(dmdb2, penv);
501	dm2.clear();
502	if (!TEST_AUTOCOMMIT)
503		commit_txn(penv);
504	if (EXPLICIT_TXN)
505		begin_txn(0, penv);
506	dm2.insert(dm1.begin(), dm1.end());
507	if (EXPLICIT_TXN)
508		commit_txn(penv);
509	if (!TEST_AUTOCOMMIT)
510		begin_txn(0, penv);
511	dm_int_t dm3 = dm2;
512	if (!TEST_AUTOCOMMIT)
513		commit_txn(penv);
514	if (EXPLICIT_TXN)
515		begin_txn(0, penv);
516	check_expr(dm3 == dm2);
517	if (EXPLICIT_TXN)
518		commit_txn(penv);
519	if (!TEST_AUTOCOMMIT)
520		begin_txn(0, penv);
521	dm3 = dm1;
522	if (!TEST_AUTOCOMMIT)
523		commit_txn(penv);
524	if (EXPLICIT_TXN)
525		begin_txn(0, penv);
526	check_expr(dm3 == dm1);
527	// this test case should be fine for hash because hash config is
528	// identical in dm1 and dm2
529	for (dmi = dm1.begin(), dmi2 = dm2.begin(); dmi != dm1.end() &&
530	    dmi2 != dm2.end(); ++dmi, dmi2++)
531		check_expr(*dmi == *dmi2);
532	int arr1[] = {33, 44, 55, 66, 77};
533
534	for (dmi = dm1.begin(), i = 0; dmi != dm1.end(); dmi++, i++)
535		(*dmi).second = tpint(arr1[i]);
536
537	for (dmi = dm1.begin(), dmi2 = dm2.begin(), i = 0;
538		dmi != dm1.end() && dmi2 != dm2.end(); dmi++, i++, dmi2++) {
539		check_expr((*dmi).second == tpint(arr1[i]));
540		dmi2->second = dmi->second;
541		check_expr(*dmi == *dmi2);
542	}
543	// db_map<>::insert(const value_type&). the range insert is already
544	// tested in fill
545	//
546	pair<dm_int_t::iterator, bool> res =
547	    dm1.insert(make_pair(3, tpint(33)));
548	check_expr((*(res.first)).first == 3 && res.second == false);
549	// we don't know which value is assigned to key 3 on hash
550	if (!dm1.is_hash())
551		check_expr((*(res.first)).second == 33);
552
553	// db_map<>::count, insert, erase, find
554	check_expr(dm1.count(3) == 1);
555	check_expr(dm1.size() == (size_t)n);// n is 5
556	check_expr(dm1.count(9) == 0);
557	res = dm1.insert(make_pair(9, tpint(99)));
558	check_expr((*(res.first)).second == 99 && (*(res.first)).first == 9 &&
559	    res.second == true);
560	check_expr(dm1.count(9) == 1);
561	check_expr(dm1.size() == (size_t)n + 1);
562
563	if (EXPLICIT_TXN)
564		dbstl::commit_txn(penv);
565
566	if (!TEST_AUTOCOMMIT)
567		dbstl::begin_txn(0, penv);
568	dm1.erase(9);
569	if (!TEST_AUTOCOMMIT)
570		commit_txn(penv);
571	if (EXPLICIT_TXN)
572		begin_txn(0, penv);
573
574	check_expr(dm1.size() == (size_t)n);
575	check_expr(dm1.count(9) == 0);
576	dm1.erase(dm1.find(3));
577	check_expr(dm1.size() == (size_t)n - 1);
578	check_expr(dm1.count(3) == 0);
579	dm2.erase(dm2.begin(), dm2.end());
580	check_expr(dm2.size() == 0);
581	check_expr(dm2.empty());
582
583	dmi = dm1.begin();
584	dmi++;
585	dmi2 = dmi;
586	dmi2++;
587	dmi2++;
588
589	if (dm1.is_hash()) {
590		check_expr(dm1.key_eq()(3, 4) == false);
591		check_expr(dm1.key_eq()(3, 3) == true);
592		check_expr(dm1.bucket_count() != 0);
593	} else
594		check_expr(dm1.key_comp()(3, 4));
595
596	if (dm1.is_hash()) {
597		check_expr(dm1.key_eq()(3, 4) == false);
598		check_expr(dm1.key_eq()(3, 3) == true);
599	} else {
600		check_expr(dm1.key_comp()(3, 4));
601	}
602
603	check_expr(dm1.value_comp()(*dmi, *dmi2));
604	if (dm1.is_hash())
605		cout<<"hash value for key = 3 is: "
606		    <<dm1.hash_funct()(3);
607
608	dm2.insert(dmi, dmi2);// 2 recs inserted, [dmi, dmi2)
609	check_expr(dm2.size() == 2);
610	for (dmi = dm1.begin(); dmi != dm1.end(); dmi++)
611		cout<<'\t'<<dmi->first<<'\t'<<dmi->second<<endl;
612	if (EXPLICIT_TXN)
613		commit_txn(penv);
614
615	if (!TEST_AUTOCOMMIT) {
616		begin_txn(0, penv);
617	}
618	dm1.swap(dm2);
619	if (!TEST_AUTOCOMMIT) {
620		commit_txn(penv);
621	}
622	if (EXPLICIT_TXN)
623		begin_txn(0, penv);
624	size_t dm1sz, dm2sz;
625	check_expr((dm1sz = dm1.size()) == 2 &&
626	    (dm2sz = dm2.size()) == (size_t)n - 1);
627	if (EXPLICIT_TXN)
628		dbstl::commit_txn(penv);
629
630	if (!TEST_AUTOCOMMIT) {
631		begin_txn(0, penv);
632	}
633	dm1.clear();
634	dm2.clear();
635	dm3.clear();
636	if (!TEST_AUTOCOMMIT) {
637		commit_txn(penv);
638	}
639	if (EXPLICIT_TXN)
640		begin_txn(0, penv);
641	fill(dm1, m1, i = 3, n = 5);
642	dm1sz = dm1.size();
643	for (i = (int)dm1sz -1; i >0; i--) {
644		dm1[i - 1] = dm1[i];
645		m1[i - 1] = m1[i];
646	}
647	if (!dm1.is_hash())
648		check_expr (is_equal(dm1, m1));
649	dm1[421] = 421;
650	check_expr(dm1.count(421) == 1);
651	m1[421] = 421;
652	int j;
653	for (i = 0; i < 100; i++) {
654		j = rand() ;
655		dm1[i] = i * j;
656#ifdef TEST_PRIMITIVE
657		m1[i] = ((ptint)dm1[i]);
658#else
659		m1[i] = ((ptint)dm1[i]).v;
660#endif
661	}
662	check_expr(dm1.size() == m1.size());
663	if (!dm1.is_hash())
664		check_expr (is_equal(dm1, m1));
665
666	for (i = 0; i < 99; i++) {
667		dm1[i] = dm1[i + 1];
668		m1[i] = m1[i + 1];
669	}
670	if (!dm1.is_hash())
671		check_expr (is_equal(dm1, m1));
672	dm1.clear();
673	m1.clear();
674	if (EXPLICIT_TXN)
675		commit_txn(penv);
676} // test_map_member_functions
677
678void TestAssoc::test_map_std_functions()
679{
680	int i;
681
682	if (EXPLICIT_TXN)
683		begin_txn(0, penv);
684	dm_int_t dm1(dmdb1, penv);
685	// the following test assumes dm1 and m1 contains
686	// (6,6), (7,7),...(14,14)
687	for(i = 6; i < 15; i++) {
688		dm1[i] = i;
689		m1[i] = i;
690	}
691	dm_int_t::iterator mpos, mpos2;
692	dm_int_t::reverse_iterator mrpos, mrpos2;
693// for_each
694	cout<<"\n_testing std algorithms applied to db_map...\n";
695	cout<<"\nfor_each begin to end\n";
696	for_each(dm1.begin(), dm1.end(), square_pair<dm_int_t::value_type_wrap>);
697	cout<<endl;
698	for_each(m1.begin(), m1.end(), square_pair2<map<int, int>::value_type>);
699	cout<<"\nfor_each begin +1 to end\n";
700	for_each(dm1.begin() ++, (dm1.begin()--)--, square_pair<dm_int_t::value_type_wrap>);
701	cout<<endl;
702	for_each(m1.begin() ++, (m1.begin() --)--, square_pair2<map<int, int>::value_type>);
703
704	//find
705	ptint tgt(12);
706	mpos = find(dm1.begin(), dm1.end(), make_pair(tgt, tgt));
707	check_expr(mpos != dm1.end() && ((mpos->second) == tgt));
708	mpos = find(++(dm1.begin() ++), --(dm1.end() --), make_pair(tgt, tgt));
709	check_expr(mpos != dm1.end() && ((mpos->second) == tgt));
710	tgt = -123;
711	mpos = find(dm1.begin(), dm1.end(), make_pair(tgt, tgt));
712	check_expr(mpos == dm1.end());
713	pair<int, int>* subseq3 = new pair<int, int>[3];
714	subseq3[0] = make_pair(8, 8);
715	subseq3[1] = make_pair(9, 9);
716	subseq3[2] = make_pair(10, 10);
717	pair<int, int>* subseq4 = new pair<int, int>[4];
718	subseq4[0] = make_pair(9, 9);
719	subseq4[1] = make_pair(8, 8);
720	subseq4[2] = make_pair(10, 10);
721	subseq4[3] = make_pair(11, 11);
722	// find_end
723	if (!dm1.is_hash()) {
724#ifdef WIN32
725		mpos = find_end(dm1.begin(), dm1.end(), dm1.begin(), ++(dm1.begin()) );
726		check_expr(mpos == dm1.begin());
727		mpos = find_end(dm1.begin(), dm1.end(), mpos2 = ++(++(dm1.begin()++)),
728		    --(--(dm1.end()--)));
729		check_expr(mpos == mpos2);
730
731		mpos = find_end(++dm1.begin(), dm1.end(), subseq3, subseq3 + 3);
732		check_expr(mpos == ++(++(dm1.begin())));
733#endif
734		// find_first_of
735		mpos = find_first_of(dm1.begin(), dm1.end(), dm1.begin(),
736		    ++dm1.begin());
737		check_expr(mpos == dm1.begin());
738
739		mpos = find_first_of(++dm1.begin(), --dm1.end(),
740		    subseq4, subseq4 + 4);
741		check_expr(mpos == ++(++dm1.begin()));
742		mpos = find_first_of(--(--dm1.end()), dm1.end(),
743		    subseq4, subseq4 + 4);
744		check_expr(mpos == dm1.end());
745
746		// mismatch
747
748		pair<dm_int_t::iterator , pair<int, int>*> resmm2 = mismatch(dm1.begin(),
749		    ++(++(++dm1.begin())), subseq3);
750		check_expr(resmm2.first == dm1.begin() && resmm2.second == subseq3);
751
752		//search
753		mpos = search(dm1.begin(), dm1.end(), dm1.begin(), ++dm1.begin());
754		check_expr(mpos == dm1.begin());
755		mpos = search(++dm1.begin(), dm1.end(), subseq3, subseq3 + 3);
756		check_expr(mpos == ++(++dm1.begin()));
757		//equal
758		mpos2 = dm1.begin();
759		mpos2.move_to(8);
760		check_expr (equal(dm1.begin(), mpos2, subseq3) == false);
761		mpos = mpos2; mpos.move_to(11);
762		check_expr(equal(mpos2, mpos, subseq3) == true);
763		mpos.move_to(10);
764		check_expr(equal(mpos2, mpos, subseq3) == true);
765	}
766	delete [] subseq4;
767	delete [] subseq3;
768	//find_if
769	mpos = find_if(dm1.begin(), dm1.end(), is2digits_pair);
770	check_expr(ptint(mpos->second) == 10);
771
772	// count_if
773	oddcnt = count_if(dm1.begin(), dm1.end(), is_odd_pair);
774	check_expr(oddcnt == 4);
775	oddcnt = count_if(dm1.begin(), dm1.begin(), is_odd_pair);
776	check_expr(oddcnt == 0);
777
778
779	if ( EXPLICIT_TXN)
780		dbstl::commit_txn(penv);
781
782
783} // test_map_std_functions
784
785void TestAssoc::test_hot_dbclose()
786{
787	int i;
788	map<ptint, ptint> m2;
789	dm_int_t dm2(dmdb2, penv);
790
791	if (!TEST_AUTOCOMMIT)
792		dbstl::begin_txn(0, penv);
793	dm2.clear();// can be auto commit
794	if (!TEST_AUTOCOMMIT)
795		dbstl::commit_txn(penv);
796
797	if (EXPLICIT_TXN)
798		begin_txn(0, penv);
799	for (i = 0; i < 5; i++) {
800		dm2[i] = i;
801		m2[i] = i;
802	}
803
804	if (EXPLICIT_TXN)
805		dbstl::commit_txn(penv);
806	dm_int_t dm1(dmdb1, penv);
807	dbstl::close_db(dm1.get_db_handle());
808	if (EXPLICIT_TXN)
809		dbstl::begin_txn(0, penv);
810
811	dm1.set_db_handle(dbp3 = dbstl::open_db(penv, "db_map.db",
812	    dbtype, DB_CREATE | dboflags, 0));
813	if (!dm1.is_hash())
814		check_expr (is_equal(dm1, m1));
815	dm1.clear();
816	if (EXPLICIT_TXN)
817		commit_txn(penv);
818} // test_hot_dbclose
819
820void TestAssoc::test_arbitrary_object_storage()
821{
822	int i;
823
824	if (EXPLICIT_TXN)
825		begin_txn(0, penv);
826	// varying length objects test
827	cout<<"\n_testing arbitary object storage using Dbt..\n";
828
829	rand_str_dbt smsdbt;
830	DbstlDbt dbt, dbtmsg;
831	string msgstr;
832	SMSMsg *smsmsgs[10];
833
834	dbtmsg.set_flags(DB_DBT_USERMEM);
835	dbt.set_data(DbstlMalloc(256));
836	dbt.set_flags(DB_DBT_USERMEM);
837	dbt.set_ulen(256);
838	db_map<int, DbstlDbt> msgmap(dbp3, penv);
839	for (i = 0; i < 10; i++) {
840		smsdbt(dbt, msgstr, 10, 200);
841		SMSMsg *pmsg = SMSMsg::make_sms_msg(time(NULL),
842		    (char *)dbt.get_data(), i);
843		smsmsgs[i] = SMSMsg::make_sms_msg(time(NULL),
844		    (char *)dbt.get_data(), i);
845		dbtmsg.set_data(pmsg);
846		dbtmsg.set_ulen((u_int32_t)(pmsg->mysize));
847		dbtmsg.set_size((u_int32_t)(pmsg->mysize));
848		dbtmsg.set_flags(DB_DBT_USERMEM);
849		msgmap.insert(make_pair(i, dbtmsg));
850		free(pmsg);
851		memset(&dbtmsg, 0, sizeof(dbtmsg));
852	}
853	dbtmsg.set_data(NULL);
854	// check that retrieved data is identical to stored data
855	SMSMsg *psmsmsg;
856	for (i = 0; i < 10; i++) {
857		db_map<int, DbstlDbt>::data_type_wrap msgref = msgmap[i];
858		psmsmsg = (SMSMsg *)msgref.get_data();
859
860		check_expr(memcmp(smsmsgs[i], psmsmsg,
861		    smsmsgs[i]->mysize) == 0);
862	}
863
864	i = 0;
865	for (db_map<int, DbstlDbt>::iterator msgitr = msgmap.begin(ReadModifyWriteOption::
866	    read_modify_write()); msgitr != msgmap.end(); ++msgitr, i++) {
867		db_map<int, DbstlDbt>::reference smsmsg = *msgitr;
868		(((SMSMsg*)(smsmsg.second.get_data())))->when = time(NULL);
869		smsmsg.second._DB_STL_StoreElement();
870
871	}
872
873	for (i = 0; i < 10; i++)
874		free(smsmsgs[i]);
875
876	msgmap.clear();
877
878
879	cout<<"\n_testing arbitary object(sparse, varying length) storage support using registered callbacks...\n";
880	db_map<int, SMSMsg2> msgmap2(dbp3, penv);
881	SMSMsg2 smsmsgs2[10];
882	DbstlElemTraits<SMSMsg2>::instance()->set_copy_function(SMSMsgCopy);
883	DbstlElemTraits<SMSMsg2>::instance()->set_size_function(SMSMsgSize);
884	DbstlElemTraits<SMSMsg2>::instance()->set_restore_function(SMSMsgRestore);
885	// use new technique to store varying length and inconsecutive objs
886	for (i = 0; i < 10; i++) {
887		smsdbt(dbt, msgstr, 10, 200);
888		SMSMsg2 msg2(time(NULL), msgstr.c_str(), i);
889		smsmsgs2[i] = msg2;
890
891		msgmap2.insert(make_pair(i, msg2));
892
893	}
894
895	// check that retrieved data is identical to stored data
896	SMSMsg2 tmpmsg2;
897	for (i = 0; i < 10; i++) {
898		tmpmsg2 = msgmap2[i];
899		check_expr(smsmsgs2[i] == tmpmsg2);
900	}
901	for (db_map<int, SMSMsg2>::iterator msgitr = msgmap2.begin(ReadModifyWriteOption::
902	    read_modify_write()); msgitr != msgmap2.end(); msgitr++) {
903		    db_map<int, SMSMsg2>::reference smsmsg = *msgitr;
904		smsmsg.second.when = time(NULL);
905		smsmsg.second._DB_STL_StoreElement();
906
907	}
908	msgmap2.clear();
909	if (EXPLICIT_TXN)
910		commit_txn(penv);
911} // test_arbitrary_object_storage
912
913// std::string persistent test.
914void TestAssoc::test_storing_std_strings()
915{
916	string kstring = "hello world", *sstring = new string("hi there");
917	if (EXPLICIT_TXN)
918		begin_txn(0, penv);
919
920	db_map<string, string> pmap(dmstringdb, NULL);
921
922	pmap[kstring] = *sstring + "!";
923	*sstring = pmap[kstring];
924	map<string, string> spmap;
925	spmap.insert(make_pair(kstring, *sstring));
926	cout<<"sstring append ! is : "<<pmap[kstring]<<" ; *sstring is : "<<*sstring;
927	delete sstring;
928	for (db_map<string, string>::iterator ii = pmap.begin();
929	    ii != pmap.end();
930	    ++ii) {
931		cout << (*ii).first << ": " << (*ii).second << endl;
932	}
933	close_db(dmstringdb);
934
935	dmstringdb = dbstl::open_db(penv, "db_map_stringdb.db",
936	    dbtype, DB_CREATE | dboflags, 0);
937	db_map<string, string> pmap2(dmstringdb, NULL);
938	for (db_map<string, string>::iterator ii = pmap2.begin();
939	    ii != pmap2.end();
940	    ++ii) {
941		cout << (*ii).first << ": " << (*ii).second << endl;
942		// assert key/data pair set equal
943		check_expr((spmap.count(ii->first) == 1) && (spmap[ii->first] == ii->second));
944	}
945	if (EXPLICIT_TXN)
946		commit_txn(penv);
947
948	db_vector<string> strvctor(10);
949	vector<string> sstrvctor(10);
950	for (int i = 0; i < 10; i++) {
951		strvctor[i] = "abc";
952		sstrvctor[i] = strvctor[i];
953	}
954	check_expr(is_equal(strvctor, sstrvctor));
955}
956
957void TestAssoc::test_secondary_containers()
958{
959	int i;
960
961	if (EXPLICIT_TXN)
962		begin_txn(0, penv);
963	// test secondary db
964	cout<<"\n_testing db container backed by secondary database...";
965
966	dbp3->associate(dbstl::current_txn(penv), dbp3sec,
967	    get_dest_secdb_callback, DB_CREATE);
968	typedef db_multimap<int, BaseMsg>  sec_mmap_t;
969	sec_mmap_t secmmap(dbp3sec, penv);// index "to" field
970	db_map<int, BaseMsg> basemsgs(dbp3, penv);
971	basemsgs.clear();
972	BaseMsg tmpmsg;
973	multiset<BaseMsg> bsmsgs, bsmsgs2;
974	multiset<BaseMsg>::iterator bsitr1, bsitr2;
975	// populate primary and sec db
976	for (i = 0; i < 10; i++) {
977		tmpmsg.when = time(NULL);
978		tmpmsg.to = 100 - i % 3;// sec index multiple
979		tmpmsg.from = i + 20;
980		bsmsgs.insert( tmpmsg);
981		basemsgs.insert(make_pair(i, tmpmsg));
982
983	}
984	check_expr(basemsgs.size() == 10);
985	// check retrieved data is identical to those fed in
986	sec_mmap_t::iterator itrsec;
987	for (itrsec = secmmap.begin(ReadModifyWriteOption::no_read_modify_write(), true);
988	    itrsec != secmmap.end(); itrsec++) {
989		bsmsgs2.insert(itrsec->second);
990	}
991	for (bsitr1 = bsmsgs.begin(), bsitr2 = bsmsgs2.begin();
992	    bsitr1 != bsmsgs.end() && bsitr2 != bsmsgs2.end(); bsitr1++, bsitr2++) {
993		check_expr(*bsitr1 == *bsitr2);
994	}
995	check_expr(bsitr1 == bsmsgs.end() && bsitr2 == bsmsgs2.end());
996
997	// search using sec index, check the retrieved data is expected
998	// and exists in bsmsgs
999	check_expr(secmmap.size() == 10);
1000	pair<sec_mmap_t::iterator, sec_mmap_t::iterator> secrg =
1001	    secmmap.equal_range(98);
1002
1003	for (itrsec = secrg.first; itrsec != secrg.second; itrsec++) {
1004		check_expr(itrsec->second.to == 98 &&
1005		    bsmsgs.count(itrsec->second) > 0);
1006	}
1007	// delete via sec db
1008	size_t nersd = secmmap.erase(98);
1009	check_expr(10 - nersd == basemsgs.size());
1010	secrg = secmmap.equal_range(98);
1011	check_expr(secrg.first == secrg.second);
1012
1013	if (EXPLICIT_TXN)
1014		dbstl::commit_txn(penv);
1015
1016} // test_secondary_containers
1017
1018void TestAssoc::test_mmap_member_functions()
1019{
1020	// db_multimap<>
1021	int i;
1022
1023	if (EXPLICIT_TXN)
1024		dbstl::begin_txn(0, penv);
1025	dmm_int_t dmm1(dmmdb1, penv);
1026
1027	dmm1.clear();
1028	// db_multimap<>::empty
1029	check_expr(dmm1.empty());
1030	{
1031	size_t sz0, szeq1, szeq2;
1032
1033	fill(dmm1, mm1, i = 3, n = 5, 4);
1034	const dmm_int_t &cdmm1 = dmm1;
1035	dmm_int_t dmmn(NULL, penv);
1036	dmmn.insert(cdmm1.begin(), cdmm1.end());
1037	check_expr(!(dmmn != cdmm1));
1038
1039	pair<dmm_int_t::const_iterator, dmm_int_t::const_iterator> cnstrg, ceqrgend;
1040	pair<dmm_int_t::iterator, dmm_int_t::iterator> nceqrg, eqrgend;
1041
1042	for (i = 3; i < 8; i++) {
1043		cnstrg = cdmm1.equal_range(i);
1044		nceqrg = dmm1.equal_range(i);
1045		dmm_int_t::const_iterator cmmitr;
1046		dmm_int_t::iterator mmitr;
1047		for (sz0 = 0, cmmitr = cnstrg.first, mmitr = nceqrg.first; mmitr != nceqrg.second; mmitr++, cmmitr++, sz0++)
1048			check_expr(*cmmitr == *mmitr);
1049		check_expr(cmmitr == cnstrg.second);
1050		if (i < 7)
1051			check_expr(*(cdmm1.upper_bound(i)) == *(dmm1.upper_bound(i)));
1052		cnstrg = cdmm1.equal_range_N(i, szeq1);
1053		nceqrg = dmm1.equal_range_N(i, szeq2);
1054		check_expr(szeq1 == szeq2 && szeq2 == sz0);
1055	}
1056	eqrgend = dmm1.equal_range(65535);
1057	check_expr(eqrgend.first == dmm1.end() && eqrgend.second == dmm1.end());
1058	eqrgend = dmm1.equal_range_N(65535, szeq1);
1059	check_expr(eqrgend.first == dmm1.end() && eqrgend.second == dmm1.end() && szeq1 == 0);
1060	ceqrgend = cdmm1.equal_range(65535);
1061	check_expr(ceqrgend.first == cdmm1.end() && ceqrgend.second == cdmm1.end());
1062	ceqrgend = cdmm1.equal_range_N(65535, szeq1);
1063	check_expr(ceqrgend.first == cdmm1.end() && ceqrgend.second == cdmm1.end() && szeq1 == 0);
1064	if (!dmm1.is_hash()) {
1065		eqrgend = dmm1.equal_range(2);
1066		check_expr((((eqrgend.first))->first == 3) && ((eqrgend.second))->first == 3);
1067		ceqrgend = cdmm1.equal_range(2);
1068		check_expr(((ceqrgend.first))->first == 3 && ((ceqrgend.second))->first == 3);
1069		eqrgend = dmm1.equal_range_N(2, szeq1);
1070		check_expr((eqrgend.first)->first == 3 && ((eqrgend.second))->first == 3 && szeq1 == 0);
1071		ceqrgend = cdmm1.equal_range_N(2, szeq1);
1072		check_expr((ceqrgend.first)->first == 3 && ((ceqrgend.second))->first == 3 && szeq1 == 0);
1073
1074		check_expr(((dmm1.upper_bound(2)))->first == 3);
1075		check_expr(((cdmm1.upper_bound(2)))->first == 3);
1076		check_expr(dmm1.upper_bound(65535) == dmm1.end());
1077		check_expr(cdmm1.upper_bound(65535) == cdmm1.end());
1078		check_expr(dmm1.lower_bound(65535) == dmm1.end());
1079		check_expr(cdmm1.lower_bound(65535) == cdmm1.end());
1080		check_expr(dmm1.count(65535) == 0);
1081		check_expr(dmm1.find(65535) == dmm1.end());
1082		check_expr(cdmm1.find(65535) == cdmm1.end());
1083
1084		dmm_int_t tmpdmm0(dmm1);
1085		dmm1.erase(dmm1.end());
1086		check_expr(dmm1 == tmpdmm0);
1087		nceqrg = tmpdmm0.equal_range(5);
1088
1089		for (dmm_int_t::iterator itr0 = nceqrg.first; itr0 != nceqrg.second; ++itr0)
1090			itr0->second *= 2;
1091		check_expr(tmpdmm0 != dmm1);
1092		tmpdmm0.insert(dmm1.begin(), ++(++dmm1.begin()));
1093		check_expr(tmpdmm0 != dmm1);
1094	}
1095	dmm1.clear();
1096	mm1.clear();
1097	}
1098	fill(dmm1, mm1, i = 3, n = 5, 4);
1099	check_expr(!dmm1.empty());
1100
1101	typedef multimap<int, int> mm_int_t;
1102	dmm_int_t::iterator dmmi, dmmi2;
1103	mm_int_t::iterator mmi;
1104	dmm_int_t::reverse_iterator dmmri;
1105	mm_int_t::reverse_iterator mmri;
1106
1107	print_mm(dmm1, dmmi);
1108	// db_multimap<>::find, count
1109	for (dmmi = dmm1.begin(), mmi = mm1.begin(), i = 3;
1110	    dmmi != dmm1.end() &&
1111	    mmi !=mm1.end(); dmmi++, mmi++, i++) {
1112		// check_expr both contain
1113		check_expr((*(dmm1.find(i))).second == i);
1114
1115		pair<dmm_int_t::iterator, dmm_int_t::iterator> erp1 =
1116		    dmm1.equal_range(i);
1117		int jc = 0;
1118		dmm_int_t::iterator jj;
1119		for (jj = erp1.first, jc = 0;
1120		    jj != erp1.second; jj++, jc++)
1121			check_expr((*jj).second == ptint(i));
1122
1123		check_expr((size_t)jc == g_count[i]); // g_count[i] duplicates
1124		if (i < 7 && !dmm1.is_hash()) {// 7 is last element
1125			check_expr((*(dmm1.upper_bound(i))).second == i + 1);
1126			check_expr((*(dmm1.lower_bound(i))).second == i);
1127		}
1128		else if (i == 7 && !dmm1.is_hash()) {
1129			check_expr(dmm1.upper_bound(i) == dmm1.end());
1130			check_expr((*(dmm1.lower_bound(i))).second == i);
1131		} else if (!dmm1.is_hash())
1132			check_expr(false);
1133
1134		check_expr(dmm1.count(i) == g_count[i]);
1135		check_expr(dmm1.count(-i) == 0);
1136		if (!dmm1.is_hash())
1137			check_expr((*dmmi).second == (*mmi).second);
1138		if (i == 3 + n - 1) {// last element
1139
1140			for (; dmmi != dmm1.end(); mmi--, i--) {
1141				// check_expr both contains
1142				check_expr((*(dmm1.find(i))).second == i);
1143				if (!dmm1.is_hash())
1144					check_expr((*dmmi).second == (*mmi).second);
1145				if (i % 2)
1146					dmmi--;
1147				else
1148					--dmmi;
1149			}
1150			break;
1151		}
1152
1153	}
1154	for (dmmri = dmm1.rbegin(), mmri = mm1.rbegin(), i = 3;
1155	    dmmri != dmm1.rend() && mmri !=mm1.rend(); dmmri++, mmri++, i++) {
1156		check_expr((dmm1.find(i) != dmm1.end()) &&
1157		    (mm1.find(i) != mm1.end()));// check_expr both contain
1158		if (dmm1.is_hash() == false)
1159			check_expr((*dmmri).second == (*mmri).second);
1160		if (i == 3 + n - 1) {// last element
1161
1162			for (; dmmri != dmm1.rend() && mmri != mm1.rend(); i--) {
1163				// check_expr both contain
1164				check_expr((*(dmm1.find(i))).second == i);
1165				if (!dmm1.is_hash())
1166					check_expr((*dmmri).second == (*mmri).second);
1167				if (i % 2)
1168					dmmri--;
1169				else
1170					--dmmri;
1171				if (i > 3) // MS STL bug: when msri points to last element, it can not go back
1172					mmri--;
1173
1174			}
1175			break;
1176		}
1177
1178	}
1179	for (dmmi = dmm1.begin(), mmi = mm1.begin(), i = 3;
1180	    dmmi != dmm1.end() &&
1181	    mmi !=mm1.end(); ++dmmi, mmi++)
1182		i++;
1183	check_expr((size_t)i == 3 + g_sum(3, 8));
1184	for (dmmri = dmm1.rbegin(), mmri = mm1.rbegin(), i = 3;
1185	    dmmri != dmm1.rend() && mmri !=mm1.rend(); ++dmmri, mmri++)
1186		i++;
1187	check_expr((size_t)i == 3 + g_sum(3, 8));
1188
1189	dmm_int_t dmm2(dmmdb2, penv);
1190	dmm2.clear();
1191	dmmi = dmm1.begin();
1192	dmmi2 = dmm1.end();
1193	dmm2.insert(dmmi, dmmi2);
1194	if (EXPLICIT_TXN)
1195		dbstl::commit_txn(penv);
1196
1197	if (!TEST_AUTOCOMMIT)
1198		dbstl::begin_txn(0, penv);
1199	dmm_int_t dmm3 = dmm2;
1200	if (!TEST_AUTOCOMMIT)
1201		dbstl::commit_txn(penv);
1202
1203	if (EXPLICIT_TXN)
1204		dbstl::begin_txn(0, penv);
1205	check_expr(dmm3 == dmm2);
1206	if (EXPLICIT_TXN)
1207		dbstl::commit_txn(penv);
1208
1209	if (!TEST_AUTOCOMMIT)
1210		dbstl::begin_txn(0, penv);
1211	dmm3 = dmm1;
1212	if (!TEST_AUTOCOMMIT)
1213		dbstl::commit_txn(penv);
1214
1215	if (EXPLICIT_TXN)
1216		dbstl::begin_txn(0, penv);
1217	check_expr(dmm3 == dmm1);
1218
1219	for (dmmi = dmm1.begin(), dmmi2 = dmm2.begin(); dmmi != dmm1.end() &&
1220	    dmmi2 != dmm2.end(); ++dmmi, dmmi2++)
1221		check_expr(*dmmi == *dmmi2);
1222
1223	// content of dmm1 and dmm2 are changed since now
1224	int arr1[] = {33, 44, 55, 66, 77};
1225	int arr11[] = {33, 44, 55, 66, 77};
1226	for (dmmi = dmm1.begin(), i = 0; dmmi != dmm1.end(); dmmi++, i++)
1227		(*dmmi).second = tpint(arr11[i % 5]);
1228
1229	for (dmmi = dmm1.begin(), dmmi2 = dmm2.begin(), i = 0;
1230	    dmmi != dmm1.end() && dmmi2 != dmm2.end();
1231	    dmmi++, i++, dmmi2++) {
1232		check_expr((*dmmi).second == tpint(arr1[i % 5]));
1233		dmmi2->second = dmmi->second;
1234		check_expr(*dmmi == *dmmi2);
1235	}
1236
1237	// db_multimap<>::insert(const value_type&). the range insert is already
1238	// tested in fill
1239	//
1240	dmm_int_t::iterator iitr = dmm1.insert(make_pair(3, tpint(33)));
1241	check_expr(iitr->first == 3);
1242	// the returned iitr points to any rec with key==3, not necessarily
1243	// the newly inserted rec, so not sure of the value on hash
1244	if (dmm1.is_hash() == false)
1245		check_expr(iitr->second == 33);
1246
1247	dmm1.clear();
1248	mm1.clear();
1249	fill(dmm1, mm1, i = 3, n = 5, 4);
1250	// db_multimap<>::count, insert, erase, find
1251	size_t sizet1;
1252	check_expr(dmm1.count(3) == g_count[3]);
1253	check_expr(dmm1.size() == (sizet1 = g_sum(3, 8)));// sum of recs from 3 to 8
1254	check_expr(dmm1.count(9) == 0);
1255	dmm_int_t::iterator iitr2 = dmm1.insert(make_pair(9, tpint(99)));
1256	check_expr(iitr2->first == 9 && iitr2->second == 99);
1257	check_expr(dmm1.count(9) == 1);
1258	check_expr(dmm1.size() == sizet1 + 1);
1259	dmm1.erase(9);
1260	check_expr(dmm1.size() == (sizet1 = g_sum(3, 8)));
1261	check_expr(dmm1.count(9) == 0);
1262	dmm1.erase(dmm1.find(3));
1263	check_expr(dmm1.size() == g_sum(3, 8) - 1);
1264	check_expr(dmm1.count(3) == (g_count[3] - 1 > 0 ? g_count[3] - 1 : 0));
1265	dmm2.erase(dmm2.begin(), dmm2.end());
1266	check_expr(dmm2.size() == 0);
1267	check_expr(dmm2.empty());
1268
1269	dmmi = dmm1.begin();
1270	dmmi++;
1271	dmmi2 = dmmi;
1272	dmmi2++;
1273	dmmi2++;
1274	size_t sizet2;
1275	dmm2.insert(dmmi, dmmi2);// 2 recs inserted, [dmi, dmi2)
1276	check_expr((sizet2 = dmm2.size()) == 2);
1277	if (EXPLICIT_TXN)
1278		dbstl::commit_txn(penv);
1279
1280	if (!TEST_AUTOCOMMIT)
1281		dbstl::begin_txn(0, penv);
1282
1283	dmm1.swap(dmm2);
1284	if (!TEST_AUTOCOMMIT)
1285		dbstl::commit_txn(penv);
1286
1287	if (EXPLICIT_TXN)
1288		dbstl::begin_txn(0, penv);
1289
1290	size_t dmm1sz, dmm2sz;
1291	check_expr((dmm1sz = dmm1.size()) == 2 && (dmm2sz =
1292	    dmm2.size()) == sizet1 - 1);
1293	if (EXPLICIT_TXN)
1294		dbstl::commit_txn(penv);
1295
1296	if (!TEST_AUTOCOMMIT)
1297		dbstl::begin_txn(0, penv);
1298	dmm1.clear();
1299	dmm2.clear();
1300	dmm3.clear();
1301	if (!TEST_AUTOCOMMIT)
1302		dbstl::commit_txn(penv);
1303
1304	if (EXPLICIT_TXN)
1305		dbstl::begin_txn(0, penv);
1306
1307	dmm_int_t dmm4(dmmdb4, penv);
1308	dmm4.clear();
1309	multimap<ptint, ptint> mm4;
1310	int jj;
1311	for (i = 0; i < 10; i++) {
1312		sizet2 = abs(rand() % 20) + 1;
1313		for (jj = 0; jj < (int)sizet2; jj++) {
1314			dmm4.insert(make_pair(i, jj));
1315			mm4.insert(make_pair(i, jj));
1316		}
1317	}
1318	pair<dmm_int_t::iterator, dmm_int_t::iterator> eqrgdmm;
1319	pair<multimap<ptint, ptint>::iterator, multimap<ptint, ptint>::iterator>
1320	    eqrgmm;
1321	dmm_int_t::iterator dmmitr;
1322	multimap<ptint, ptint>::iterator mmitr;
1323	for (i = 0; i < 10; i++) {
1324		eqrgdmm = dmm4.equal_range(i);
1325		eqrgmm = mm4.equal_range(i);
1326		for (dmmitr = eqrgdmm.first, mmitr = eqrgmm.first; dmmitr !=
1327		    eqrgdmm.second && mmitr != eqrgmm.second; dmmitr++, mmitr++)
1328			check_expr(*dmmitr == *mmitr);
1329		check_expr((dmmitr == eqrgdmm.second) && (mmitr == eqrgmm.second));
1330	}
1331	if (EXPLICIT_TXN)
1332		dbstl::commit_txn(penv);
1333
1334} // test_mmap_member_functions
1335
1336void TestAssoc::test_set_member_functions()
1337{
1338// db_set<>
1339	int i;
1340	int arr1[] = {33, 44, 55, 66, 77};
1341
1342	if (EXPLICIT_TXN)
1343		dbstl::begin_txn(0, penv);
1344	dms_int_t dms1(dmsdb1, penv);
1345	const dms_int_t& cnstdms1 = dms1;
1346	set<ptint> ms1;
1347
1348	n = 10;
1349	for (i = 0; i < n; i++)
1350		dms1.insert(i);
1351
1352	for (i = 0; i < n; i++) {
1353		dms_int_t::const_iterator citr, citr1;
1354		citr = dms1.find(i);
1355		check_expr(*citr == *dms1.find(i));
1356		dms_int_t::iterator itr = citr;
1357		check_expr(*citr == *itr);
1358		*itr = i;
1359		itr = dms1.find(i);
1360		citr = itr;
1361		citr1 = itr;
1362		check_expr(*citr == *itr);
1363		check_expr(*citr == *citr1);
1364		check_expr(*citr == *dms1.find(i));
1365	}
1366
1367	for (i = 0; i < n; i++) {
1368		dms_int_t::const_iterator citr = dms1.find(i);
1369		check_expr(*citr == *dms1.find(i));
1370		dms_int_t::iterator itr = citr;
1371		check_expr(*citr == *itr);
1372		*itr = i;
1373		itr = dms1.find(i);
1374		citr = itr;
1375		dms_int_t::const_iterator citr1 = itr;
1376		check_expr(*citr == *itr);
1377		check_expr(*citr == *citr1);
1378		check_expr(*citr == *dms1.find(i));
1379	}
1380
1381	for (i = 0; i < n; i++) {
1382		dms_int_t::iterator ncitr, ncitr1;
1383		dms_int_t::const_iterator citr, citr1;
1384
1385		ncitr = cnstdms1.find(i);
1386		check_expr(*ncitr == *cnstdms1.find(i));
1387		citr = ncitr;
1388		check_expr(*citr == *ncitr);
1389		//*ncitr = i * 2 + 1;
1390		citr1 = ncitr;
1391		ncitr1 = citr1;
1392		check_expr(*citr == *ncitr);
1393		check_expr(*citr == *ncitr1);
1394		check_expr(*citr == *citr1);
1395		check_expr(*citr == *cnstdms1.find(i));
1396	}
1397
1398	for (i = 0; i < n; i++) {
1399
1400		dms_int_t::iterator ncitr = cnstdms1.find(i);
1401		check_expr(*ncitr == *cnstdms1.find(i));
1402		dms_int_t::const_iterator citr = ncitr;
1403		check_expr(*citr == *ncitr);
1404		//*itr = i * 2 + 1;
1405		dms_int_t::const_iterator citr1 = ncitr;
1406		dms_int_t::iterator ncitr1 = citr1;
1407
1408		check_expr(*citr == *ncitr);
1409		check_expr(*citr == *ncitr1);
1410		check_expr(*citr == *citr1);
1411		check_expr(*citr == *cnstdms1.find(i));
1412	}
1413
1414	if (dms1.is_hash() == false)
1415	{
1416		ms1.clear();
1417		dms1.clear();
1418		for (i = 0; i < n; i++) {
1419			dms1.insert(ptint(i));
1420			ms1.insert(ptint(i));
1421		}
1422
1423		const dms_int_t &cnstdms1 = dms1;
1424		dms_int_t tmpdms0;
1425
1426		tmpdms0.insert(cnstdms1.begin(), cnstdms1.end());
1427		dms_int_t::const_iterator citr = dms1.end(), citr2 = --dms1.begin(), itr2;
1428		set<ptint>::const_iterator scitr = ms1.end(), scitr2 = --ms1.begin();
1429		for (citr--, scitr--; citr != citr2; --citr, --scitr) {
1430			check_expr(*citr == *scitr);
1431		}
1432		check_expr(scitr == scitr2);
1433
1434		db_set<ptype<int> > dmspt;
1435		dmspt.insert(cnstdms1.begin(), cnstdms1.end());
1436
1437		db_set<ptype<int> >::const_iterator itrpt;
1438		db_set<ptype<int> >::iterator itrpt2;
1439
1440		for (itrpt = dmspt.begin(), citr = dms1.begin(); itrpt != dmspt.end(); ++itrpt, ++citr) {
1441			itrpt.refresh(true);
1442			check_expr(itrpt->v == *citr);
1443		}
1444
1445		for (itrpt2 = dmspt.begin(), itr2 = dms1.begin(); itrpt2 != dmspt.end(); ++itrpt2, ++itr2) {
1446			itrpt2.refresh(true);
1447			check_expr(itrpt2->v == *itr2);
1448		}
1449
1450		dms_int_t dmstmp(dms1);
1451		check_expr(dms1 == dmstmp);
1452		dms1.insert(dms1.begin(), 101);
1453		check_expr(dms1 != dmstmp);
1454
1455		ms1.clear();
1456		dms1.clear();
1457	}
1458	dms1.clear();
1459	// db_map<>::empty
1460	check_expr(dms1.empty());
1461	fill(dms1, ms1, i = 3, n = 5);
1462	check_expr(!dms1.empty());
1463
1464	typedef set<int> ms_int_t;
1465	dms_int_t::iterator dmsi, dmsi2;
1466	ms_int_t::iterator msi;
1467	dms_int_t::reverse_iterator dmsri;
1468	ms_int_t::reverse_iterator msri;
1469
1470	// db_set<>::find, count
1471	for (dmsi = dms1.begin(), msi = ms1.begin(), i = 3; dmsi != dms1.end() &&
1472	    msi !=ms1.end(); dmsi++, msi++, i++) {
1473		// check_expr both contain
1474		check_expr(*(dms1.find(i)) == i);
1475
1476		pair<dms_int_t::iterator, dms_int_t::iterator> erp =
1477		    dms1.equal_range(i);
1478		int jc = 0;
1479		dms_int_t::iterator jj;
1480		for (jj = erp.first, jc = 0;
1481		    jj != erp.second; jj++, jc++)
1482		    check_expr((*jj) == ptint(i));
1483		check_expr(jc == 1);
1484		if (i < 7 && !dms1.is_hash()) {// 7 is last element
1485			check_expr((*(dms1.upper_bound(i))) == i + 1);
1486			check_expr((*(dms1.lower_bound(i))) == i);
1487		}
1488		else if (i == 7 && !dms1.is_hash()) {
1489			check_expr(dms1.upper_bound(i) == dms1.end());
1490			check_expr((*(dms1.lower_bound(i))) == i);
1491		} else if (!dms1.is_hash())
1492			check_expr(false);
1493
1494		check_expr(dms1.count(i) == 1);
1495		check_expr(dms1.count(-i) == 0);
1496		if (!dms1.is_hash()) {
1497			check_expr((*dmsi) == (*msi));
1498			check_expr((*dmsi) == (*msi));
1499		}
1500		if (i == 3 + n - 1) {// last element
1501			if (!dms1.is_hash())
1502				check_expr((*dmsi) == (*msi));
1503			for (; dmsi != dms1.end() && (*dmsi) == (*msi); i--) {
1504				// check_expr both contains
1505				if (!dms1.is_hash())
1506					check_expr((*dmsi) == (*msi));
1507				check_expr((*(dms1.find(i)) == i));
1508
1509				if (i % 2)
1510					dmsi--;
1511				else
1512					--dmsi;
1513				msi--;
1514			}
1515			break;
1516		}
1517
1518	}
1519	for (dmsri = dms1.rbegin(), msri = ms1.rbegin(), i = 3;
1520	    dmsri != dms1.rend() && msri != ms1.rend(); dmsri++, msri++, i++) {
1521		check_expr((*(dms1.find(i)) == i));
1522		if (!dms1.is_hash())
1523			check_expr((*dmsri) == (*msri));
1524		if (i == 3 + n - 1) {// last element
1525
1526			for (; dmsri != dms1.rend() && msri != ms1.rend(); i--) {
1527				// check_expr both contain
1528				check_expr((dms1.find(i) != dms1.end()) &&
1529				    (ms1.find(i) != ms1.end()));
1530				if (!dms1.is_hash())
1531					check_expr((*dmsri) == (*msri));
1532
1533				if (i % 2)
1534					dmsri--;
1535				else
1536					--dmsri;
1537				if (i > 3) // MS STL bug: when msri points to last element, it can not go back
1538					msri--;
1539
1540			}
1541			break;
1542		}
1543
1544	}
1545	for (dmsi = dms1.begin(), msi = ms1.begin(), i = 3; dmsi != dms1.end() &&
1546	    msi !=ms1.end(); ++dmsi, msi++)
1547		i++;
1548	check_expr(i == 3 + n);
1549
1550	for (dmsri = dms1.rbegin(), msri = ms1.rbegin(), i = 3;
1551	    dmsri != dms1.rend() && msri !=ms1.rend(); ++dmsri, msri++)
1552		i++;
1553	check_expr(i == 3 + n);
1554
1555	dms_int_t dms2(dmsdb2, penv);
1556	dms2.clear();
1557	dms2.insert(dms1.begin(), dms1.end());
1558	if (EXPLICIT_TXN)
1559		dbstl::commit_txn(penv);
1560
1561	if (!TEST_AUTOCOMMIT)
1562		dbstl::begin_txn(0, penv);
1563	dms_int_t dms3 = dms2;
1564	if (!TEST_AUTOCOMMIT)
1565		dbstl::commit_txn(penv);
1566
1567	if (EXPLICIT_TXN)
1568		dbstl::begin_txn(0, penv);
1569
1570	check_expr(dms3 == dms2);
1571	dms3 = dms1;
1572	if (!TEST_AUTOCOMMIT)
1573		dbstl::commit_txn(penv);
1574
1575	if (EXPLICIT_TXN)
1576		dbstl::begin_txn(0, penv);
1577
1578	check_expr(dms3 == dms1);
1579
1580	for (dmsi = dms1.begin(), dmsi2 = dms2.begin(); dmsi != dms1.end() &&
1581	    dmsi2 != dms2.end(); ++dmsi, dmsi2++)
1582		check_expr(*dmsi == *dmsi2);
1583
1584	/* !!!XXX
1585	set keys are not supposed to be mutated, so this is an extra functionality, just like
1586	the set iterator assignment in ms's stl library. Here we must use i < dms1.size() to
1587	limit the number of loops because after each assignment, dmsi will be positioned to
1588	the element which is immediately next to the old key it sits on before the assignment,
1589	thus it may take more loops to go to the end() position.
1590	*/
1591	pprint(dms1, "dms1 before iterator assignment : \n");
1592	dms_int_t::size_type ui;
1593	for (dmsi = dms1.begin(), ui = 0; dmsi != dms1.end() && ui < dms1.size(); dmsi++, ui++) {
1594		(*dmsi) = tpint(arr1[ui]);
1595		pprint(dms1, "\ndms1 after one element assignment : ");
1596	}
1597	if (dms1.is_hash() == false) {
1598		pprint(dms1, "dms1 after iterator assignment : \n");
1599		for (dmsi = dms1.begin(), dmsi2 = dms2.begin(), i = 0;
1600			dmsi != dms1.end() && dmsi2 != dms2.end(); dmsi++, i++, dmsi2++) {
1601			check_expr((*dmsi) == tpint(arr1[i]));
1602			*dmsi2 = *dmsi;
1603			// check_expr(*dmsi == *dmsi2); dmsi2 is invalidated by the assignment, so can't compare here.
1604		}
1605		// Compare here.
1606		for (dmsi = dms1.begin(), dmsi2 = dms2.begin(), i = 0;
1607		    dmsi != dms1.end() && dmsi2 != dms2.end(); dmsi++, i++, dmsi2++)
1608			check_expr(*dmsi2 == *dmsi);
1609	}
1610
1611	dms1.clear();
1612	//dms2.clear();
1613	fill(dms1, ms1, i = 3, n = 5);
1614	// db_set<>::insert(const value_type&). the range insert is already
1615	// tested in fill
1616	//
1617	pair<dms_int_t::iterator, bool> ress =
1618	    dms1.insert(tpint(3));
1619	check_expr((*(ress.first)) == 3 && ress.second == false);
1620
1621	// db_set<>::count, insert, erase, find
1622	check_expr(dms1.count(3) == 1);
1623	check_expr(dms1.size() == (size_t)n);// n is 5
1624	check_expr(dms1.count(9) == 0);
1625	ress = dms1.insert(tpint(9));
1626	check_expr((*(ress.first)) == 9 && ress.second == true);
1627	check_expr(dms1.count(9) == 1);
1628	check_expr(dms1.size() == (size_t)n + 1);
1629	dms1.erase(9);
1630	check_expr(dms1.size() == (size_t)n);
1631	check_expr(dms1.count(9) == 0);
1632	dms1.erase(dms1.find(3));
1633	check_expr(dms1.size() == (size_t)n - 1);
1634	check_expr(dms1.count(3) == 0);
1635	dms2.erase(dms2.begin(), dms2.end());
1636	check_expr(dms2.size() == 0);
1637	check_expr(dms2.empty());
1638
1639	dmsi = dms1.begin();
1640	dmsi++;
1641	dmsi2 = dmsi;
1642	dmsi2++;
1643	dmsi2++;
1644	dms2.insert(dmsi, dmsi2);// 2 recs inserted, [dmsi, dmsi2)
1645	check_expr(dms2.size() == 2);
1646	if (EXPLICIT_TXN)
1647		dbstl::commit_txn(penv);
1648
1649	if (!TEST_AUTOCOMMIT)
1650		dbstl::begin_txn(0, penv);
1651	dms1.swap(dms2);
1652	if (!TEST_AUTOCOMMIT)
1653		dbstl::commit_txn(penv);
1654
1655	if (EXPLICIT_TXN)
1656		dbstl::begin_txn(0, penv);
1657	size_t dms1sz, dms2sz;
1658	check_expr((dms1sz = dms1.size()) == 2 && (dms2sz = dms2.size()) == (size_t)n - 1);
1659	dms1.clear();
1660	dms2.clear();
1661	dms3.clear();
1662
1663	if (EXPLICIT_TXN)
1664		dbstl::commit_txn(penv);
1665
1666} // test_set_member_functions
1667
1668void TestAssoc::test_mset_member_functions()
1669{
1670// db_multiset<>
1671	int i;
1672	size_t sizet1;
1673
1674	if (EXPLICIT_TXN)
1675		dbstl::begin_txn(0, penv);
1676
1677	dmms_int_t dmms1(dmmsdb1, penv);
1678	multiset<int> mms1;
1679
1680	dmms1.clear();
1681	// db_multiset<>::empty
1682	check_expr(dmms1.empty());
1683	fill(dmms1, mms1, i = 3, n = 5, 4);
1684	check_expr(!dmms1.empty());
1685	dmms_int_t tmpmms0;
1686	const dmms_int_t &cnstmms = dmms1;
1687	dmms_int_t tmpmms1;
1688	tmpmms1.insert(dmms1.begin(), dmms1.end());
1689	tmpmms0.insert(cnstmms.begin(), cnstmms.end());
1690	tmpmms0.insert(tmpmms0.begin(), *(--tmpmms0.end()));
1691	check_expr(tmpmms0 != tmpmms1);
1692
1693	typedef multiset<int> mms_int_t;
1694	dmms_int_t::iterator dmmsi, dmmsi2;
1695	mms_int_t::iterator mmsi;
1696	dmms_int_t::reverse_iterator dmmsri;
1697	mms_int_t::reverse_iterator mmsri;
1698
1699	// db_multiset<>::find, count
1700	for (dmmsi = dmms1.begin(), mmsi = mms1.begin(), i = 3;
1701	    dmmsi != dmms1.end() &&
1702	    mmsi !=mms1.end(); dmmsi++, mmsi++, i++) {
1703		// check_expr both contain
1704		check_expr((*(dmms1.find(i))) == i);
1705
1706		pair<dmms_int_t::iterator, dmms_int_t::iterator> erp1 =
1707		    dmms1.equal_range(i);
1708		int jc = 0;
1709		dmms_int_t::iterator jj;
1710		for (jj = erp1.first, jc = 0;
1711		    jj != erp1.second; jj++, jc++) {
1712			// there is bug so this line can be reached
1713			if ((size_t)jc == g_count[i]) {
1714				jj == erp1.second;// cmp again to debug it
1715				dmms1.get_db_handle()->stat_print(DB_STAT_ALL);
1716			}
1717			check_expr((*jj) == ptint(i));
1718		}
1719		check_expr((size_t)jc == g_count[i]); // g_count[i] duplicates
1720		if (i < 7 && !dmms1.is_hash()) {// 7 is last element
1721			check_expr((*(dmms1.upper_bound(i))) == i + 1);
1722			check_expr((*(dmms1.lower_bound(i))) == i);
1723		}
1724		else if (i == 7 && !dmms1.is_hash()) {
1725			check_expr(dmms1.upper_bound(i) == dmms1.end());
1726			check_expr((*(dmms1.lower_bound(i))) == i);
1727		} else if (!dmms1.is_hash())
1728			check_expr(false);
1729
1730		check_expr(dmms1.count(i) == g_count[i]);
1731		check_expr(dmms1.count(-i) == 0);
1732		if (!dmms1.is_hash())
1733			check_expr((*dmmsi) == (*mmsi));
1734		if (i == 3 + n - 1) {// last element
1735
1736			for (; dmmsi != dmms1.end(); mmsi--, i--) {
1737				// check_expr both contains
1738				check_expr((*(dmms1.find(i))) == i);
1739				if (!dmms1.is_hash())
1740					check_expr((*dmmsi) == (*mmsi));
1741				if (i % 2)
1742					dmmsi--;
1743				else
1744					--dmmsi;
1745			}
1746			break;
1747		}
1748
1749	}
1750	for (dmmsri = dmms1.rbegin(), mmsri = mms1.rbegin(), i = 3;
1751	    dmmsri != dmms1.rend() && mmsri !=mms1.rend(); dmmsri++, mmsri++, i++) {
1752		check_expr((dmms1.find(i) != dmms1.end()) &&
1753		    (mms1.find(i) != mms1.end()));// check_expr both contain
1754		if (dmms1.is_hash() == false)
1755			check_expr((*dmmsri) == (*mmsri));
1756		if (i == 3 + n - 1) {// last element
1757
1758			for (; dmmsri != dmms1.rend() && mmsri != mms1.rend(); i--) {
1759				// check_expr both contain
1760				check_expr((*(dmms1.find(i))) == i);
1761				if (!dmms1.is_hash())
1762					check_expr((*dmmsri) == (*mmsri));
1763				if (i % 2)
1764					dmmsri--;
1765				else
1766					--dmmsri;
1767				if (i > 3) // MS STL bug: when msri points to last element, it can not go back
1768					mmsri--;
1769			}
1770			break;
1771		}
1772
1773	}
1774	for (dmmsi = dmms1.begin(), mmsi = mms1.begin(), i = 3;
1775	    dmmsi != dmms1.end() &&
1776	    mmsi !=mms1.end(); ++dmmsi, mmsi++)
1777		i++;
1778	check_expr((size_t)i == 3 + g_sum(3, 8));
1779	for (dmmsri = dmms1.rbegin(), mmsri = mms1.rbegin(), i = 3;
1780	    dmmsri != dmms1.rend() && mmsri !=mms1.rend(); ++dmmsri, mmsri++)
1781		i++;
1782	check_expr((size_t)i == 3 + g_sum(3, 8));
1783
1784
1785
1786
1787	dmms_int_t dmms2(dmmsdb2, penv);
1788	dmms2.clear();
1789	dmms2.insert(dmms1.begin(), dmms1.end());
1790	if (EXPLICIT_TXN)
1791		dbstl::commit_txn(penv);
1792
1793	if (!TEST_AUTOCOMMIT)
1794		dbstl::begin_txn(0, penv);
1795	dmms_int_t dmms3 = dmms2;
1796	if (!TEST_AUTOCOMMIT)
1797		dbstl::commit_txn(penv);
1798
1799	if (EXPLICIT_TXN)
1800		dbstl::begin_txn(0, penv);
1801	cout<<"\ndmms2: \n";
1802	for (dmms_int_t::iterator itr = dmms2.begin(); itr != dmms2.end(); ++itr)
1803		cout<<"\t"<<*itr;
1804	cout<<"\ndmms3: \n";
1805	for (dmms_int_t::iterator itr = dmms3.begin(); itr != dmms3.end(); ++itr)
1806		cout<<"\t"<<*itr;
1807
1808	check_expr(dmms3 == dmms2);
1809	if (EXPLICIT_TXN)
1810		dbstl::commit_txn(penv);
1811
1812	if (!TEST_AUTOCOMMIT)
1813		dbstl::begin_txn(0, penv);
1814	dmms3 = dmms1;
1815	if (!TEST_AUTOCOMMIT)
1816		dbstl::commit_txn(penv);
1817
1818	if (EXPLICIT_TXN)
1819		dbstl::begin_txn(0, penv);
1820	check_expr(dmms3 == dmms1);
1821
1822	for (dmmsi = dmms1.begin(), dmmsi2 = dmms2.begin(); dmmsi != dmms1.end() &&
1823	    dmmsi2 != dmms2.end(); ++dmmsi, dmmsi2++)
1824		check_expr(*dmmsi == *dmmsi2);
1825
1826	// content of dmms1 and dmms2 are changed since now
1827	// int arr11[] = {33, 44, 55, 66, 77};
1828
1829	// db_multiset<>::insert(const value_type&). the range insert is already
1830	// tested in fill
1831	//
1832	dmms_int_t::iterator iitrms = dmms1.insert(ptint (3));
1833	check_expr(*iitrms == 3);
1834
1835	dmms1.clear();
1836	mms1.clear();
1837	fill(dmms1, mms1, i = 3, n = 5, 4);
1838	// db_multiset<>::count, insert, erase, find
1839	check_expr(dmms1.count(3) == g_count[3]);
1840	check_expr(dmms1.size() == (sizet1 = g_sum(3, 8)));// sum of recs from 3 to 8
1841	check_expr(dmms1.count(9) == 0);
1842	dmms_int_t::iterator iitrms2 = dmms1.insert(ptint (9));
1843	check_expr(*iitrms2 == 9);
1844	check_expr(dmms1.count(9) == 1);
1845	check_expr(dmms1.size() == sizet1 + 1);
1846	dmms1.erase(9);
1847	check_expr(dmms1.size() == g_sum(3, 8));
1848	check_expr(dmms1.count(9) == 0);
1849	dmms1.erase(dmms1.find(3));
1850	check_expr(dmms1.size() == g_sum(3, 8) - 1);
1851	check_expr(dmms1.count(3) == (g_count[3] - 1 > 0 ? g_count[3] - 1 : 0));
1852	dmms2.erase(dmms2.begin(), dmms2.end());
1853	check_expr(dmms2.size() == 0);
1854	check_expr(dmms2.empty());
1855
1856	dmmsi = dmms1.begin();
1857	dmmsi++;
1858	dmmsi2 = dmmsi;
1859	dmmsi2++;
1860	dmmsi2++;
1861	dmms2.insert(dmmsi, dmmsi2);// 2 recs inserted, [dmi, dmi2)
1862	size_t sssz;
1863	check_expr((sssz = dmms2.size()) == 2);
1864	if (EXPLICIT_TXN)
1865		dbstl::commit_txn(penv);
1866
1867	if (!TEST_AUTOCOMMIT)
1868		dbstl::begin_txn(0, penv);
1869	dmms1.swap(dmms2);
1870	if (!TEST_AUTOCOMMIT)
1871		dbstl::commit_txn(penv);
1872
1873	if (EXPLICIT_TXN)
1874		dbstl::begin_txn(0, penv);
1875	size_t dmms1sz, dmms2sz;
1876	check_expr((dmms1sz = dmms1.size()) == 2 && (dmms2sz = dmms2.size()) == sizet1 - 1);
1877
1878	dmms1.clear();
1879	dmms2.clear();
1880	dmms3.clear();
1881	if (EXPLICIT_TXN)
1882		dbstl::commit_txn(penv);
1883
1884} // test_mset_member_functions
1885
1886void TestAssoc::test_char_star_string_storage()
1887{
1888	int i;
1889	// testing varying length data element storage/retrieval
1890	cout<<"\n_testing char*/wchar_t* string storage support...\n";
1891
1892	if (EXPLICIT_TXN)
1893		dbstl::begin_txn(0, penv);
1894	// Use Dbt to wrap any object and store them. This is rarely needed,
1895	// so this piece of code is only for test purpose.
1896	db_vector<DbstlDbt> strv(dbstrv, penv);
1897	vector<string> strsv;
1898	vector<DbstlDbt> strvdbts;
1899	strv.clear();
1900
1901	int strlenmax = 256, strlenmin = 64;
1902	string str;
1903	DbstlDbt dbt;
1904	rand_str_dbt rand_str_maker;
1905	dbt.set_flags(DB_DBT_USERMEM);
1906	dbt.set_data(DbstlMalloc(strlenmax + 10));
1907	dbt.set_ulen(strlenmax + 10);
1908
1909	for (int jj = 0; jj < 10; jj++) {
1910		rand_str_maker(dbt, str, strlenmin, strlenmax);
1911		strsv.push_back(str);
1912		strv.push_back(dbt);
1913	}
1914
1915	cout<<"\nstrings:\n";
1916	for (i = 0; i < 10; i++) {
1917
1918		db_vector<DbstlDbt>::value_type_wrap elemref = strv[i];
1919		strvdbts.push_back(elemref);
1920		printf("\n%s\n%s",  (char*)(strvdbts[i].get_data()), strsv[i].c_str());
1921		check_expr(strcmp((char*)(elemref.get_data()), strsv[i].c_str()) == 0);
1922		check_expr(strcmp((char*)(strvdbts[i].get_data()), strsv[i].c_str()) == 0);
1923	}
1924	strv.clear();
1925
1926	if (EXPLICIT_TXN) {
1927		dbstl::commit_txn(penv);
1928		dbstl::begin_txn(0, penv);
1929	}
1930
1931	// Use ordinary way to store strings.
1932	TCHAR cstr1[32], cstr2[32], cstr3[32];
1933	strcpy(cstr1, "abc");
1934	strcpy(cstr2, "defcd");
1935	strcpy(cstr3, "edggsefcd");
1936// = _T("abc"), *cstr2 = _T("defcd"), *cstr3 = _T("edggsefcd");
1937	typedef db_map<int, TCHAR*, ElementHolder<TCHAR*> > strmap_t;
1938	strmap_t strmap(dmdb6, penv);
1939	strmap.clear();
1940	strmap.insert(make_pair(1, cstr1));
1941	strmap.insert(make_pair(2, cstr2));
1942	strmap.insert(make_pair(3, cstr3));
1943	cout<<"\n strings in strmap:\n";
1944	for (strmap_t::const_iterator citr = strmap.begin(); citr != strmap.end(); citr++)
1945		cout<<(*citr).second<<'\t';
1946	cout<<strmap[1]<<strmap[2]<<strmap[3];
1947	TCHAR cstr4[32], cstr5[32], cstr6[32];
1948	_tcscpy(cstr4, strmap[1]);
1949	_tcscpy(cstr5, strmap[2]);
1950	_tcscpy(cstr6, strmap[3]);
1951	_tprintf(_T("%s, %s, %s"), cstr4, cstr5, cstr6);
1952	strmap_t::value_type_wrap::second_type vts = strmap[1];
1953	using_charstr(vts);
1954	vts._DB_STL_StoreElement();
1955	_tcscpy(cstr4, _T("hello world"));
1956	vts = cstr4;
1957	vts._DB_STL_StoreElement();
1958	cout<<"\n\nstrmap[1]: "<<strmap[1];
1959	check_expr(_tcscmp(strmap[1], cstr4) == 0);
1960	vts[0] = _T('H');// itis wrong to do it this way
1961	vts._DB_STL_StoreElement();
1962	check_expr(_tcscmp(strmap[1], _T("Hello world")) == 0);
1963	TCHAR *strbase = vts._DB_STL_value();
1964	strbase[6] = _T('W');
1965	vts._DB_STL_StoreElement();
1966	check_expr(_tcscmp(strmap[1], _T("Hello World")) == 0);
1967	strmap.clear();
1968
1969	typedef db_map<const char *, const char *, ElementHolder<const char *> > cstrpairs_t;
1970	cstrpairs_t strpairs(dmdb6, penv);
1971	strpairs["abc"] = "def";
1972	strpairs["ghi"] = "jkl";
1973	strpairs["mno"] = "pqrs";
1974	strpairs["tuv"] = "wxyz";
1975	cstrpairs_t::const_iterator ciitr;
1976	cstrpairs_t::iterator iitr;
1977	for (ciitr = strpairs.begin(), iitr = strpairs.begin(); iitr != strpairs.end(); ++iitr, ++ciitr) {
1978		cout<<"\n"<<iitr->first<<"\t"<<iitr->second;
1979		cout<<"\n"<<ciitr->first<<"\t"<<ciitr->second;
1980		check_expr(strcmp(ciitr->first, iitr->first) == 0 && strcmp(ciitr->second, iitr->second) == 0);
1981	}
1982
1983	typedef db_map<char *, char *, ElementHolder<char *> > strpairs_t;
1984	typedef std::map<string, string> sstrpairs_t;
1985	sstrpairs_t sstrpairs2;
1986	strpairs_t strpairs2;
1987	rand_str_dbt randstr;
1988
1989	for (i = 0; i < 100; i++) {
1990		string rdstr, rdstr2;
1991		randstr(dbt, rdstr);
1992		randstr(dbt, rdstr2);
1993		strpairs2[(char *)rdstr.c_str()] = (char *)rdstr2.c_str();
1994		sstrpairs2[rdstr] = rdstr2;
1995	}
1996	strpairs_t::iterator itr;
1997	strpairs_t::const_iterator citr;
1998
1999	for (itr = strpairs2.begin(); itr != strpairs2.end(); ++itr) {
2000		check_expr(strcmp(strpairs2[itr->first], itr->second) == 0);
2001		check_expr(string(itr->second) == sstrpairs2[string(itr->first)]);
2002		strpairs_t::value_type_wrap::second_type&secref = itr->second;
2003		std::reverse((char *)secref, (char *)secref + strlen(secref));
2004		secref._DB_STL_StoreElement();
2005		std::reverse(sstrpairs2[itr->first].begin(), sstrpairs2[itr->first].end());
2006	}
2007
2008	check_expr(strpairs2.size() == sstrpairs2.size());
2009	for (citr = strpairs2.begin(ReadModifyWriteOption::no_read_modify_write(),
2010		true, BulkRetrievalOption::bulk_retrieval()); citr != strpairs2.end(); ++citr) {
2011		check_expr(strcmp(strpairs2[citr->first], citr->second) == 0);
2012		check_expr(string(citr->second) == sstrpairs2[string(citr->first)]);
2013	}
2014
2015
2016	if (EXPLICIT_TXN)
2017		dbstl::commit_txn(penv);
2018
2019	db_vector<const char *, ElementHolder<const char *> > csvct(10);
2020	vector<const char *> scsvct(10);
2021	const char *pconststr = "abc";
2022	for (i = 0; i < 10; i++) {
2023		scsvct[i] = pconststr;
2024		csvct[i] = pconststr;
2025		csvct[i] = scsvct[i];
2026		// scsvct[i] = csvct[i]; assignment won't work because scsvct
2027		// only stores pointer but do not copy the sequence, thus it
2028		// will refer to an invalid pointer when i changes.
2029	}
2030	for (i = 0; i < 10; i++) {
2031		check_expr(strcmp(csvct[i], scsvct[i]) == 0);
2032		cout<<endl<<(const char *)(csvct[i]);
2033	}
2034
2035	db_vector<const wchar_t *, ElementHolder<const wchar_t *> > wcsvct(10);
2036	vector<const wchar_t *> wscsvct(10);
2037	const wchar_t *pconstwstr = L"abc";
2038	for (i = 0; i < 10; i++) {
2039		wscsvct[i] = pconstwstr;
2040		wcsvct[i] = pconstwstr;
2041		wcsvct[i] = wscsvct[i];
2042		// scsvct[i] = csvct[i]; assignment won't work because scsvct
2043		// only stores pointer but do not copy the sequence, thus it
2044		// will refer to an invalid pointer when i changes.
2045	}
2046	for (i = 0; i < 10; i++) {
2047		check_expr(wcscmp(wcsvct[i], wscsvct[i]) == 0);
2048
2049	}
2050
2051} // test_char_star_string_storage
2052
2053void TestAssoc::test_fixed_len_obj_storage()
2054{
2055	int i;
2056	map<int, sms_t> ssmsmap;
2057
2058	if (EXPLICIT_TXN)
2059		dbstl::begin_txn(0, penv);
2060
2061	typedef db_map<int, sms_t> smsmap_t;
2062	smsmap_t smsmap(dmdb6, penv);
2063
2064	sms_t smsmsg;
2065	time_t now;
2066	for (i = 0; i < 2008; i++) {
2067		smsmsg.from = 1000 + i;
2068		smsmsg.to = 10000 - i;
2069		smsmsg.sz = sizeof(smsmsg);
2070		time(&now);
2071		smsmsg.when = now;
2072		ssmsmap.insert(make_pair(i, smsmsg));
2073		smsmap.insert(make_pair(i, smsmsg));
2074	}
2075	smsmap.clear();
2076	if (EXPLICIT_TXN)
2077		dbstl::commit_txn(penv);
2078} //test_var_len_obj_storage
2079
2080void TestAssoc::test_arbitray_sequence_storage()
2081{
2082	int i, j;
2083
2084	if (EXPLICIT_TXN)
2085		dbstl::begin_txn(0, penv);
2086	// storing arbitary sequence test .
2087	cout<<endl<<"Testing arbitary type of sequence storage support...\n";
2088	RGBB *rgbs[10], *prgb1, *prgb2;
2089	typedef db_map<int, RGBB *, ElementHolder<RGBB *> > rgbmap_t;
2090	rgbmap_t rgbsmap(dmdb6, penv);
2091
2092	map<int, RGBB *> srgbsmap;
2093
2094	DbstlElemTraits<RGBB>::instance()->set_sequence_len_function(rgblen);
2095	DbstlElemTraits<RGBB>::instance()->set_sequence_copy_function(rgbcpy);
2096	// populate srgbsmap and rgbsmap
2097	for (i = 0; i < 10; i++) {
2098		n = abs(rand()) % 10 + 2;
2099		rgbs[i] = new RGBB[n];
2100		memset(&rgbs[i][n - 1], 0, sizeof(RGBB));//make last element 0
2101		for (j = 0; j < n - 1; j++) {
2102			rgbs[i][j].r_ = i + 128;
2103			rgbs[i][j].g_ = 256 - i;
2104			rgbs[i][j].b_ = 128 - i;
2105			rgbs[i][j].bright_ = 256 / (i + 1);
2106
2107		}
2108		rgbsmap.insert(make_pair(i, rgbs[i]));
2109		srgbsmap.insert(make_pair(i, rgbs[i]));
2110	}
2111
2112	// retrieve and assert equal, then modify and store
2113	for (i = 0; i < 10; i++) {
2114		rgbmap_t::value_type_wrap::second_type rgbelem = rgbsmap[i];
2115		prgb1 = rgbelem;
2116		check_expr(memcmp(prgb1, prgb2 = srgbsmap[i],
2117		    (n = (int)rgblen(srgbsmap[i])) * sizeof(RGBB)) == 0);
2118		for (j = 0; j < n - 1; j++) {
2119			prgb1[j].r_ = 256 - prgb1[j].r_;
2120			prgb1[j].g_ = 256 - prgb1[j].g_;
2121			prgb1[j].b_ = 256 - prgb1[j].b_;
2122			prgb2[j].r_ = 256 - prgb2[j].r_;
2123			prgb2[j].g_ = 256 - prgb2[j].g_;
2124			prgb2[j].b_ = 256 - prgb2[j].b_;
2125		}
2126		rgbelem._DB_STL_StoreElement();
2127	}
2128
2129	// retrieve again and assert equal
2130	for (i = 0; i < 10; i++) {
2131		rgbmap_t::value_type_wrap::second_type rgbelem = rgbsmap[i];
2132		prgb1 = rgbelem;// Can't use rgbsmap[i] here because container::operator[] is an temporary value.;
2133		check_expr(memcmp(prgb1, prgb2 = srgbsmap[i],
2134		    sizeof(RGBB) * rgblen(srgbsmap[i])) == 0);
2135	}
2136
2137	rgbmap_t::iterator rmitr;
2138	map<int, RGBB *>::iterator srmitr;
2139
2140	for (rmitr = rgbsmap.begin();
2141	    rmitr != rgbsmap.end(); ++rmitr) {
2142		rgbmap_t::value_type_wrap::second_type rgbelem2 = (*rmitr).second;
2143		prgb1 = (*rmitr).second;
2144		srmitr = srgbsmap.find(rmitr->first);
2145		check_expr(memcmp(prgb1, prgb2 = srmitr->second,
2146		    sizeof(RGBB) * rgblen(srmitr->second)) == 0);
2147		rmitr.refresh();
2148	}
2149
2150	for (i = 0; i < 10; i++)
2151		delete []rgbs[i];
2152	if (EXPLICIT_TXN)
2153		dbstl::commit_txn(penv);
2154} // test_arbitray_sequence_storage
2155
2156void TestAssoc::test_bulk_retrieval_read()
2157{
2158
2159	int i;
2160
2161	typedef db_map<int, sms_t> smsmap_t;
2162	smsmap_t smsmap(dmdb6, penv);
2163	map<int, sms_t> ssmsmap;
2164	if (EXPLICIT_TXN)
2165		dbstl::begin_txn(0, penv);
2166
2167	cout<<"\n_testing bulk retrieval support:\n";
2168	sms_t smsmsg;
2169	time_t now;
2170	smsmap.clear();
2171	for (i = 0; i < 2008; i++) {
2172		smsmsg.from = 1000 + i;
2173		smsmsg.to = 10000 - i;
2174		smsmsg.sz = sizeof(smsmsg);
2175		time(&now);
2176		smsmsg.when = now;
2177		ssmsmap.insert(make_pair(i, smsmsg));
2178		smsmap.insert(make_pair(i, smsmsg));
2179	}
2180
2181	// bulk retrieval test.
2182	map<int, sms_t>::iterator ssmsitr = ssmsmap.begin();
2183	i = 0;
2184	const smsmap_t &rosmsmap = smsmap;
2185	smsmap_t::const_iterator smsitr;
2186	for (smsitr = rosmsmap.begin(
2187	    BulkRetrievalOption::bulk_retrieval());
2188	    smsitr != smsmap.end(); i++) {
2189		// The order may be different, so if the two key set are
2190		// identical, it is right.
2191		check_expr((ssmsmap.count(smsitr->first) == 1));
2192		check_expr((smsitr->second == ssmsmap[smsitr->first]));
2193		if (i % 2)
2194			smsitr++;
2195		else
2196			++smsitr; // Exercise both pre/post increment.
2197		if (i % 100 == 0)
2198			smsitr.set_bulk_buffer((u_int32_t)(smsitr.get_bulk_bufsize() * 1.1));
2199	}
2200
2201	smsmap.clear();
2202	ssmsmap.clear();
2203
2204	// Using db_vector. when moving its iterator sequentially to end(),
2205	// bulk retrieval works, if moving randomly, it dose not function
2206	// for db_vector iterators. Also, note that we can create a read only
2207	// iterator when using db_vector<>::iterator rather than
2208	// db_vector<>::const_iterator.
2209	db_vector<sms_t> vctsms;
2210	db_vector<sms_t>::iterator itrv;
2211	vector<sms_t>::iterator sitrv;
2212	vector<sms_t> svctsms;
2213	for (i = 0; i < 2008; i++) {
2214		smsmsg.from = 1000 + i;
2215		smsmsg.to = 10000 - i;
2216		smsmsg.sz = sizeof(smsmsg);
2217		time(&now);
2218		smsmsg.when = now;
2219		vctsms.push_back(smsmsg);
2220		svctsms.push_back(smsmsg);
2221	}
2222
2223	for (itrv = vctsms.begin(ReadModifyWriteOption::no_read_modify_write(),
2224	    true, BulkRetrievalOption::bulk_retrieval(64 * 1024)),
2225	    sitrv = svctsms.begin(), i = 0; itrv != vctsms.end();
2226	    ++itrv, ++sitrv, ++i) {
2227		check_expr(*itrv == *sitrv);
2228		if (i % 100 == 0)
2229			itrv.set_bulk_buffer((u_int32_t)(itrv.get_bulk_bufsize() * 1.1));
2230	}
2231
2232	if (EXPLICIT_TXN)
2233		dbstl::commit_txn(penv);
2234
2235
2236} //test_bulk_retrieval_read
2237
2238void TestAssoc::test_nested_txns()
2239{
2240	int i;
2241	size_t sizet1;
2242
2243	if (!EXPLICIT_TXN)
2244		return;// nested txn tests can't be run if container not txnal
2245
2246	// nested transaction test
2247	// 1. many external txns nested, no internal txn.
2248
2249	typedef db_map<char*, char*, ElementHolder<char*> > strstrmap_t;
2250	DbTxn *txn1 = NULL, *txn2, *txn3;
2251	char kstr[10], dstr[10];
2252	std::map<int, string> kstrs;
2253	int commit_or_abort = 0;
2254	set<int> idxset;
2255	char *keystr;
2256
2257	strstrmap_t smap(dbstrmap, penv);
2258commit_abort:
2259
2260#define _DB_STL_TEST_SET_TXN_NAME(txn)	\
2261	txn->set_name(commit_or_abort == 0 ? #txn"_commit" : #txn"_abort")
2262
2263	txn1 = begin_txn(0, penv);
2264	smap.clear();
2265	//txn1->set_name(commit_or_abort == 0 ? "txn1_commit" : "txn1_abort");
2266	_DB_STL_TEST_SET_TXN_NAME(txn1);
2267	memset(kstr, 0, sizeof(kstr));
2268	memset(dstr, 0, sizeof(dstr));
2269	for (char cc = 'a'; cc <= 'z'; cc++) {
2270		_snprintf(kstr, 10, "%c%c%c", cc, cc, cc);
2271		for (int kk = 0; kk < 9; kk++)
2272			dstr[kk] = cc;
2273
2274		i = cc - 'a';
2275		kstrs.insert(make_pair(i, string(kstr)));
2276		switch (i) {
2277		case 3:
2278			txn2 = begin_txn(0, penv);// nest txn2 into txn1
2279			_DB_STL_TEST_SET_TXN_NAME(txn2);
2280			break;
2281		case 6://
2282			abort_txn(penv); // abort txn2
2283
2284			for (int kk = 3; kk < 6; kk++) {
2285				keystr = const_cast<char*>(kstrs[kk].c_str());
2286				check_expr(smap.count(keystr) == 0);
2287			}
2288
2289			txn2 = begin_txn(0, penv);// nest txn2 into txn1
2290			_DB_STL_TEST_SET_TXN_NAME(txn2);
2291			break;
2292		case 9:// 6--11: txn3 abort and txn2 commit
2293			txn3 = begin_txn(0, penv);// nest txn3 into txn2, txn2 is in txn1
2294			_DB_STL_TEST_SET_TXN_NAME(txn3);
2295			break;
2296		case 12:
2297			abort_txn(penv);// abort txn3
2298			commit_txn(penv);// commit txn2, its txn3 part is not applied
2299			for (int kk = 6; kk < 12; kk++) {
2300				keystr = const_cast<char*>(kstrs[kk].c_str());
2301				if (kk < 9)
2302					check_expr((sizet1 = smap.count(keystr)) > 0);
2303				if (kk >= 9)
2304					check_expr(smap.count(keystr) == 0);
2305			}
2306
2307			break;
2308		case 15:// 15--18: txn3 commit and txn2 abort
2309			txn2 = begin_txn(0, penv);
2310			_DB_STL_TEST_SET_TXN_NAME(txn2);
2311			break;
2312		case 17:
2313			txn3 = begin_txn(0, penv);
2314			_DB_STL_TEST_SET_TXN_NAME(txn3);
2315			break;
2316		case 19:
2317			commit_txn(penv);// commit txn3
2318			abort_txn(penv);// abort txn2;
2319			for (int kk = 15; kk < 19; kk++) {
2320				keystr = const_cast<char*>(kstrs[kk].c_str());
2321				check_expr(smap.count(keystr) == 0);
2322			}
2323			txn2 = begin_txn(0, penv);
2324			_DB_STL_TEST_SET_TXN_NAME(txn2);
2325			break;
2326		case 20:
2327			txn3 = begin_txn(0, penv);
2328			_DB_STL_TEST_SET_TXN_NAME(txn3);
2329			break;
2330		case 22:
2331	// txn3 is unresolved, after commit txn2, txn3 should have been commited
2332			commit_txn(penv, txn2);
2333			for (int kk = 19; kk < 22; kk++) {
2334				keystr = const_cast<char*>(kstrs[kk].c_str());
2335				check_expr(smap.count(keystr) > 0);
2336			}
2337			txn2 = begin_txn(0, penv);
2338			_DB_STL_TEST_SET_TXN_NAME(txn2);
2339			break;
2340		case 23:
2341			txn3 = begin_txn(0, penv);
2342			_DB_STL_TEST_SET_TXN_NAME(txn3);
2343			break;
2344		case 25:
2345	// txn3 is unresolved, after abort txn2, txn3 should have been aborted
2346			abort_txn(penv, txn2);
2347			for (int kk = 22; kk < 24; kk++) {
2348				keystr = const_cast<char*>(kstrs[kk].c_str());
2349				check_expr(smap.count(keystr) == 0);
2350			}
2351
2352			break;
2353
2354		default:
2355			break;
2356
2357		}//switch
2358
2359		smap.insert(make_pair(kstr, dstr));
2360	}// for
2361
2362	if (commit_or_abort == 0) {
2363
2364		// if txn1 commits,  0 1 2 6 7 8 12 13 14 19 20 21 25, 26
2365		idxset.insert(0);
2366		idxset.insert(1);
2367		idxset.insert(2);
2368		idxset.insert(6);
2369		idxset.insert(7);
2370		idxset.insert(8);
2371		idxset.insert(12);
2372		idxset.insert(13);
2373		idxset.insert(14);
2374		idxset.insert(19);
2375		idxset.insert(20);
2376		idxset.insert(21);
2377		idxset.insert(25);
2378
2379
2380
2381		for (int kk = 0; kk < 26; kk++) {
2382			keystr = const_cast<char*>(kstrs[kk].c_str());
2383			sizet1 = smap.count(keystr);
2384			if (idxset.count(kk) > 0) {
2385				check_expr(sizet1 > 0);
2386			} else {
2387				check_expr(sizet1 == 0);
2388			}
2389		}
2390
2391		commit_or_abort = 1;
2392		smap.clear();
2393		commit_txn(penv, txn1);
2394		goto commit_abort;
2395	}
2396
2397	if (commit_or_abort != 0){
2398		abort_txn(penv, txn1);// non could have been inserted
2399		begin_txn(0, penv);// put this call in a txnal context
2400		check_expr((sizet1 = smap.size()) == 0);
2401		commit_txn(penv);
2402	}
2403
2404	if (TEST_AUTOCOMMIT)
2405		dbstl::commit_txn(penv);
2406
2407
2408	 return;
2409} // test_nested_txns
2410
2411
2412// Testing miscellaneous functions.
2413void TestAssoc::test_etc()
2414{
2415	set_global_dbfile_suffix_number(65536);
2416	DbEnv *penvtmp = dbstl::open_env(".", 0, DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL);
2417	dbstl::close_db_env(penvtmp);
2418	db_mutex_t mtxhdl = dbstl::alloc_mutex();
2419	lock_mutex(mtxhdl);
2420	unlock_mutex(mtxhdl);
2421	free_mutex(mtxhdl);
2422
2423	try {
2424	throw_bdb_exception("test_assoc::test_etc()", DB_LOCK_DEADLOCK);
2425	} catch (DbDeadlockException e1)
2426	{}
2427
2428	try {
2429	throw_bdb_exception("test_assoc::test_etc()", DB_LOCK_NOTGRANTED);
2430	} catch (DbLockNotGrantedException e2)
2431	{}
2432
2433	try {
2434	throw_bdb_exception("test_assoc::test_etc()", DB_REP_HANDLE_DEAD);
2435	} catch (DbRepHandleDeadException e13)
2436	{}
2437
2438	try {
2439	throw_bdb_exception("test_assoc::test_etc()", DB_RUNRECOVERY);
2440	} catch (DbRunRecoveryException e4)
2441	{}
2442
2443	try {
2444	throw_bdb_exception("test_assoc::test_etc()", 12345);
2445	} catch (DbException e1)
2446	{}
2447
2448	try {
2449	throw_bdb_exception("test_assoc::test_etc()", 54321);
2450	} catch (DbException e1)
2451	{}
2452
2453	ptint_vector vctr;
2454	vctr.set_all_flags(1, 1, 1);
2455	check_expr(vctr.get_commit_flags() == 1);
2456	check_expr(vctr.get_cursor_open_flags() == 1);
2457	check_expr(vctr.get_db_open_flags() & DB_CREATE);
2458	check_expr(vctr.get_txn_begin_flags() == 1);
2459	vctr.get_db_set_flags();
2460	vctr.set_commit_flags(2);
2461	check_expr(vctr.get_commit_flags() == 2);
2462	vctr.set_cursor_open_flags(2);
2463	check_expr(vctr.get_cursor_open_flags() == 2);
2464	vctr.set_txn_begin_flags(2);
2465	check_expr(vctr.get_txn_begin_flags() == 2);
2466
2467
2468}
2469
2470
2471