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 |
Berkeley DB 4.8 with rust build script for linux.
Diffstat (limited to 'db-4.8.30/test_stl')
-rw-r--r-- | db-4.8.30/test_stl/base/ptype.h | 260 | ||||
-rw-r--r-- | db-4.8.30/test_stl/base/test.h | 470 | ||||
-rw-r--r-- | db-4.8.30/test_stl/base/test_assoc.h | 2470 | ||||
-rw-r--r-- | db-4.8.30/test_stl/base/test_dbstl.cpp | 313 | ||||
-rw-r--r-- | db-4.8.30/test_stl/base/test_mt.h | 914 | ||||
-rw-r--r-- | db-4.8.30/test_stl/base/test_util.cpp | 280 | ||||
-rw-r--r-- | db-4.8.30/test_stl/base/test_util.h | 605 | ||||
-rw-r--r-- | db-4.8.30/test_stl/base/test_vector.h | 1338 | ||||
-rw-r--r-- | db-4.8.30/test_stl/run_base.sh | 92 | ||||
-rw-r--r-- | db-4.8.30/test_stl/run_base_profile.sh | 63 | ||||
-rw-r--r-- | db-4.8.30/test_stl/run_msdbstl.sh | 77 | ||||
-rw-r--r-- | db-4.8.30/test_stl/run_stlport.sh | 24 |
12 files changed, 6906 insertions, 0 deletions
diff --git a/db-4.8.30/test_stl/base/ptype.h b/db-4.8.30/test_stl/base/ptype.h new file mode 100644 index 0000000..574f7b9 --- /dev/null +++ b/db-4.8.30/test_stl/base/ptype.h @@ -0,0 +1,260 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2009 Oracle. All rights reserved. + * + * $Id$ + */ + +#ifndef _DB_STL_PTYPE_H +#define _DB_STL_PTYPE_H + +#include "dbstl_common.h" +#include "dbstl_element_ref.h" +#include <iostream> + +using std::istream; +using std::ostream; +using namespace dbstl; +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// +// ptype class template definition +// +// ptype<> is a primitive types wrapper, must use this wrapper to +// store/retrieve primitive types to/from db via db stl interface +// +template <Typename T> +class ptype +{ +public: + T v; + ptype(){v = 0;} + ptype(T vv){v = vv;} + typedef ptype<T> tptype; + typedef db_vector_iterator<tptype> dvit; + + operator T() + { + return v; + } + + ptype(const ElementRef<ptype<T> >&rval) + { + if ( rval._DB_STL_GetData(*this) != INVALID_KEY_DATA) { + + } else { + throw new InvalidDbtException(); + } + } + + ptype(const ptype<T>&p2) + { + v = p2.v; + } + + template <Typename T2> + ptype(const ptype<T2>&p2) + { + v = p2.v; + } + template <Typename T2> + const ptype<T>& operator=(const ptype<T2>&p2) + { + v = p2.v; + return *this; + } + template <Typename T2> + const ptype<T> operator +(const ptype<T2> &p2) const + { + return ptype<T>(v + p2.v ); + } + template <Typename T2> + const ptype<T> operator -(const ptype<T2> &p2) const + { + return ptype<T>(v - p2.v ); + } + template <Typename T2> + const ptype<T> operator *(const ptype<T2> &p2) const + { + return ptype<T>(v * p2.v ); + } + template <Typename T2> + const ptype<T> operator /(const ptype<T2> &p2) const + { + return ptype<T>(v / p2.v ); + } + template <Typename T2> + const ptype<T> operator %(const ptype<T2> &p2) const + { + return ptype<T>(v % p2.v ); + } + + template <Typename T2> + const ptype<T>& operator +=(const ptype<T2> &p2) const + { + v += p2.v; + return *this; + } + + template <Typename T2> + const ptype<T>& operator -=(const ptype<T2> &p2) const + { + v -= p2.v; + return *this; + } + template <Typename T2> + const ptype<T>& operator *=(const ptype<T2> &p2) const + { + v *= p2.v; + return *this; + } + template <Typename T2> + const ptype<T>& operator /=(const ptype<T2> &p2) const + { + v /= p2.v; + return *this; + } + template <Typename T2> + const ptype<T>& operator %=(const ptype<T2> &p2) const + { + v %= p2.v; + return *this; + } + + template <Typename T2> + bool operator==(const ptype<T2>&p2) const + { + return v == p2.v; + } + template <Typename T2> + bool operator!=(const ptype<T2>&p2)const + { + return v != p2.v; + } + + template <Typename T2> + bool operator<(const ptype<T2>&p2) const + { + return v < p2.v; + } + + template <Typename T2> + bool operator>(const ptype<T2>&p2) const + { + return v > p2.v; + } + + template <Typename T2> + bool operator<=(const ptype<T2>&p2) const + { + return v <= p2.v; + } + template <Typename T2> + bool operator>=(const ptype<T2>&p2) const + { + return v >= p2.v; + } + + const ptype<T>& operator=(const ptype<T>&p2) + { + v = p2.v; + return p2; + } + + bool operator>(const ptype<T>&p2) const + { + return v > p2.v; + } + bool operator<(const ptype<T>&p2) const + { + return v < p2.v; + } + + bool operator>=(const ptype<T>&p2) const + { + return v >= p2.v; + } + bool operator<=(const ptype<T>&p2) const + { + return v <= p2.v; + } + const ptype<T> operator-() const + { + return ptype<T>(-v); + } + // althought the definitionos of following arithmetic operators are quite + // alike, we can't define them using macros, seems macro's parameter can only + // be symbols or literals, not operators + const ptype<T> operator +(const ptype<T> &p2) const + { + return ptype<T>(v + p2.v ); + } + const ptype<T> operator -(const ptype<T> &p2) const + { + return ptype<T>(v - p2.v ); + } + const ptype<T> operator *(const ptype<T> &p2) const + { + return ptype<T>(v * p2.v ); + } + const ptype<T> operator /(const ptype<T> &p2) const + { + return ptype<T>(v / p2.v ); + } + const ptype<T> operator %(const ptype<T> &p2) const + { + return ptype<T>(v % p2.v ); + } + const ptype<T>& operator %=(const ptype<T> &p2) const + { + v %= p2.v; + return *this; + } + + const ptype<T>& operator +=(const ptype<T> &p2) const + { + v += p2.v; + return *this; + } + const ptype<T>& operator -=(const ptype<T> &p2) const + { + v -= p2.v; + return *this; + } + const ptype<T>& operator /=(const ptype<T> &p2) const + { + v /= p2.v; + return *this; + } + const ptype<T>& operator *=(const ptype<T> &p2) const + { + v *= p2.v; + return *this; + } +}; // ptype + +// the following two functions help io ptype objs to/from any streams +template<Typename _CharT, Typename _Traits, Typename T> +basic_istream<_CharT,_Traits>& +operator>>( basic_istream<_CharT,_Traits> & in, ptype<T>&p) +{ + in>>p.v; + return in; +} + +template<Typename _CharT, Typename _Traits, Typename T> +basic_ostream<_CharT,_Traits>& +operator<<( basic_ostream<_CharT,_Traits> & out, const ptype<T>&p) +{ + out<<p.v; + return out; +} + +template <Typename T> +T operator * (T t, const ptype<T> &pt) +{ + return t * pt.v; +} + +#endif // !_DB_STL_PTYPE_H diff --git a/db-4.8.30/test_stl/base/test.h b/db-4.8.30/test_stl/base/test.h new file mode 100644 index 0000000..f5ad545 --- /dev/null +++ b/db-4.8.30/test_stl/base/test.h @@ -0,0 +1,470 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2009 Oracle. All rights reserved. + * + * $Id$ + */ + +#ifndef _DB_STL_TEST_H__ +#define _DB_STL_TEST_H__ + +#include <time.h> + +#include <utility> +#include <functional> +#include <algorithm> +#include <iostream> +#include <vector> +#include <list> +#include <queue> +#include <stack> +#include <fstream> +#include <map> +#include <set> +#include <string> + +#include "db_config.h" +#include "db_int.h" + +#define DB_STL_HAVE_DB_TIMESPEC 1 +#include "dbstl_map.h" +#include "dbstl_set.h" +#include "dbstl_vector.h" + +#include "ptype.h" + +using namespace std; +using namespace dbstl; + +///////////////////////////////////////////////////////////////////////// +///////////////////////// Macro and typedef definitions /////////// + +#define check_expr(expression) do { \ + if (!(expression)) { \ + FailedAssertionException ex(__FILE__, __LINE__, #expression);\ + throw ex; } } while (0) + +#define TEST_PRIMITIVE +#ifndef TEST_PRIMITIVE +typedef ptype<int> ptint; +typedef db_vector<ptint> intvec_t; +typedef db_vector<ptint> ptint_vector; +typedef db_map<ptint, ptint> dm_int_t; +typedef db_multimap<ptint, ptint> dmm_int_t; +typedef db_set<ptint> dms_int_t; +typedef db_multiset<ptint> dmms_int_t; +#define TOINT +#else +#define ptint int +#define TOINT (int) +typedef db_vector<ptint, ElementHolder<ptint> > intvec_t; +typedef db_vector<ptint, ElementHolder<ptint> > ptint_vector; +typedef db_map<ptint, ptint, ElementHolder<ptint> > dm_int_t; +typedef db_multimap<ptint, ptint, ElementHolder<ptint> > dmm_int_t; +typedef db_set<ptint, ElementHolder<ptint> > dms_int_t; +typedef db_multiset<ptint, ElementHolder<ptint> > dmms_int_t; +#endif + +#define DELDB(pdb) if (pdb){delete pdb; pdb = NULL;} +#define print_mm(dmm1, dmmi) \ +for (dmmi = dmm1.begin(); dmmi != dmm1.end(); dmmi++) \ + cout<<dmmi->first<<'\t'<<dmmi->second; + +// Portable thread functions, supporting Win32 and pthread libraries +// These functions are used by the multi-threaded test. +#if defined(DB_WIN32) || defined(WIN32) + +extern "C" { +extern int getopt(int, char * const *, const char *); +extern char *optarg; +extern int optind; +} + +typedef HANDLE os_pid_t; +typedef HANDLE os_thread_t; + +#define os_thread_create(thrp, attr, func, arg) \ + (((*(thrp) = CreateThread(NULL, 0, \ + (LPTHREAD_START_ROUTINE)(func), (arg), 0, NULL)) == NULL) ? -1 : 0) +#define os_thread_join(thr, statusp) \ + ((WaitForSingleObject((thr), INFINITE) == WAIT_OBJECT_0) && \ + GetExitCodeThread((thr), (LPDWORD)(statusp)) ? 0 : -1) +#define os_thread_self() GetCurrentThreadId() +#else /* !DB_WIN32 */ + +#include <sys/wait.h> +#include <pthread.h> + +typedef pid_t os_pid_t; +typedef pthread_t os_thread_t; + +#define os_thread_create(thrp, attr, func, arg) \ + pthread_create((thrp), (attr), (func), (arg)) +#define os_thread_join(thr, statusp) pthread_join((thr), (statusp)) +#define os_thread_self() pthread_self() +#endif /* !DB_WIN32 */ + +//////////////////////////////////////////////////////////////////////////// +///////////////////// Global variable declarations //////////////////////// +/*extern DbEnv *penv; +extern Db *db, *db2, *db3, *dmdb1, *dmdb2, *dmmdb1, *dmmdb2, *dmsdb1, + *dmsdb2, *dmmsdb1, *dmmsdb2, *dbstrv; +*/ +extern int g_StopInsert; +extern ofstream fout; +extern size_t g_count[256]; +extern char *optarg; +extern int g_test_start_txn; +extern DbEnv *g_env; +extern int optind; +/////////////////////////////////////////////////////////////////////// +//////////////////////// Function Declarations //////////////////// +// XXX!!! Function templates can't be declared here otherwise the declarations +// here will be deemed as the definition, so at link time these symbols are +// not resolved. So like class templates, function templates can't be separated +// as declarations and definitions, only definitions and only be built into one +// object file otherwise there will be "multiple symbol definitions". OTOH, compilers +// can avoid the multiple definitions if we are building a class template instantiation +// in multiple object files, so class tempaltes are recommended to use rather than +// function templates. Only use function templates if it is a simple one and used +// only in one code file. +// +size_t g_sum(size_t s, size_t e); +bool is_odd(ptint s); +ptint addup(const ptint&i, const ptint&j); +ptint randint(); +int randpos(int p); +bool is2digits(ptint i); +int rmdir_rcsv(const char *dir, bool keep_this_dir); +bool strlt(const string&, const string&); +bool strlt0(const char *s1, const char *s2); +bool streq0(const char *s1, const char *s2); +bool streq(const string&, const string&); + +int get_dest_secdb_callback(Db *secondary, const Dbt *key, + const Dbt *data, Dbt *result); +void copy_array(TCHAR**arr, TCHAR***dest); +void using_charstr(TCHAR*str); +void usage(); +int test_assoc(void* param1); +int test_vector(void* param1); + +class RGBB; +class SMSMsg2; +void SMSMsgRestore(SMSMsg2& dest, const void *srcdata); +u_int32_t SMSMsgSize(const SMSMsg2& elem); +void SMSMsgCopy(void *dest, const SMSMsg2&elem); +typedef bool (*ptintless_ft)(const ptint& a, const ptint& b); +bool ptintless(const ptint& a, const ptint& b); +u_int32_t rgblen(const RGBB * seq); +void rgbcpy(RGBB *seq, const RGBB *, size_t); + + +///////////////////////////////////////////////////////////////////////////////// +////////////////////////// Utility class definitions /////////////////////////// + +class BaseMsg +{ +public: + time_t when; + int to; + int from; + + BaseMsg() + { + to = from = 0; + when = 0; + } + + BaseMsg(const BaseMsg& msg) + { + to = msg.to; + from = msg.from; + when = msg.when; + } + + bool operator==(const BaseMsg& msg2) const + { + return when == msg2.when && to == msg2.to && from == msg2.from; + } + + bool operator<(const BaseMsg& msg2) const + { + return to < msg2.to; + } +}; + +// used to test arbitary obj storage(not in one chunk) +class SMSMsg2 : public BaseMsg +{ +public: + typedef SMSMsg2 self; + SMSMsg2(time_t tm, const char *msgp, int t) + { + memset(this, 0, sizeof(*this)); + when = tm; + szmsg = strlen(msgp) + 1; + msg = (char *)DbstlMalloc(szmsg); + strncpy(msg, msgp, szmsg); + to = t; + + mysize = sizeof(*this); //+ szmsg; + } + + SMSMsg2() + { + memset(this, 0, sizeof(SMSMsg2)); + } + + SMSMsg2(const self& obj) : BaseMsg(obj) + { + mysize = obj.mysize; + szmsg = obj.szmsg; + if (szmsg > 0 && obj.msg != NULL) { + msg = (char *)DbstlMalloc(szmsg); + strncpy(msg, obj.msg, szmsg); + } else + msg = NULL; + } + + ~SMSMsg2() + { + if (msg) + free(msg); + } + + const self& operator = (const self &obj) + { + + this->from = obj.from; + to = obj.to; + when = obj.when; + mysize = obj.mysize; + szmsg = obj.szmsg; + if (szmsg > 0 && obj.msg != NULL) { + msg = (char *)DbstlReAlloc(msg, szmsg); + strncpy(msg, obj.msg, szmsg); + } + return obj; + } + + bool operator == (const self&obj) const + { + return BaseMsg::operator==(obj) && strcmp(obj.msg, msg) == 0; + } + + const static size_t BUFLEN = 256; + size_t mysize; + size_t szmsg; + char *msg; + +};//SMSMsg2 + +// SMS message class +class SMSMsg : public BaseMsg +{ + + +public: + + size_t mysize; + size_t szmsg; + char msg[1]; + static SMSMsg* make_sms_msg(time_t t, const char*msg, int dest) + { + size_t mlen = 0, totalsz = 0; + + SMSMsg *p = (SMSMsg *)DbstlMalloc(totalsz = (sizeof(SMSMsg) + (mlen = strlen(msg) + 4))); + memset(p, 0, totalsz); + // adding sizeof(p->to) to avoid memory alignment issues + p->mysize = sizeof(SMSMsg) + mlen; + p->when = t; + p->szmsg = mlen - 3; + p->to = dest; + p->from = 0; + strcpy(&(p->msg[0]), msg); + + return p; + } + + SMSMsg() + { + + } +protected: + SMSMsg(time_t t, const char*msg1, int dest) + { + size_t mlen = 0; + + when = t; + szmsg = strlen(msg1) + 1; + mlen = strlen(msg1); + strncpy((char*)&(this->msg[0]), msg1, mlen); + *(int*)(((char*)&(this->msg[0])) + mlen + 1) = dest; + } + +};// SMSMsg + +class RGBB +{ +public: + typedef unsigned char color_t; + + color_t r_, g_, b_, bright_; + + RGBB() + { + memset(this, 0, sizeof(RGBB));// complete 0 means invalid + } + + RGBB(color_t r, color_t g, color_t b, color_t brightness) + { + r_ = r; + g_ = g; + b_ = b; + bright_ = brightness; + } + +};// RGBB + +template <Typename T> +class separator +{ +public: + T mid; + bool operator()(const T& ele) + { + return ele < mid; + } +}; + + +class square +{ +public: + void operator()(ptint s) + { + cout<<s*s<<'\t'; + } +}; + + +class rand_str_dbt +{ +public: + static const size_t BUFLEN = 2048; + static bool init; + static char buf[BUFLEN]; + + rand_str_dbt() + { + int len = BUFLEN, i; + + if (!init) { + init = true; + + for (i = 0; i < len - 1; i++) { + buf[i] = 'a' + rand() % 26; + } + buf[i] = '\0'; + } + } + // dbt is of DB_DBT_USERMEM, mem allocated by DbstlMalloc + void operator()(Dbt&dbt, string&str, size_t shortest = 30, size_t longest = 150) + { + int rd = rand(); + + if (rd < 0) + rd = -rd; + str.clear(); + + check_expr(shortest > 0 && longest < BUFLEN); + check_expr(dbt.get_flags() & DB_DBT_USERMEM);// USER PROVIDE MEM + size_t len = (u_int32_t)(rd % longest); + if (len < shortest) + len = shortest; + else if (len >= BUFLEN) + len = BUFLEN - 1; + // start must be less than BUFLEN - len, otherwise we have no + // len bytes to offer + size_t start = rand() % (BUFLEN - len); + + char c = buf[start + len]; + + buf[start + len] = '\0'; + str = buf + start; + if (dbt.get_ulen() < (len + 1)) { + free(dbt.get_data()); + dbt.set_data(DbstlMalloc(len + 1)); + check_expr(dbt.get_data() != NULL); + } + memcpy(dbt.get_data(), (void*)(buf + start), len + 1); + dbt.set_size(u_int32_t(len + 1));// store the '\0' at the end + buf[start + len] = c; + } +}; // rand_str_dbt + +class rand_str_dbt; +struct TestParam{ + int flags, setflags, TEST_AUTOCOMMIT, dboflags, EXPLICIT_TXN; + DBTYPE dbtype; + DbEnv *dbenv; +}; + +class test_block +{ +private: + db_timespec tp; +public: + string blkname; + + void begin(const char* name) + { + + blkname = name; + cout<<endl<<"============= start of test "<< + name<<" =============="; + __os_gettime(NULL, &tp, 1); + } + void end() + { + db_timespec tp2; + __os_gettime(NULL, &tp2, 1); + + cout<<"\n============ end of test "<<blkname<<" , time spent: " + <<tp2.tv_sec - tp.tv_sec + (tp2.tv_nsec - + tp.tv_nsec) / 1000000000.0<<" secs ============="; + } +}; + +// a mobile phone SMS structure for test. will add more members in future +class sms_t +{ +public: + size_t sz; + time_t when; + int from; + int to; + char msg[512]; + + const sms_t& operator=(const sms_t&me) + { + memcpy(this, &me, sizeof(*this)); + return me; + } + + bool operator==(const sms_t& me) const + { + return memcmp(this, &me, sizeof(me)) == 0; + } + bool operator!=(const sms_t& me) + { + return memcmp(this, &me, sizeof(me)) != 0; + } +}; + +enum wt_job {wt_read, wt_insert, wt_update, wt_delete}; +enum ContainerType {ct_vector, ct_map, ct_multimap, ct_set, ct_multiset, ct_none}; + +#endif // ! _DB_STL_TEST_H__ 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); + + +} + + diff --git a/db-4.8.30/test_stl/base/test_dbstl.cpp b/db-4.8.30/test_stl/base/test_dbstl.cpp new file mode 100644 index 0000000..0a75c72 --- /dev/null +++ b/db-4.8.30/test_stl/base/test_dbstl.cpp @@ -0,0 +1,313 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2009 Oracle. All rights reserved. + * + * $Id$ + */ + +// test_dbstl.cpp : A test program which tests all container's all methods, +// by verify the result is identical to expected value, or by doing paralell +// operations with corresponding container of STL and verify the result of +// both containers are identical after the same operations. Also, it tests +// multithreaded test +// +#include "db_config.h" +#include "db_int.h" + +#include "test.h" +#include "test_util.h" +#include "test_vector.h" +#include "test_assoc.h" +#include "test_mt.h" + +int main(int argc, char *argv[]) +{ + int c, i, j, ret; + int nreader = 5, nwriter = 3; + char *mode = NULL; + int flags = DB_THREAD, setflags = 0, EXPLICIT_TXN = 0; + int TEST_AUTOCOMMIT = 1, totalinsert = 100, verbose = 0; + DBTYPE dbtype = DB_BTREE; + int gi, shortest = 50, longest = 200, loop_count = 1; + bool multionly = false; + u_int32_t sflags = 0, oflags = 0; + u_int32_t cachesize = 8 * 1024 * 1024; + db_threadid_t tid; + string contname; + DbEnv *penv = NULL; + Db *dbstrv = NULL; + __os_id(0, 0, &tid); + + TestParam *ptp = new TestParam; + ContainerType contypes[] = { + ct_vector, + ct_map, + ct_multimap, + ct_set, + ct_multiset, + ct_none + }; + + while ((c = getopt(argc, argv, "MT:c:hk:l:m:n:r:s:t:vw:")) != EOF) { + switch (c) { + case 'M': + multionly = true; + break; + case 'T': + totalinsert = atoi(optarg); + break; + case 'c': + cachesize = atoi(optarg); + break; + case 'h': + usage(); + return 0; + break; + case 'k': + shortest = atoi(optarg); + break; + case 'l': + longest = atoi(optarg); + break; + case 'm': + mode = optarg; + break; + case 'n': + loop_count = atoi(optarg); + break; + case 'r': + nreader = atoi(optarg); + break; + case 's': // db type for associative containers + if (*optarg == 'h') // hash db type + dbtype = DB_HASH; + else if (*optarg == 'b') + dbtype = DB_BTREE; + else + usage(); + break; + case 't': + EXPLICIT_TXN = 1; + if (*optarg == 'a') + setflags = DB_AUTO_COMMIT; + else if (*optarg == 'e') // explicit txn + TEST_AUTOCOMMIT = 0; + else + usage(); + break; + case 'v': + verbose = 1; + break; + case 'w': + nwriter = atoi(optarg); + break; + default: + usage(); + break; + } + } + + if (nwriter < 3) + nwriter = 3; + + if (mode == NULL) + flags |= 0; + else if (*mode == 'c') //cds + flags |= DB_INIT_CDB; + else if (*mode == 't') + flags |= DB_INIT_TXN | DB_RECOVER + | DB_INIT_LOG | DB_INIT_LOCK; + else + flags |= 0; + g_test_start_txn = TEST_AUTOCOMMIT * EXPLICIT_TXN; + ptp->EXPLICIT_TXN = EXPLICIT_TXN; + ptp->flags = flags; + ptp->dbtype = dbtype; + ptp->setflags = setflags; + ptp->TEST_AUTOCOMMIT = TEST_AUTOCOMMIT; + ptp->dboflags = DB_THREAD; + + // This may fail because there is already dbenv. + __os_mkdir(NULL, "dbenv", 0777); + if (!multionly){ + if (loop_count <= 0) + loop_count = 1; + dbstl_startup(); + for (; loop_count > 0; loop_count--){ + rmdir_rcsv("dbenv", true); + BDBOP(__os_mkdir(NULL, "dbenv/data", 0777), ret);// This should not fail. + penv = new DbEnv(DB_CXX_NO_EXCEPTIONS); + BDBOP(penv->set_flags(setflags, 1), ret); + BDBOP(penv->set_cachesize(0, cachesize, 1), ret); + BDBOP(penv->set_data_dir("data"), ret); + + // Methods of containers returning a reference costs + // locker/object/lock slots. + penv->set_lk_max_lockers(10000); + penv->set_lk_max_objects(10000); + penv->set_lk_max_locks(10000); + + penv->set_flags(DB_TXN_NOSYNC, 1); + penv->log_set_config(DB_LOG_IN_MEMORY, 1); + penv->set_lg_bsize(128 * 1024 * 1024); + + BDBOP(penv->open("dbenv", flags | DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0777), ret); + register_db_env(penv); + // CDS dose not need deadlock detection + if (penv->get_open_flags(&oflags) == 0 && ((oflags & DB_INIT_TXN) != 0)) { + penv->set_lk_detect(DB_LOCK_RANDOM); + penv->set_timeout(1000000, DB_SET_LOCK_TIMEOUT); + + } + + ptp->dbenv = penv; + g_env = penv; + TestVector testvector(ptp); + testvector.start_test(); + TestAssoc testassoc(ptp); + testassoc.start_test(); + + close_all_dbs(); + //close_db_env(penv); + close_all_db_envs(); + cerr<<"\n\nOne round of dbstl test is run to completion successfully!\n\n"; + } + } + else { + dbstl_startup(); + rmdir_rcsv("dbenv", true); + BDBOP(__os_mkdir(NULL, "dbenv/data", 0777), ret);// This should not fail. + penv = new DbEnv(DB_CXX_NO_EXCEPTIONS); + BDBOP(penv->set_flags(setflags, 1), ret); + BDBOP(penv->set_cachesize(0, cachesize, 1), ret); + BDBOP(penv->set_data_dir("data"), ret); + + // Multi-CPU machines requires larger lockers/locks/objects because of + // the higher concurrency, more iterators can be opened at the same time. + // This setting was required by the stahp05 8-cpu machine, not others. + BDBOP(penv->set_lk_max_lockers(100000), ret); + BDBOP(penv->set_lk_max_locks(100000), ret); + BDBOP(penv->set_lk_max_objects(100000), ret); + + penv->set_flags(DB_TXN_NOSYNC, 1); + penv->log_set_config(DB_LOG_IN_MEMORY, 1); + penv->set_lg_bsize(128 * 1024 * 1024); + + BDBOP(penv->open("dbenv", flags | DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0777), ret); + register_db_env(penv); + // CDS dose not need deadlock detection + if (penv->get_open_flags(&oflags) == 0 && ((oflags & DB_INIT_TXN) != 0)) { + penv->set_lk_detect(DB_LOCK_RANDOM); + penv->set_timeout(1000000, DB_SET_LOCK_TIMEOUT); + } + + ptp->dbenv = penv; + g_env = penv; + + ThreadMgr thrds, insthrds; + vector<wt_job> jobs; + jobs.push_back(wt_insert); + jobs.push_back(wt_update); + jobs.push_back(wt_delete); + srand ((unsigned int)tid); + + for (i = 3; i < nwriter; i++) { + j = rand() % 3; + switch (j) { + case 0: jobs.push_back(wt_insert); break; + case 1: jobs.push_back(wt_update); break; + case 2: jobs.push_back(wt_delete); break; + } + } + + vector<WorkerThread *> vctthrds; + WorkerThread *pwthrd; + for (gi = 0; contypes[gi] != ct_none; gi++) { + + switch (contypes[gi]) { + case ct_vector: contname = "db_vector"; break; + case ct_map: contname = "db_map"; break; + case ct_multimap: contname = "db_multimap"; break; + case ct_set: contname = "db_set"; break; + case ct_multiset: contname = "db_multiset"; break; + default: throw "unexpected container type!"; break; + } + cout<<endl<<contname<<" multi-threaded tests:\n"; + + g_StopInsert = 0; + WorkerThread par; + memset(&par, 0, sizeof(par)); + par.total_insert = totalinsert; + par.verbose = verbose != 0; + par.strlenmax = longest; + par.strlenmin = shortest; + par.cntnr_type = contypes[gi]; + par.penv = penv; + if (par.cntnr_type != ct_vector) { + if (par.cntnr_type == ct_map || + par.cntnr_type == ct_set) + sflags = 0; + else if (par.cntnr_type == ct_multimap || + par.cntnr_type == ct_multiset) + sflags = DB_DUP; + par.pdb = dbstl:: + open_db(penv, "db_mt_map.db", + ptp->dbtype, DB_CREATE | ptp->dboflags, sflags); + } else if (par.cntnr_type == ct_vector) { + if (NULL == dbstrv) + dbstrv = dbstl::open_db(penv, "dbstr.db", + DB_RECNO, DB_CREATE | ptp->dboflags, DB_RENUMBER); + par.pdb = dbstrv; + } + + par.txnal = ptp->EXPLICIT_TXN != 0; + for (j = 0; j < nwriter; j++) { + par.job = jobs[j]; + pwthrd = new WorkerThread(par); + if (par.job == wt_insert) { + insthrds.create_thread(pwthrd); + } else { + thrds.create_thread(pwthrd); + } + + vctthrds.push_back(pwthrd); + if (j == 0) + __os_yield(NULL, 3, 0);// sleep 3 secs + } + + par.job = wt_read; + for (i = 0; i < nreader; i++) { + pwthrd = new WorkerThread(par); + thrds.create_thread(pwthrd); + vctthrds.push_back(pwthrd); + } + + thrds.join_all(); + + g_StopInsert = 1; + insthrds.join_all(); + for (vector<WorkerThread *>::size_type ui = 0; ui < vctthrds.size(); ui++) + delete vctthrds[ui]; + vctthrds.clear(); + if (ptp->EXPLICIT_TXN && !TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + dbstl::close_db(par.pdb); + penv->dbremove(dbstl::current_txn(penv), "db_mt_map.db", NULL, 0); + if (ptp->EXPLICIT_TXN && !TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + thrds.clear(); + insthrds.clear(); + cout.flush(); + + } // for (int gi + + + } // else + + delete ptp; + dbstl_exit(); + + if (penv) + delete penv; +} diff --git a/db-4.8.30/test_stl/base/test_mt.h b/db-4.8.30/test_stl/base/test_mt.h new file mode 100644 index 0000000..ae4794b --- /dev/null +++ b/db-4.8.30/test_stl/base/test_mt.h @@ -0,0 +1,914 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2009 Oracle. All rights reserved. + * + * $Id$ + */ + +#include "test.h" + +// tests containers in multiple threads, this thread class +// runs the thread function in specified manner---manipulating +// a specified type of container, with some thread inserting, +// updating, and deleting, some others reading specified amount +// of key/data pairs. +// +class WorkerThread +{ +public: + bool txnal/* if true, will create txn */, verbose; + wt_job job; + ContainerType cntnr_type; + int total_insert; + int strlenmin, strlenmax; + rand_str_dbt rand_str_maker; + Db *pdb; + DbEnv *penv; + + WorkerThread() + { + pdb = NULL; + penv = NULL; + + } + + WorkerThread(const WorkerThread& wt) + { + memcpy(this, &wt, sizeof(wt)); + } + + void run() + { + WorkerThread *p = this; + db_threadid_t tid; + int cnt = 0, i, total = total_insert, ndx; + DbstlDbt dbt, dbt2; + string str, str2; + bool iscds = false; + u_int32_t oflags; + size_t dlcnt = 0; + + + dbt.set_flags(DB_DBT_USERMEM); + dbt.set_data(DbstlMalloc(strlenmax + 10)); + dbt.set_ulen(strlenmax + 10); + dbt2.set_flags(DB_DBT_USERMEM); + dbt2.set_data(DbstlMalloc(strlenmax + 10)); + dbt2.set_ulen(strlenmax + 10); + + penv->get_open_flags(&oflags); + if (oflags & DB_INIT_CDB) + iscds = true; + __os_id(NULL, 0, &tid); + dbstl::register_db(p->pdb); + dbstl::register_db_env(penv); + if (p->cntnr_type == ct_vector) { + typedef db_vector<DbstlDbt> container_t; + container_t vi(p->pdb, penv); + const container_t& vi0 = vi; + srand((unsigned int)tid); + switch (p->job) { + case wt_read: { + + while (cnt < total - 1) { + cnt = 0; + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (container_t::const_iterator itr = vi0.begin(); itr != vi0.end() && cnt < total - 1; + itr++, cnt++) { + str = (char*)((*itr).get_data()); + if (verbose) + cout<<"\n [ "<<cnt<<" ] tid: "<<tid<<"\t [ "<< itr.get_current_index()<<" ] = "<<str.c_str(); + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 1, 0); // sleep 1 sec + } + if (iscds) // The update and delete thread will block until insert thread exits in cds mode + g_StopInsert = 1; + cout<<"\nthread "<<tid<<" got enough key/data pairs now, exiting, dead lock count = "<<dlcnt; + break; + } // case wt_job: + + case wt_insert: {// writer + + for (i = 0; g_StopInsert == 0; i++) { + rand_str_maker(dbt, str, strlenmin, strlenmax); + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + vi.push_back(dbt); + if (p->txnal) + dbstl::commit_txn(penv); + if (verbose) + cout<<endl<<"[ "<<i<<" ] thread "<<tid<<" put a string "<<str.c_str(); + } catch (DbException e) { + i--; + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + } + cout<<"\n[ "<<tid<<" ] writer OK, exiting... dead lock count = "<<dlcnt; + + break; + + } // case wt_insert + + case wt_delete: { + i = 0; // ADDITIVE, do total * 0.3 times of successful deletes, not necessarily delete so many recs because some ops may be aborted + while ( i < total * 0.1) { + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + while (i < total * 0.1) { + container_t::iterator itr = vi.begin(); + itr += (ndx = rand() % total); + if (itr != vi.end()) { + + vi.erase(itr); + i++; + if (verbose) + cout<<endl<<"vector element deleted: "<<itr.get_current_index()<<" : "<<(char*)(itr->get_data()); + } else { + if (vi.size() == 0) + return; + __os_yield(NULL, 0, 500000); + } + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + } + cout<<"\n[ "<<tid<<" ] deleter OK, exiting... dead lock count = "<<dlcnt; + break; + + }// case wt_delete + + case wt_update: { + rand_str_maker(dbt, str, strlenmin, strlenmax); + i = 0;// ADDITIVE + + while ( i < total * 0.5) { + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + while (i < total * 0.5) { + container_t::iterator itr = vi.begin(); + itr += (ndx = rand() % total); + if (itr != vi.end()) { + if (verbose) + cout<<endl<<"vector element updated: "<<itr.get_current_index()<<" updated: "<<(char*)(itr->get_data())<<" ===> "; + *itr = dbt; + i++; + if (verbose) + cout<<(char*)dbt.get_data(); + } else { + if (vi.size() == 0) + return; + __os_yield(NULL, 0, 500000); + } + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + } + cout<<"\n[ "<<tid<<" ] updater OK, exiting... dead lock count = "<<dlcnt; + break; + }; // case wt_update + + } // switch (p->job) + } // fi + if (p->cntnr_type == ct_map) { + typedef db_map<ptint , DbstlDbt> container_t; + container_t vi(p->pdb, penv); + const container_t& vi0 = vi; + container_t::iterator itr; + pair<container_t::iterator, bool> insret; + switch (p->job) { + case wt_read: + { + while (cnt < total - 1) { + cnt = 0; + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (container_t::const_iterator itrc = vi0.begin(); itrc != vi0.end(); + itrc++, cnt++) { + //str = (char*)((*itrc).first.get_data()); + str2 = (char*)((*itrc).second.get_data()); + if (verbose) + cout<<"\n [ "<<cnt<<" ] tid: "<<tid<<'\t'<<itrc->first<<"--> "<<str2.c_str(); + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 1, 0); // sleep 1 sec + } + if (iscds) // The update and delete thread will block until insert thread exits in cds mode + g_StopInsert = 1; + cout<<"\nthread "<<tid<<" got enough key/data pairs now, exiting... dead lock count = "<<dlcnt; + break; + } + case wt_insert: + {// writer + +tag6: for (i = 0; g_StopInsert == 0; i++) { + //rand_str_maker(dbt, str); + rand_str_maker(dbt2, str2, strlenmin, strlenmax); + if (i % 100 == 0) + __os_yield(NULL, 0, 0); // yield cpu + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + insret = vi.insert(make_pair(i, dbt2)); + //if (insret.second == false) // fail to insert + // i--; + if (p->txnal) + dbstl::commit_txn(penv); + if (verbose) + cout<<endl<<"[ "<<i<<" ] thread "<<tid<<" put a string "<<str.c_str()<<" --> "<<str2.c_str(); + } catch (DbException e) { + i--; + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + goto tag6; // continue; + } + + } + cout<<"\n [ "<<tid<<" ] writer thread finishes writing, exiting... dead lock count = "<<dlcnt; + break; + } //case wt_insert: + + case wt_delete: + { + i = 0;// ADDITIVE + while (i < total * 0.1) { + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (; i < total * 0.1;) { + itr = vi.begin(); + itr.move_to((ndx = rand() % total)); + if (itr != vi.end()) { + vi.erase(itr); + i++; + if (verbose) + cout<<endl<<"map k/d deleted: "<<itr->first<<" : "<<(char*)(itr->second.get_data()); + } else { + if (vi.size() == 0) + return; + __os_yield(NULL, 0, 500000); + } + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 0, 500000); + } + cout<<"\n[ "<<tid<<" ] deleter OK, exiting... dead lock count = "<<dlcnt; + break; + + }// case wt_delete + + case wt_update: + { + rand_str_maker(dbt, str, strlenmin, strlenmax); + i = 0; + while ( i < total * 0.5) { + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (i = 0; i < total * 0.5;) {// REAL DELETE: really update total * 0.5 number of recs from db + itr = vi.begin(); + itr.move_to(ndx = rand() % total); + if (itr != vi.end()) { + if (verbose) + cout<<endl<<"map key = "<<itr->first<<" updated: "<<(char*)(itr->second.get_data())<<" ===> "; + itr->second = dbt; + i++; + if (verbose) + cout<<(char*)dbt.get_data(); + } else { + if (vi.size() == 0) + return; + __os_yield(NULL, 0, 500000); + } + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 0, 500000); + } + cout<<"\n[ "<<tid<<" ] updater OK, exiting... dead lock count = "<<dlcnt; + break; + }; // case wt_update + } //switch (p->job) + + } + + if (p->cntnr_type == ct_multimap) { + typedef db_multimap<ptint , DbstlDbt> container_t; + container_t vi(p->pdb, penv); + const container_t& vi0 = vi; + + switch (p->job) { + case wt_read: + { + + while (cnt < total - 1) { + cnt = 0; + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (container_t::const_iterator itrc = vi0.begin(); itrc != vi0.end(); + itrc++, cnt++) { + //str = (char*)((*itrc).first.get_data()); + str2 = (char*)((*itrc).second.get_data()); + if (verbose) + cout<<"\n [ "<<cnt<<" ] tid: "<<tid<<'\t'<<itrc->first<<"--> "<<str2.c_str(); + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 1, 0); // sleep 1 sec + } + if (iscds) // The update and delete thread will block until insert thread exits in cds mode + g_StopInsert = 1; + cout<<"\nthread "<<tid<<" got enough key/data pairs now, exiting... dead lock count = "<<dlcnt; + break; + } //case wt_read: + + case wt_insert: + {// writer + srand ((unsigned int)tid); + int j, dupcnt; + for (i = 0; g_StopInsert == 0; i += dupcnt) { + //rand_str_maker(dbt, str); + for (j = 0, dupcnt = (rand() % 5); j < dupcnt; j++) { + + rand_str_maker(dbt2, str2, strlenmin, strlenmax); + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + vi.insert(make_pair(i, dbt2)); + if (p->txnal) + dbstl::commit_txn(penv); + if (verbose) + cout<<endl<<"[ "<<i<<" ] thread "<<tid<<" put a string "<<str.c_str()<<" --> "<<str2.c_str(); + } catch (DbException e) { + i--; + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + } + } // there may be more than total number of recs inserted because of the dupcnt + cout<<"\n[ "<<tid<<" ] writer thread finishes writing, exiting... dead lock count = "<<dlcnt; + break; + } //case wt_insert: + + case wt_delete: + { + i = 0;// ADDITIVE + while ( i < total * 0.1) { + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (container_t::iterator itr = vi.begin(); i < total * 0.1;) { + + itr.move_to(ndx = rand() % total); + if (itr != vi.end()) { + + vi.erase(itr); + i++; + if (verbose) + cout<<endl<<"multimap k/d deleted: "<<itr->first<<" : "<<(char*)(itr->second.get_data()); + + } else { + if (vi.size() == 0) + return; + __os_yield(NULL, 0, 500000); + } + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 0, 500000); + } + cout<<"\n[ "<<tid<<" ] deleter OK, exiting... dead lock count = "<<dlcnt; + break; + + }// case wt_delete + + case wt_update: + { + rand_str_maker(dbt, str, strlenmin, strlenmax); + i = 0;// ADDITIVE + while (i < total * 0.5) { + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (container_t::iterator itr = vi.begin(); i < total * 0.5;) { + + itr.move_to(ndx = rand() % total); + if (itr != vi.end()) { + if (verbose) + cout<<endl<<"multimap key = "<<itr->first<<" updated: "<<(char*)(itr->second.get_data())<<" ===> "; + itr->second = dbt; + i++; + if (verbose) + cout<<(char*)dbt.get_data(); + + } else { + if (vi.size() == 0) + return; + __os_yield(NULL, 0, 500000); + } + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 0, 500000); + + } + cout<<"\n[ "<<tid<<" ] updater OK, exiting... dead lock count = "<<dlcnt; + break; + + } // case wt_update + } // switch (p->job) + } + + if (p->cntnr_type == ct_set) { + typedef db_set<DbstlDbt> container_t; + container_t vi(p->pdb, penv); + const container_t &vi0 = vi; + container_t::iterator itr; + int rowcnt; + int j; + switch (p->job) { + case wt_read: + { + + while (cnt < total - 1) { + cnt = 0; + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (container_t::const_iterator itrc = vi0.begin(); itrc != vi0.end(); + itrc++, cnt++) { + str = (char*)((*itrc).get_data()); + if (verbose) + cout<<"\n [ "<<cnt<<" ] tid: "<<tid<<'\t'<<str.c_str(); + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 1, 0); // sleep 1 sec + } + if (iscds) // The update and delete thread will block until insert thread exits in cds mode + g_StopInsert = 1; + cout<<"\nthread "<<tid<<" got enough key/data pairs now, exiting... dead lock count = "<<dlcnt; + break; + } + case wt_insert: + {// writer + srand ((unsigned int)tid); + + pair<container_t::iterator, bool> insret; + for (i = 0; g_StopInsert == 0; i += 1) { + + rand_str_maker(dbt, str, strlenmin, strlenmax); + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + insret = vi.insert(dbt); + if (p->txnal) + dbstl::commit_txn(penv); + if (insret.second == false) // fail to insert + i--; + if (verbose) + cout<<endl<<"[ "<<i<<" ] thread "<<tid<<" put a string "<<str.c_str(); + } catch (DbException e) { + i--; + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + + } // there may be more than total number of recs inserted because of the dupcnt + cout<<"\n[ "<<tid<<" ] writer thread finishes writing, exiting... dead lock count = "<<dlcnt; + break; + } // case wt_insert: + + case wt_delete: + { + i = 0; + j = 0; + while (i < total * 0.1) { + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for ( ; i < total * 0.1;) {// ADDITIVE + rowcnt = rand() % total; + for (itr = vi.begin(), j = 0; j < rowcnt; j++, itr++) + ; // move to a random pos + if (itr != vi.end()) { + + vi.erase(itr); + i++; + if (verbose) + cout<<endl<<"set key deleted: "<<(char*)(itr->get_data()); + + } else { + if (vi.size() == 0) + return; + __os_yield(NULL, 0, 500000); + } + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 0, 500000); + } + cout<<"\n[ "<<tid<<" ] deleter OK, exiting... dead lock count = "<<dlcnt; + break; + + }// case wt_delete + + case wt_update: + { + rand_str_maker(dbt, str, strlenmin, strlenmax); + i = 0; + while ( i < total * 0.5) { + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (i = 0; i < total * 0.5;) { // REAL UPDATE + rowcnt = rand() % total; + + for (itr = vi.begin(), j = 0; j < rowcnt; j++, itr++) + ; // move to a random pos + if (itr != vi.end()) { + if (verbose) + cout<<endl<<"set key updated: "<<(char*)(itr->get_data())<<" ===> "; + *itr = dbt; + i++; + if (verbose) + cout<<(char*)dbt.get_data(); + + } else { + if (vi.size() == 0) + return; + __os_yield(NULL, 0, 500000); + } + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 0, 500000); + } + cout<<"\n[ "<<tid<<" ] updater OK, exiting... dead lock count = "<<dlcnt; + break; + }// case wt_update + } // switch (p->job) + } // fi + + if (p->cntnr_type == ct_multiset) { + typedef db_multiset<DbstlDbt> container_t; + container_t::iterator itr; + int rowcnt; + int j, dupcnt; + container_t vi(p->pdb, penv); + const container_t &vi0 = vi; + switch (p->job) { + case wt_read: + { + + while (cnt < total - 1) { + cnt = 0; + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (container_t::const_iterator itrc = vi0.begin(); itrc != vi0.end(); + itrc++, cnt++) { + str = (char*)((*itrc).get_data()); + if (verbose) + cout<<"\n [ "<<cnt<<" ] tid: "<<tid<<'\t'<<str.c_str(); + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 1, 0); // sleep 1 sec + } + if (iscds) // The update and delete thread will block until insert thread exits in cds mode + g_StopInsert = 1; + cout<<"\nthread "<<tid<<" got enough key/data pairs now, exiting... dead lock count = "<<dlcnt; + break; + } // case wt_read: + case wt_insert: + {// writer + srand ((unsigned int)tid); + + for (i = 0; g_StopInsert == 0; i += dupcnt) { + + for (j = 0, dupcnt = (rand() % 5); j < dupcnt; j++) { + rand_str_maker(dbt, str, strlenmin, strlenmax); + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + vi.insert(dbt); + if (p->txnal) + dbstl::commit_txn(penv); + if (verbose) + cout<<endl<<"[ "<<i<<" ] thread "<<tid<<" put a string "<<str.c_str(); + } catch (DbException e) { + i--; + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + } + } // there may be more than total number of recs inserted because of the dupcnt + cout<<"\n[ "<<tid<<" ] writer thread finishes writing, exiting... dead lock count = "<<dlcnt; + break; + } // case wt_insert: + case wt_delete: + { + i = 0; + j = 0; + while (i < total * 0.1) { + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (; i < total * 0.1;) {// ADDITIVE + rowcnt = rand() % total; + for (itr = vi.begin(), j = 0; j < rowcnt; j++, itr++) + ; // move to a random pos + if (itr != vi.end()) { + + vi.erase(itr); + i++; + if (verbose) + cout<<endl<<"multiset key deleted: "<<(char*)(itr->get_data()); + + } else { + if (vi.size() == 0) + return; + __os_yield(NULL, 0, 500000); + } + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 0, 500000); + } + cout<<"\n[ "<<tid<<" ] deleter OK, exiting... dead lock count = "<<dlcnt; + break; + + }// case wt_delete + + case wt_update: + { + rand_str_maker(dbt, str, strlenmin, strlenmax); + i = 0; + while ( i < total * 0.5) { + + try { + if (p->txnal) + dbstl::begin_txn(0, penv); + for (i = 0; i < total * 0.5;) {// REAL UPDATE + rowcnt = rand() % total; + for (itr = vi.begin(), j = 0; j < rowcnt; j++, itr++) + ; // move to a random pos + if (itr != vi.end()) { + if (verbose) + cout<<endl<<"multiset key updated: "<<(char*)(itr->get_data())<<" ===> "; + *itr = dbt; + i++; + if (verbose) + cout<<(char*)dbt.get_data(); + + } else { + if (vi.size() == 0) + return; + __os_yield(NULL, 0, 500000); + } + } + if (p->txnal) + dbstl::commit_txn(penv); + } catch (DbException e) { + dlcnt++; + dbstl::abort_txn(penv); + if (e.get_errno() != DB_LOCK_DEADLOCK) + throw e; + else + continue; + } + + __os_yield(NULL, 0, 500000); + } + cout<<"\n[ "<<tid<<" ] updater OK, exiting... dead lock count = "<<dlcnt; + break; + } // case wt_update + } //switch (p->job) + }// fi + + }// void operator()() +}; // WorkerThread + +// Used in the multi-threaded test to manage test threads, +// works like boost::thread_group +class ThreadMgr +{ +public: + os_thread_t create_thread(WorkerThread *thrd); + void clear() { threads.clear();} + void join_all(); + ThreadMgr() : threads(0){} +private: + vector<os_thread_t> threads; +}; // ThreadMgr + +#ifdef WIN32 +#define ThrdFuncRet DWORD +#define FunctRet return (0) +#else +#define ThrdFuncRet void* +#define FunctRet return (NULL) +#endif + +static ThrdFuncRet thread_func(void *arg) +{ + (*((WorkerThread *)arg)).run(); + FunctRet; +} + +os_thread_t ThreadMgr::create_thread(WorkerThread *thrd) +{ + os_thread_t thrdhandle; + + os_thread_create(&thrdhandle, NULL, thread_func, thrd); + threads.push_back(thrdhandle); + return thrdhandle; +} + +void ThreadMgr::join_all() +{ + ThrdFuncRet ret; + + for (size_t i = 0; i < threads.size(); i++) + os_thread_join(threads[i], &ret); +} diff --git a/db-4.8.30/test_stl/base/test_util.cpp b/db-4.8.30/test_stl/base/test_util.cpp new file mode 100644 index 0000000..203d25b --- /dev/null +++ b/db-4.8.30/test_stl/base/test_util.cpp @@ -0,0 +1,280 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2009 Oracle. All rights reserved. + * + * $Id$ + */ + +#include "test.h" + +char rand_str_dbt::buf[rand_str_dbt::BUFLEN]; +bool rand_str_dbt::init = false; +//boost::mutex g_mtx_co;// global mutex to sync create/open +DbEnv *g_env = NULL; +int g_test_start_txn = 0; +int g_StopInsert = 0; + +bool strlt0(const char *s1, const char *s2) +{ + return strcmp(s1, s2) < 0; +} + +bool streq0(const char *s1, const char *s2)// for list::unique +{ + return strcmp(s1, s2) == 0; +} + +bool strlt(const string&s1, const string&s2)// for list::merge and list::sort +{ + return strcmp(s1.c_str(), s2.c_str()) < 0; +} + +bool streq(const string&s1, const string&s2)// for list::unique +{ + return strcmp(s1.c_str(), s2.c_str()) == 0; +} + +bool operator==(ElementHolder<const char *>s1, const char *s2) +{ + return strcmp(s1, s2) == 0; +} + +bool operator==(ElementHolder<const wchar_t *>s1, const wchar_t *s2) +{ + return wcscmp(s1, s2) == 0; +} + +bool operator!=(ElementHolder<const char *>s1, const char *s2) +{ + return !operator==(s1, s2); +} + +bool operator!=(ElementHolder<const wchar_t *>s1, const wchar_t *s2) +{ + return !operator==(s1, s2); +} + +size_t g_sum(size_t s, size_t e) +{ + size_t sum = 0; + + for (size_t i = s; i <= e; i++) + sum += g_count[i]; + return sum; +} + +bool is_odd(ptint s) +{ + return ( s % 2) != 0; +} + +ptint addup(const ptint&i, const ptint&j) +{ + return i + j; +} + +ptint randint() +{ + return -999; +} + +int randpos(int p) +{ + return abs(rand()) % p; +} + +bool is2digits(ptint i) +{ + return (i > (9)) && (i < (100)); +} + +int get_dest_secdb_callback(Db * /* secondary */, const Dbt * /* key */, + const Dbt *data, Dbt *result) +{ + SMSMsg *p = (SMSMsg*)data->get_data(); + + result->set_data(&(p->to)); + result->set_size(sizeof(p->to)); + return 0; +} + +void usage() +{ + cout<< + "\nusage: test_dbstl \n\ +[-M run multi-thread test only]\n\ +[-T number total number of insert in multithread test]\n\ +[-c number cache size]\n\ +[-h print this help message then exit]\n\ +[-k number shortest string inserted]\n\ +[-l number longest string inserted]\n\ +[-m ds/cds/tds use ds/cds/tds product]\n\ +[-r number number of reader threads in multithread test]\n\ +[-s b/h use btree/hash type of DB for assocative \ +containers] \n\ +[-t a/e for tds, use autocommit/explicit transaction in \ +the test] \n\ +[-v verbose mode, output more info in multithread \ +test]\n\ +[-w number number of writer threads in multithread test]\n\ +"; +} + +void using_charstr(TCHAR*str) +{ + cout<<_T("using str read only with non-const parameter type:")<<str; + str[0] = _T('U'); + str[1] = _T('R'); +} + +void copy_array(TCHAR**arr, TCHAR***dest) +{ + int i; + + *dest = new TCHAR*[32]; + for (i = 0; arr[i] != NULL; i++) { + (*dest)[i] = new TCHAR[_tcslen(arr[i])]; + _tcscpy((*dest)[i], arr[i]); + } + +} + +void SMSMsgRestore(SMSMsg2& dest, const void *srcdata) +{ + char *p = dest.msg; + + memcpy(&dest, srcdata, sizeof(dest)); + + dest.msg = (char *)DbstlReAlloc(p, dest.szmsg); + strcpy(dest.msg, (char*)srcdata + sizeof(dest)); +} + +u_int32_t SMSMsgSize(const SMSMsg2& elem) +{ + return (u_int32_t)(sizeof(elem) + strlen(elem.msg) + 1); +} + +void SMSMsgCopy(void *dest, const SMSMsg2&elem) +{ + memcpy(dest, &elem, sizeof(elem)); + strcpy((char*)dest + sizeof(elem), elem.msg); +} + +bool ptintless(const ptint& a, const ptint& b) +{ + return a < b; +} + +u_int32_t rgblen(const RGBB *seq) +{ + size_t s = 0; + + const RGBB *p = seq, rgb0; + for (s = 0, p = seq; memcmp(p, &rgb0, sizeof(rgb0)) != 0; p++, s++); + // this size includes the all-0 last element used like '\0' + // for char* strings + return (u_int32_t)(s + 1); + +} + +// the seqs sequence of RGBB objects may not reside in a consecutive chunk of mem +// but the seqd points to a consecutive chunk of mem large enough to hold all objects +// from seqs +void rgbcpy(RGBB *seqd, const RGBB *seqs, size_t num) +{ + const RGBB *p = seqs; + RGBB rgb0; + RGBB *q = seqd; + + memset((void *)&rgb0, 0, sizeof(rgb0)); + for (p = seqs, q = seqd; memcmp(p, &rgb0, sizeof(rgb0)) != 0 && + num > 0; num--, p++, q++) + memcpy((void *)q, p, sizeof(RGBB)); + memcpy((void *)q, p, sizeof(RGBB));// append trailing end token. + + return; +} + +// Create test directory. +inline int dir_setup(const char *testdir) +{ + int ret; + +#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 3 + if ((ret = __os_mkdir(NULL, testdir, 0755)) != 0) { +#else + if ((ret = mkdir(testdir, 0755)) != 0) { +#endif + fprintf(stderr, + "dir_setup: Creating directory %s: %s\n", + testdir, db_strerror(ret)); + return (1); + } + return (0); +} + +inline int os_unlink(const char *path) +{ +#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 7 + return (__os_unlink(NULL, path)); +#else + return (__os_unlink(NULL, path, 0)); +#endif +} + +#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 4 +#define OS_EXISTS(a, b, c) __os_exists(a, b, c) +#else +#define OS_EXISTS(a, b, c) __os_exists(b, c) +#endif + +// Remove contents in specified directory recursively(in DB versions earlier +// than 4.6, don't recursively), and optionally remove the directory itself. +int rmdir_rcsv(const char *dir, bool keep_this_dir) +{ + int cnt, i, isdir, ret; + char buf[1024], **names; + + ret = 0; + + /* If the directory doesn't exist, we're done. */ + if (OS_EXISTS(NULL, dir, &isdir) != 0) + return (0); + + /* Get a list of the directory contents. */ +#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 6 + if ((ret = __os_dirlist(NULL, dir, 1, &names, &cnt)) != 0) + return (ret); +#else + if ((ret = __os_dirlist(NULL, dir, &names, &cnt)) != 0) + return (ret); +#endif + /* Go through the file name list, remove each file in the list */ + for (i = 0; i < cnt; ++i) { + (void)snprintf(buf, sizeof(buf), + "%s%c%s", dir, PATH_SEPARATOR[0], names[i]); + if ((ret = OS_EXISTS(NULL, buf, &isdir)) != 0) + goto file_err; + if (!isdir && (ret = os_unlink(buf)) != 0) { +file_err: fprintf(stderr, + "os_unlink: Error unlinking file: %s: %s\n", + buf, db_strerror(ret)); + break; + } + if (isdir && rmdir_rcsv(buf, false) != 0) + goto file_err; + } + + __os_dirfree(NULL, names, cnt); + + /* + * If we removed the contents of the directory and we don't want to + * keep this directory, remove the directory itself. + */ + if (i == cnt && !keep_this_dir && (ret = rmdir(dir)) != 0) + fprintf(stderr, + "rmdir_rcsv(%s): %s\n", dir, db_strerror(errno)); + return (ret); +} // rmdir_rcsv + diff --git a/db-4.8.30/test_stl/base/test_util.h b/db-4.8.30/test_stl/base/test_util.h new file mode 100644 index 0000000..ca0fc87 --- /dev/null +++ b/db-4.8.30/test_stl/base/test_util.h @@ -0,0 +1,605 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2009 Oracle. All rights reserved. + * + * $Id$ + */ + +#include "test.h" +#include "ptype.h" + +/* + * this function should not be included into dbstl because swapping + * different type of vars is possible to lose precision, this is why std::swap + * requires same type. here I know I won't lose precision so I do it at my + * cost + */ +namespace std { +template <Typename T1, Typename T2> +void swap(T1&t1, T2&t2) +{ + T2 t; + t = t2; + t2 = t1; + t1 = t; + +} + +bool operator==(const pair<ptint, ElementHolder<ptint> >&v1, const pair<ptint, ElementHolder<ptint> >&v2) +{ + return v1.first == v2.first && v1.second._DB_STL_value() == v2.second._DB_STL_value(); +} + +template <typename T1, typename T2, typename T3, typename T4> +bool operator==(const pair<T1, T2>&v1, const pair<T3, T4> &v2) +{ + return v1.first == v2.first && v1.second == v2.second; +} +} // namespace std + +template <Typename T1, Typename T2, Typename T3, Typename T4> +bool is_equal(db_map<T1, T2, ElementHolder<T2> >& dv, map<T3, T4>&v) +{ + size_t s1, s2; + bool ret; + typename db_map<T1, T2, ElementHolder<T2> >::iterator itr1; + typename map<T3, T4>::iterator itr2; + + if (g_test_start_txn) + begin_txn(0, g_env); + if ((s1 = dv.size()) != (s2 = v.size())){ + ret = false; + goto done; + } + + for (itr1 = dv.begin(), itr2 = v.begin(); itr1 != dv.end(); ++itr1, ++itr2) { + if (itr1->first != itr2->first || itr1->second != itr2->second){ + ret = false; + goto done; + } + + } + + ret = true; +done: + if (g_test_start_txn) + commit_txn(g_env); + return ret; + +} + +template <Typename T1, Typename T2, Typename T3, Typename T4> +bool is_equal(db_map<T1, T2, ElementRef<T2> >& dv, map<T3, T4>&v) +{ + size_t s1, s2; + bool ret; + typename db_map<T1, T2, ElementRef<T2> >::iterator itr1; + typename map<T3, T4>::iterator itr2; + + if (g_test_start_txn) + begin_txn(0, g_env); + if ((s1 = dv.size()) != (s2 = v.size())){ + + ret = false; + goto done; + } + + + for (itr1 = dv.begin(), itr2 = v.begin(); itr1 != dv.end(); ++itr1, ++itr2) { + if (itr1->first != itr2->first || itr1->second != itr2->second){ + ret = false; + goto done; + } + } + + ret = true; +done: + if (g_test_start_txn) + commit_txn(g_env); + return ret; + +} + + +template<Typename T1, Typename T2> +bool is_equal(const db_set<T1, ElementHolder<T1> >&s1, const set<T2>&s2) +{ + bool ret; + typename db_set<T1, ElementHolder<T1> >::iterator itr; + + if (g_test_start_txn) + begin_txn(0, g_env); + if (s1.size() != s2.size()){ + ret = false; + goto done; + } + + for (itr = s1.begin(); itr != s1.end(); itr++) { + if (s2.count(*itr) == 0) { + ret = false; + goto done; + } + } + ret = true; +done: + if (g_test_start_txn) + commit_txn(g_env); + return ret; + +} + + +template <Typename T1, Typename T2> +bool is_equal(const db_vector<T1>& dv, const vector<T2>&v) +{ + size_t s1, s2; + bool ret; + T1 t1; + size_t i, sz = v.size(); + + if (g_test_start_txn) + begin_txn(0, g_env); + if ((s1 = dv.size()) != (s2 = v.size())) { + ret = false; + goto done; + } + + + for (i = 0; i < sz; i++) { + t1 = T1(dv[(index_type)i] ); + if (t1 != v[i]){ + ret = false; + goto done; + } + } + ret = true; +done: + + if (g_test_start_txn) + commit_txn(g_env); + return ret; +} + +// The following four functions are designed to work with is_equal to compare +// char*/wchar_t* strings properly, unforturnately they can not override +// the default pointer value comparison behavior. +bool operator==(ElementHolder<const char *>s1, const char *s2); +bool operator==(ElementHolder<const wchar_t *>s1, const wchar_t *s2); +bool operator!=(ElementHolder<const char *>s1, const char *s2); +bool operator!=(ElementHolder<const wchar_t *>s1, const wchar_t *s2); + +template <Typename T1> +bool is_equal(const db_vector<T1, ElementHolder<T1> >& dv, const vector<T1>&v) +{ + size_t s1, s2; + bool ret; + size_t i, sz = v.size(); + + if (g_test_start_txn) + begin_txn(0, g_env); + if ((s1 = dv.size()) != (s2 = v.size())) { + ret = false; + goto done; + } + + for (i = 0; i < sz; i++) { + if (dv[(index_type)i] != v[i]) { + ret = false; + goto done; + } + } + ret = true; +done: + + if (g_test_start_txn) + commit_txn(g_env); + return ret; +} + + +template <Typename T1, Typename T2> +bool is_equal(db_vector<T1>& dv, list<T2>&v) +{ + size_t s1, s2; + bool ret; + typename db_vector<T1>::iterator itr; + typename list<T2>::iterator itr2; + + if (g_test_start_txn) + begin_txn(0, g_env); + if ((s1 = dv.size()) != (s2 = v.size())) { + ret = false; + goto done; + } + + + for (itr = dv.begin(), itr2 = v.begin(); + itr2 != v.end(); ++itr, ++itr2) { + if (*itr != *itr2) { + ret = false; + goto done; + } + } + ret = true; +done: + + if (g_test_start_txn) + commit_txn(g_env); + return ret; +} + +bool is_equal(db_vector<char *, ElementHolder<char *> >&v1, std::list<string> &v2) +{ + db_vector<char *, ElementHolder<char *> >::iterator itr; + std::list<string>::iterator itr2; + + if (v1.size() != v2.size()) + return false; + + for (itr = v1.begin(), itr2 = v2.begin(); itr2 != v2.end(); ++itr, ++itr2) + if (strcmp(*itr, (*itr2).c_str()) != 0) + return false; + + return true; +} + +template <Typename T1> +class atom_equal { +public: + bool operator()(T1 a, T1 b) + { + return a == b; + } +}; +template<> +class atom_equal<const char *> { +public: + bool operator()(const char *s1, const char *s2) + { + return strcmp(s1, s2) == 0; + } +}; + +template <Typename T1> +bool is_equal(const db_vector<T1, ElementHolder<T1> >& dv, const list<T1>&v) +{ + size_t s1, s2; + bool ret; + typename db_vector<T1, ElementHolder<T1> >::const_iterator itr; + typename list<T1>::const_iterator itr2; + atom_equal<T1> eqcmp; + if (g_test_start_txn) + begin_txn(0, g_env); + if ((s1 = dv.size()) != (s2 = v.size())) { + ret = false; + goto done; + } + + + for (itr = dv.begin(), itr2 = v.begin(); + itr2 != v.end(); ++itr, ++itr2) { + if (!eqcmp(*itr, *itr2)) { + ret = false; + goto done; + } + } + ret = true; +done: + + if (g_test_start_txn) + commit_txn(g_env); + return ret; +} + +// fill the two vectors with identical n integers,starting from start +template<Typename T> +void fill(db_vector<ptype<T> >&v, vector<T>&sv, T start = 0, int n = 5) +{ + T i; + + v.clear(); + sv.clear(); + for (i = start; i < n + start; i++) { + v.push_back(i); + sv.push_back(i); + } +} + + +template<Typename T> +void fill(db_vector<T, ElementHolder<T> >&v, vector<T>&sv, T start = 0, int n = 5 ) +{ + int i; + + v.clear(); + sv.clear(); + for (i = 0; i < n; i++) { + v.push_back(i + start); + sv.push_back(i + start); + } +} + +template <Typename T> +void fill(db_map<ptype<T>, ptype<T> >&m, map<T, T>&sm, + T start = 0, int n = 5) +{ + int i; + ptype<T> pi; + + m.clear(); + sm.clear(); + for (i = 0; i < n; i++) { + pi = i + start; + m.insert(make_pair(pi, pi)); + sm.insert(make_pair(pi.v, pi.v)); + } + +} + + +template <Typename T> +void fill(db_map<T, T, ElementHolder<T> >&m, map<T, T>&sm, + T start = 0, int n = 5) +{ + int i; + T pi; + + m.clear(); + sm.clear(); + for (i = 0; i < n; i++) { + pi = i + start; + m.insert(make_pair(pi, pi)); + sm.insert(make_pair(pi, pi)); + } + +} + + +template <Typename T> +void fill(db_set<ptype<T> >&m, set<T>&sm, T start = 0, int n = 5) +{ + int i; + ptype<T> pi; + + m.clear(); + sm.clear(); + + for (i = 0; i < n; i++) { + + pi = i + start; + m.insert(pi); + sm.insert(pi.v); + } + +} + + +template <Typename T> +void fill(db_set<T, ElementHolder<T> >&m, set<T>&sm, + T start = 0, int n = 5) +{ + int i; + T pi; + + m.clear(); + sm.clear(); + for (i = 0; i < n; i++) { + pi = i + start; + m.insert(pi); + sm.insert(pi); + } + +} + + +size_t g_count[256]; +template <Typename T> +void fill(db_multimap<ptype<T>, ptype<T> >&m, multimap<T, T>&sm, + T start = 0, int n = 5, size_t randn = 5) +{ + + int i; + size_t j, cnt; + + if (randn == 0) + randn = 1; + + m.clear(); + sm.clear(); + for (i = 0; i < n; i++) { + if (randn > 1) + cnt = abs(rand()) % randn; + if (cnt == 0) + cnt = randn; + i += start; + g_count[i] = cnt; + for (j = 0; j < cnt; j++) {// insert duplicates + m.insert(make_pair(i, ptype<T>(i))); + sm.insert(make_pair(i, i)); + } + i -= start; + } +} + + +template <Typename T> +void fill(db_multimap<T, T, ElementHolder<T> >&m, multimap<T, T>&sm, + T start = 0, int n = 5, size_t randn = 5) +{ + int i; + size_t j, cnt = 0; + + if (randn < 5) + randn = 5; + + m.clear(); + sm.clear(); + for (i = 0; i < n; i++) { + cnt = abs(rand()) % randn; + if (cnt == 0) + cnt = randn; + i += start; + g_count[i] = cnt; + for (j = 0; j < cnt; j++) {// insert duplicates + m.insert(make_pair(i, i)); + sm.insert(make_pair(i, i)); + } + i -= start; + } + +} + + +template <Typename T> +void fill(db_multiset<ptype<T> >&m, multiset<T>&sm, T start, + int n, size_t randn) +{ + + int i; + size_t j, cnt; + + if (randn == 0) + randn = 1; + + m.clear(); + sm.clear(); + for (i = 0; i < n; i++) { + if (randn > 1) + cnt = abs(rand()) % randn; + if (cnt == 0) + cnt = randn; + i += start; + g_count[i] = cnt; + for (j = 0; j < cnt; j++) {// insert duplicates + m.insert(ptype<T>(i)); + sm.insert(i); + } + i -= start; + } +} + + +template <Typename T> +void fill(db_multiset<T, ElementHolder<T> >&m, multiset<T>&sm, + T start = 0, int n = 5 , size_t randn = 5) +{ + int i; + size_t j, cnt; + + if (randn < 5) + randn = 5; + + m.clear(); + sm.clear(); + for (i = 0; i < n; i++) { + cnt = abs(rand()) % randn; + if (cnt == 0) + cnt = randn; + i += start; + g_count[i] = cnt; + for (j = 0; j < cnt; j++) {// insert duplicates + m.insert(i); + sm.insert(i); + } + i -= start; + } +} + + +#ifdef TEST_PRIMITIVE +bool is_odd_pair(pair<ptint, ElementHolder<ptint> >& s) +{ + return ( s.second._DB_STL_value() % 2) != 0; +} +#else +bool is_odd_pair(pair<ptint, ElementRef<ptint> >& s) +{ + return ( s.second._DB_STL_value() % 2) != 0; +} +#endif + + +template<Typename pair_type> +void square_pair(pair_type&s) +{ + cout<<s.second*s.second<<'\t'; +} + +template<Typename pair_type> +void square_pair2(pair_type&s) +{ + cout<<s.second*s.second<<'\t'; +} + + + + +#ifndef TEST_PRIMITIVE +bool is2digits_pair(pair<ptint, ElementRef<ptint> >& i) +{ + return (i.second._DB_STL_value() > (9)) && (i.second._DB_STL_value() < (100)); +} + +#else +bool is2digits_pair(pair<ptint, ElementHolder<ptint> >& i) +{ + return (i.second._DB_STL_value() > (9)) && (i.second._DB_STL_value() < (100)); +} +#endif +bool is7(const ptint& value) { return (value == (ptint)7); } + + +template <Typename T, Typename value_type_sub> +void pprint(db_vector<T, value_type_sub>&v, const char *prefix = NULL) +{ +return; + size_t i; + size_t sz = v.size(); + + cout<<"\n"; + if (prefix) + cout<<prefix; + if (g_test_start_txn) + begin_txn(0, g_env); + for (i = 0; i < sz; i++) { + cout<<"\t"<<(v[(index_type)i]); + } + if (g_test_start_txn) + commit_txn(g_env); +} + + +template <Typename T, Typename ddt, Typename value_type_sub> +void pprint(db_map<T, ddt, value_type_sub>&v, const char *prefix = NULL) +{ +return; + if (g_test_start_txn) + begin_txn(0, g_env); + cout<<"\n"; + if (prefix) + cout<<prefix; + typename db_map<T, ddt, value_type_sub>::iterator itr; + for (itr = v.begin(); itr != v.end(); itr++) + cout<<'\t'<<itr->first<<'\t'<<itr->second; + if (g_test_start_txn) + commit_txn(g_env); +} + + +template <Typename T, Typename value_type_sub> +void pprint(db_set<T, value_type_sub>&v, const char *prefix = NULL) +{ +return; + if (g_test_start_txn) + begin_txn(0, g_env); + cout<<"\n"; + if (prefix) + cout<<prefix; + typename db_set<T, value_type_sub>::iterator itr; + for (itr = v.begin(); itr != v.end(); itr++) + cout<<'\t'<<*itr; + if (g_test_start_txn) + commit_txn(g_env); +} + diff --git a/db-4.8.30/test_stl/base/test_vector.h b/db-4.8.30/test_stl/base/test_vector.h new file mode 100644 index 0000000..efcf165 --- /dev/null +++ b/db-4.8.30/test_stl/base/test_vector.h @@ -0,0 +1,1338 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2009 Oracle. All rights reserved. + * + * $Id$ + */ + +#include "test.h" + +#include <list> + +using std::list; +using std::priority_queue; + +// This class tests all methods of db_vector and db_vector_iterator +// Most tests are done by doing identical operations to db_vector +// and std::vector and check the result data set in the two vectors +// are identical. Also, almost all algorithms in std are applied to +// the different ranges created from db_vector and std::vector, and +// also compare result of the in the same way. +// +class TestVector +{ +public: + ~TestVector(); + TestVector(void *param1); + void start_test() + { + + tb.begin("db_vector"); + // Do not change the order of these functions. + + // Test each member function of db_vector and + // db_vector_iterator that are shared by all three + // std containers std::vector, std::deque and std::list. + test_member_functions(); + + // Test std::list specific methods. + test_list_specific_member_functions(); + + // Use std functions to manipulate db_vector containers. + test_std_functions(); + + // Test storing primitive data. + test_primitive(); + + // Test whether db_vector works with std container adapters + // std::stack, std::queue and std::priority_queue + test_queue_stack(); + tb.end(); + } + + void test_member_functions(); + void test_list_specific_member_functions(); + void test_std_functions(); + void test_primitive(); + void test_queue_stack(); +private: + + int n; + int flags, setflags, EXPLICIT_TXN, TEST_AUTOCOMMIT; + DBTYPE dbtype; + DbEnv *penv; + Db *db, *db2, *db3; + Db *quedb, *pquedb; + test_block tb; + + vector<int> svi, svi2, svi3; + +}; + +TestVector::~TestVector() +{ + +} + +TestVector::TestVector(void *param1) +{ + check_expr(param1 != NULL); + TestParam *param = (TestParam*)param1; + TestParam *ptp = param; + penv = param->dbenv; + db = db2 = db3 = NULL; + flags = 0, setflags = 0, EXPLICIT_TXN = 1, TEST_AUTOCOMMIT = 0; + flags = param->flags; + dbtype = param->dbtype; + setflags = param->setflags; + TEST_AUTOCOMMIT = param->TEST_AUTOCOMMIT; + EXPLICIT_TXN = param->EXPLICIT_TXN; + n = 5; + dbtype = DB_BTREE; + db = dbstl::open_db(penv, "db1.db", + DB_RECNO, DB_CREATE | ptp->dboflags | DB_THREAD, DB_RENUMBER); + db2 = dbstl::open_db(penv, "db2.db", + DB_RECNO, DB_CREATE | ptp->dboflags, DB_RENUMBER); + db3 = dbstl::open_db(penv, "db3.db", + DB_RECNO, DB_CREATE | ptp->dboflags, DB_RENUMBER); + // NO DB_RENUMBER needed + quedb = dbstl::open_db(penv, "dbquedb.db", + DB_RECNO, DB_CREATE | ptp->dboflags | DB_THREAD, 0); + pquedb = dbstl::open_db(penv, "dbpquedb.db", + DB_RECNO, DB_CREATE | ptp->dboflags | DB_THREAD, DB_RENUMBER); +} + +void TestVector::test_member_functions() +{ + int i; + ptint_vector::iterator itr1, itr; + ptint_vector::reverse_iterator ritr1, ritr; + vector<int>::iterator sitr, sitr1; + vector<int>::reverse_iterator rsitr, rsitr1; + + + ptint_vector vi(db, penv); + const ptint_vector& cnstvi = vi; + vi.clear(); + if ( EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + fill(vi, svi, 0, n); + + for (i = 0; i < n; i++) { + ptint_vector::const_iterator citr, citr1; + citr = vi.begin() + i; + check_expr(*citr == vi[i]); + itr = citr; + check_expr(*citr == *itr); + *itr = i * 2 + 1; + citr1 = itr; + check_expr(*citr == *itr); + check_expr(*citr == *citr1); + check_expr(*citr == vi[i]); + } + + for (i = 0; i < n; i++) { + ptint_vector::const_iterator citr = vi.begin() + i; + check_expr(*citr == vi[i]); + itr = citr; + check_expr(*citr == *itr); + *itr = i * 2 + 1; + ptint_vector::const_iterator citr1 = itr; + check_expr(*citr == *itr); + check_expr(*citr == *citr1); + check_expr(*citr == vi[i]); + } + + for (i = 0; i < n; i++) { + ptint_vector::iterator ncitr, ncitr1; + ptint_vector::const_iterator citr, citr1; + + ncitr = cnstvi.begin() + i; + check_expr(*ncitr == cnstvi[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 == cnstvi[i]); + } + + for (i = 0; i < n; i++) { + + ptint_vector::iterator ncitr = cnstvi.begin() + i; + check_expr(*ncitr == cnstvi[i]); + ptint_vector::const_iterator citr = ncitr; + check_expr(*citr == *ncitr); + //*itr = i * 2 + 1; + ptint_vector::const_iterator citr1 = ncitr; + ptint_vector::iterator ncitr1 = citr1; + + check_expr(*citr == *ncitr); + check_expr(*citr == *ncitr1); + check_expr(*citr == *citr1); + check_expr(*citr == cnstvi[i]); + } + + { + vi.clear(); + svi.clear(); + vi.push_back(123); + svi.push_back(123); + ptint_vector::iterator ncitr = vi.begin(); + vector<int>::iterator ncsitr = svi.begin(); + *ncitr += 5; + *ncitr -= 3; + *ncitr *= 4; + *ncitr /= 2; + *ncitr %= 97; + (*ncitr)++; + (*ncitr)--; + ++(*ncitr); + --(*ncitr); + *ncsitr += 5; + *ncsitr -= 3; + *ncsitr *= 4; + *ncsitr /= 2; + *ncsitr %= 97; + (*ncsitr)++; + (*ncsitr)--; + ++(*ncsitr); + --(*ncsitr); + check_expr(*ncsitr == *ncitr); + + *ncitr &= 0x9874abcd; + *ncitr |= 0x12345678; + *ncitr ^= 0x11223344; + *ncsitr &= 0x9874abcd; + *ncsitr |= 0x12345678; + *ncsitr ^= 0x11223344; + ncitr.refresh(true); + check_expr(*ncsitr == *ncitr); + + vi.clear(); + svi.clear(); + db_vector<ptype<int> > tmpvi; + const db_vector<ptype<int> > & ctmpvi = tmpvi; + fill(tmpvi, svi, 0, n); + db_vector<ptype<int> >::const_reverse_iterator critr; + vector<int>::const_reverse_iterator crsitr; + db_vector<ptype<int> >::const_iterator citr2; + vector<int>::const_iterator csitr2; + + check_expr(ctmpvi.back() == svi.back()); + check_expr(ctmpvi.at(0) == svi.at(0)); + critr = tmpvi.rbegin();//XXXXXXXXX modify db_reverse_iterator, use twin type + for (i = n - 1, crsitr = svi.rbegin(); critr != tmpvi.rend(); ++critr, ++crsitr, i--) { + check_expr(crsitr < crsitr + 1); + check_expr(critr < critr + 1); + check_expr(critr <= critr + 1); + + + check_expr(critr > critr - 1); + check_expr(critr >= critr - 1); + if (i > 0) { + ptype<int> tmpv1 = critr[1]; + int tmpv2 = crsitr[1]; + check_expr(tmpv1 == tmpv2); + } + + check_expr(critr <= 2 + critr); + //if (i < n - 2) + check_expr(critr >= -2 + critr); + check_expr(*critr == *crsitr); + } + + for (critr = ctmpvi.rbegin(), crsitr = svi.rbegin(), i = 0; critr != ctmpvi.rend(); critr += 3, crsitr += 3, i++) { + check_expr(*critr == *crsitr); + if (i > 0) { + critr -= 2; + crsitr -= 2; + } + check_expr(*critr == *crsitr); + } + + for (citr2 = tmpvi.begin(), csitr2 = svi.begin(), i = 0; citr2 != tmpvi.rend(); ++citr2, ++csitr2, i++) { + check_expr(citr2 < citr2 + 1); + check_expr(citr2 <= citr2 + 1); + check_expr(citr2 > citr2 - 1); + check_expr(citr2 >= citr2 - 1); + check_expr(citr2 <= 2 + citr2); + + if (i > 1) + check_expr(citr2 >= -2 + citr2); + check_expr(*citr2 == *csitr2); + if (i < n - 1) + check_expr(citr2[1] == csitr2[1]); + } + + for (citr2 = ctmpvi.begin(), csitr2 = svi.begin(), i = 0; citr2 != ctmpvi.rend(); citr2 += 3, csitr2 += 3, i++) { + citr2.refresh(true); + check_expr(*citr2 == *csitr2); + if (i > 0) { + citr2 -= 2; + csitr2 -= 2; + } + check_expr(*citr2 == *csitr2); + check_expr(citr2->v == *csitr2); + } + citr2 = ctmpvi.begin() + 2; + csitr2 = svi.begin() + 2; + check_expr(*citr2 == *csitr2); + citr2--; + csitr2--; + check_expr(*citr2 == *csitr2); + --citr2; + --csitr2; + check_expr(*citr2 == *csitr2); + + db_vector<ptype<int> > tmpvi2; + vector<int> tmpsvi2; + tmpvi2.insert(tmpvi2.begin(), tmpvi.begin() + 1, tmpvi.end() - 1); + //tmpsvi2.insert(svi.begin(), svi.begin() + 1, svi.end() - 1); c++ stl does not support this + for (i = 1; i < (int)tmpvi.size() - 1; i++) + tmpsvi2.push_back(tmpvi[i]); + check_expr(is_equal(tmpvi2, tmpsvi2)); + + tmpvi2.clear(false); + tmpsvi2.clear(); + + tmpvi2.insert(tmpvi2.end(), tmpvi.begin(), tmpvi.end()); + tmpsvi2.insert(tmpsvi2.end(), svi.begin(), svi.end()); + check_expr(is_equal(tmpvi2, tmpsvi2)); + + tmpvi2.insert(tmpvi2.end() - 3, tmpvi.begin() + 2, tmpvi.end() - 1); + tmpsvi2.insert(tmpsvi2.end() - 3, svi.begin() + 2, svi.end() - 1); + check_expr(is_equal(tmpvi2, tmpsvi2)); + + db_vector<char, ElementHolder<char> > charvec(n); + for (i = 0; i < n; i++) + charvec[i] = (char)i; + db_vector<char, ElementHolder<char> > charvec3(charvec); + const db_vector<char, ElementHolder<char> > &ccharvec3 = charvec3; + check_expr(ctmpvi == charvec); + charvec[n / 2] *= 2; + check_expr(ctmpvi != charvec); + charvec.push_back(127); + check_expr(ctmpvi != charvec); + charvec.resize(charvec.size()); + charvec.assign(ccharvec3.begin(), ccharvec3.end()); + check_expr(charvec == ccharvec3); + charvec.clear(false); + charvec.insert(charvec.begin(), ccharvec3.begin(), ccharvec3.end()); + charvec.insert(charvec.begin(), 113); + db_vector<char, ElementHolder<char> > charvec2(5); + charvec2.assign(charvec.begin(), charvec.end(), false); + check_expr((charvec2 != charvec) == false); + + db_vector<string> tmpvi3, tmpvi4; + db_vector<char *, ElementHolder<char *> > tmpvi5, tmpvi6; + + std::list<string> tmpsvi3, tmpsvi4; + char tmpbuf[4]; + tmpbuf[3] = '\0'; + int exec_cnt = 0; +doagain: + for (i = 0; i < 64; i++) { + tmpbuf[0] = 'a' + rand() % 3; + tmpbuf[1] = 'a' + rand() % 3; + tmpbuf[2] = 'a' + rand() % 3; + tmpvi3.push_back(string(tmpbuf)); + tmpsvi3.push_back(string(tmpbuf)); + tmpvi5.push_back(tmpbuf); + } + + // sort + if (exec_cnt == 0) { + tmpvi5.sort(strlt0); + tmpvi3.sort(strlt); + tmpsvi3.sort(strlt); + } else { + tmpvi5.sort(); + tmpvi3.sort(); + tmpsvi3.sort(); + } + check_expr(is_equal(tmpvi3, tmpsvi3)); + check_expr(is_equal(tmpvi5, tmpsvi3)); + + // unique + if (exec_cnt == 0) { + tmpvi5.unique(streq0); + tmpvi3.unique(streq); + tmpsvi3.unique(streq); + } else { + tmpvi5.unique(); + tmpvi3.unique(); + tmpsvi3.unique(); + } + check_expr(is_equal(tmpvi3,tmpsvi3)); + check_expr(is_equal(tmpvi5, tmpsvi3)); + + // merge + for (i = 0; i < 64; i++) { + tmpbuf[0] = 'b' + rand() % 3; + tmpbuf[1] = 'b' + rand() % 3; + tmpbuf[2] = 'b' + rand() % 3; + tmpvi4.push_back(string(tmpbuf)); + tmpsvi4.push_back(string(tmpbuf)); + tmpvi6.push_back(tmpbuf); + } + + if (exec_cnt == 0) { + tmpvi6.sort(strlt0); + tmpvi4.sort(strlt); + tmpsvi4.sort(strlt); + tmpvi5.merge(tmpvi6, strlt0); + tmpvi3.merge(tmpvi4, strlt); + tmpsvi3.merge(tmpsvi4, strlt); + } else { + tmpvi6.sort(); + tmpvi4.sort(); + tmpsvi4.sort(); + tmpvi5.merge(tmpvi6); + tmpvi3.merge(tmpvi4); + tmpsvi3.merge(tmpsvi4); + } + check_expr(is_equal(tmpvi3, tmpsvi3)); + check_expr(is_equal(tmpvi5, tmpsvi3)); + + exec_cnt++; + if (exec_cnt == 1) { + tmpvi3.clear(); + tmpvi4.clear(); + tmpvi5.clear(); + tmpvi6.clear(); + tmpsvi3.clear(); + tmpsvi4.clear(); + goto doagain; + } + vi.clear(); + svi.clear(); + } + + vi.clear(); + // tested: push_back, operator!= , db_vector::size, + fill(vi, svi, 0, n); + pprint(vi); + check_expr(is_equal(vi, svi) == true); + ptint tmp; + + // tested functions: + // db_vector<>::begin, end; iterator::operator ++/*/=, + // iterator copy constructor, RandDbc<>::operator=, + // RandDbc<>(const RandDbc&), + // T(const RandDbc<T>&), + // RandDbc<T>::operator=(const RandDbc<T>&), + // and also the reverse iterator versions of these functions/classes + // + for(itr1 = vi.begin(), itr = itr1, sitr1 = svi.begin(), + sitr = sitr1, i = 0; + itr1 != vi.end() && sitr1 != svi.end(); itr1++, sitr1++, i++) { + + *itr = (tmp = ptint(*itr1) * 2); + cout<<"\n*itr = "<<(ptint(*itr))<<"\ttmp = "<<tmp; + itr = itr1; + *sitr = (*sitr1) * 2; + sitr = sitr1; + } + pprint(vi); + check_expr(is_equal(vi, svi) == true); + size_t ii; + for(itr1 = vi.begin(), sitr1 = svi.begin(), ii = 0; + ii < svi.size(); ii++) { + itr1[ii] = 2 * itr1[ii]; + sitr1[ii] = 2 * sitr1[ii]; + } + pprint(vi); + check_expr(is_equal(vi, svi) == true); + //itr.close_cursor(); + if ( EXPLICIT_TXN) { + + dbstl::commit_txn(penv); + dbstl::begin_txn(0, penv); + } + for(ritr1 = vi.rbegin(), ritr = ritr1, rsitr1 = svi.rbegin(), + rsitr = rsitr1, i = 0; + ritr1 != vi.rend() && rsitr1 != svi.rend(); + ritr1++, rsitr1++, i++) { + + *ritr = (tmp = (*ritr1 * 2)); + cout<<"\n*itr = "<<(ptint(*ritr))<<"\ttmp = "<<tmp; + ritr = ritr1; + *rsitr = *rsitr1 * 2; + rsitr = rsitr1; + } + + if (EXPLICIT_TXN) { + + dbstl::commit_txn(penv); + dbstl::begin_txn(0, penv); + } + pprint(vi); + check_expr(is_equal(vi, svi) == true); + + for(ritr1 = vi.rbegin(), ritr = ritr1, rsitr1 = svi.rbegin(), + rsitr = rsitr1, i = 0; + ritr1 != vi.rend() && rsitr1 != svi.rend(); + ritr1++, rsitr1++, i++) { + + *ritr = (tmp = ptint(*ritr1) * 2); + cout<<"\n*itr = "<<(ptint(*ritr))<<"\ttmp = "<<tmp; + ritr = ritr1; + *rsitr = (*rsitr1) * 2; + rsitr = rsitr1; + } + + pprint(vi); + check_expr(is_equal(vi, svi) == true); + if (EXPLICIT_TXN){ + dbstl::commit_txn(penv); + dbstl::begin_txn(0, penv); + } + for(itr1 = vi.begin(), itr = itr1, sitr1 = svi.begin(), + sitr = sitr1, i = 0; + itr1 != vi.end() && sitr1 != svi.end(); + itr1++, sitr1++, i++) { + + *itr = (tmp = ptint(*itr1) * 2); + cout<<"\n*itr = "<<(ptint(*itr))<<"\ttmp = "<<tmp; + itr = itr1; + *sitr = (*sitr1) * 2; + sitr = sitr1; + } + + itr.close_cursor(); + pprint(vi); + check_expr(is_equal(vi, svi) == true); + if (EXPLICIT_TXN) { + + dbstl::commit_txn(penv); + dbstl::begin_txn(0, penv); + } + + for (i = 0; i< n - 1; i++) { + vi[i] = ptint(vi[i]) * 2; + vi[i] = TOINT( ptint(vi[i]) - (ptint(vi[i + 1]) * 2)); + + svi[i] = svi[i] * 2; + svi[i] = TOINT(svi[i] - svi[i + 1] * 2); + + } + pprint(vi); + check_expr(is_equal(vi, svi) == true); + if (EXPLICIT_TXN) + dbstl::commit_txn(penv); + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + + // testing pop_back and back() + ptint t; + for (i = n - 1; i >= 0; i--) { + check_expr(ptint(vi.back()) == svi[i]); + vi.pop_back(); + } + + list<int> lvi; + list<int>::iterator lvit; + for (i = 0; i < n; i++) { + lvi.push_front(i); + vi.push_front(i); + } + pprint(vi, "inserted by push_front"); + for (i = 0; i < n; i++) { + pprint(vi, "pop front :"); + check_expr(ptint(vi.front()) == lvi.front()); + vi.pop_front(); + lvi.pop_front(); + } + fill(vi, svi, 0, n); + if ( !TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + //testing front(), erase() + cout<<"front test\n"; + for (i = 0, itr = vi.begin(); i < n; i++) { + pprint(vi); + check_expr(ptint(vi.front()) == svi[i]); + if (i % 2) // try both + itr = vi.erase(itr); + else { + vi.pop_front(); // here pop_front is also OK + itr = vi.begin(); + } + } + itr.close_cursor(); + fill(vi, svi, 0, n); + + + /* + * Currently we can only use a ref to ref the *itr and use + * the ref UNTIL we store changes, rahter than + * use *itr multiple times, because iterator::operator* will erase + * changed data members. this limitation won't influence std + * algorithms because they all manipulate the elements in their + * whole, never access their members. + */ + for (itr1 = vi.begin(), itr = itr1, + sitr1 = svi.begin(), sitr = sitr1, i = 0; + itr1 != vi.end() && sitr1 != svi.end();i++, itr1++, sitr1++) { + + if (i % 2 == 0) { + ptint_vector::iterator::reference itrref = (*itr); + t = itrref; + check_expr( t == *sitr); + itrref = (t) * 3; + (*sitr) = 3 * (*sitr); + itrref._DB_STL_StoreElement(); + itr = itr1; + sitr = sitr1; + + } else { + ptint_vector::reference itrref = vi[i]; + t = itrref; + check_expr(t == svi[i]); + itrref = t * 3; + svi[i] = 3 * svi[i]; + itrref._DB_STL_StoreElement(); + } + + } + pprint(vi); + check_expr(is_equal(vi, svi) == true); + + ptint_vector vi2(db2, penv); + vi2.clear(); + + vi2.insert(vi2.end(), 1024); + svi2.insert(svi2.end(), 1024); + check_expr(is_equal(vi2, svi2) == true); + if ( EXPLICIT_TXN) + dbstl::commit_txn(penv); + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + pprint(vi, "vi before swapping: "); + fill(vi2, svi2, 6, 9); + check_expr(vi != vi2); + pprint(vi, "vi before swapping2:"); + pprint(vi2, "vi2 before swapping: "); + vi.swap(vi2); + check_expr(vi != vi2); + svi.swap(svi2); + pprint(vi, "vi:"); + pprint(vi2, "vi2:"); + check_expr(is_equal(vi, svi) == true); + check_expr(is_equal(vi2, svi2) == true); + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + cout<<"\ntesting db container's insert method..."; + vi.insert(vi.end(), 1024); + svi.insert(svi.end(), 1024); + vi.insert(vi.begin(), vi2.begin(), vi2.end()); + svi.insert(svi.begin(), svi2.begin(), svi2.end()); + vi.insert(vi.begin() + 3, 10101); + svi.insert(svi.begin() + 3, 10101); + vi.insert(vi.end(), (size_t)10, ptint (987)); + svi.insert(svi.end(), 10, 987); + check_expr(is_equal(vi, svi) == true); + vi.insert(vi.end(), vi2.begin() + 3, vi2.end()); + svi.insert(svi.end(), svi2.begin() + 3, svi2.end()); + pprint(vi, "\nvi after inserting a range and 10 identical numbers"); + check_expr(is_equal(vi, svi) == true); + + vi.assign(vi2.begin(), vi2.end()); + svi.assign(svi2.begin(), svi2.end()); + check_expr(is_equal(vi, svi) == true); + + vi.assign(vi2.begin(), vi2.end()); + svi.assign(svi2.begin(), svi2.end()); + check_expr(is_equal(vi, svi) == true); + pprint(vi, "vi before assigning"); + + vi.assign(vi2.begin() + 1, vi2.begin() + 3); + svi.assign(svi2.begin() + 1, svi2.begin() + 3); + check_expr(is_equal(vi, svi) == true); + vi.assign((size_t)10, ptint (141)); + svi.assign(10, 141); + check_expr(is_equal(vi, svi) == true); + + vi.insert(vi.begin(), vi2.begin(), vi2.end()); + svi.insert(svi.begin(), svi2.begin(), svi2.end()); + + vi.resize(vi.size() / 2); + svi.resize(svi.size() / 2); + check_expr(is_equal(vi, svi) == true); + vi.resize(vi.size() * 4); + svi.resize(svi.size() * 4); + check_expr(is_equal(vi, svi) == true); + + for (int ui = 0; ui < (int)svi.size(); ui++) { + svi[ui] = ui; + vi[ui] = ui; + } + + itr = vi.begin() + 3; + itr1 = vi.begin() + vi.size() - 8; + sitr = svi.begin() + 3; + sitr1 = svi.begin() + svi.size() - 8; + pprint(vi, "vi before erasing range: "); + vi.erase(itr, itr1); + svi.erase(sitr, sitr1); + check_expr(is_equal(vi, svi) == true); + + vi.clear(); + svi.clear(); + if ( EXPLICIT_TXN) + dbstl::commit_txn(penv); +} // test_member_functions + +// Testing list specific methods. +void TestVector::test_list_specific_member_functions() +{ + int i; + std::list<ptint> slvi; + std::list<ptint>::iterator slitr; + ptint_vector vi(db, penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + fill(vi, svi, 1,10); + for (i = 1; i < 11; i++) + slvi.push_back(i); + pprint(vi, "vi after fill: "); + vi.push_back(8); + vi.push_back(1); + vi.push_front(2); + vi.push_front(100); + vi.insert(vi.begin() + 4, 7); + slvi.push_back(8); + slvi.push_back(1); + slvi.push_front(2); + slvi.push_front(100); + slitr = slvi.begin(); + std::advance(slitr, 4); + slvi.insert(slitr, 7); + pprint(vi, "vi after push_back: "); + + vi.remove(8); + slvi.remove(8); + pprint(vi, "vi after remove(8): "); + check_expr(is_equal(vi, slvi)); + vi.remove_if(is7); + slvi.remove_if(is7); + check_expr(is_equal(vi, slvi)); + + vi.reverse(); + slvi.reverse(); + check_expr(is_equal(vi, slvi)); + + vi.sort(); + slvi.sort(); + check_expr(is_equal(vi, slvi)); + + vi.push_back(100); + slvi.push_back(100); + vi.push_front(1); + slvi.push_front(1); + pprint(vi, "vi before vi.unique():"); + vi.unique(); + slvi.unique(); + pprint(vi, "vi after vi.unique():"); + check_expr(is_equal(vi, slvi)); + + ptint_vector vi3(db3, penv); + list<ptint> slvi3; + + fill(vi3, svi, 4, 15); + for (i = 4; i < 19; i++) + slvi3.push_back(i); + + vi.merge(vi3); + slvi.merge(slvi3); + check_expr(is_equal(vi, slvi)); + pprint(vi3, "vi3 after merge:"); + check_expr(is_equal(vi3, slvi3)); + + vi3.clear(); + slvi3.clear(); + svi.clear(); + fill(vi3, svi, 4, 15); + for (i = 4; i < 19; i++) + slvi3.push_back(i); + + list<ptint>::iterator slitr2; + slitr = slvi3.begin(); + std::advance(slitr, 4); + slitr2 = slvi.begin(); + std::advance(slitr2, 6); + + pprint(vi, "vi before splice :"); + vi.splice(vi.begin() + 6, vi3, vi3.begin() + 4); + slvi.splice(slitr2, slvi3, slitr); + pprint(vi, "vi after splice :"); + check_expr(is_equal(vi, slvi)); + pprint(vi3, "vi3 after splice :"); + check_expr(is_equal(vi3, slvi3)); + + slitr = slvi3.begin(); + std::advance(slitr, 5); + vi.splice(vi.begin(), vi3, vi3.begin() + 5, vi3.end()); + slvi.splice(slvi.begin(), slvi3, slitr, slvi3.end()); + pprint(vi, "vi after splice :"); + pprint(vi3, "vi3 after splice :"); + check_expr(is_equal(vi, slvi)); + check_expr(is_equal(vi3, slvi3)); + + vi.splice(vi.end(), vi3); + slvi.splice(slvi.end(), slvi3); + pprint(vi, "vi after splice :"); + pprint(vi3, "vi3 after splice :"); + check_expr(is_equal(vi, slvi)); + check_expr(is_equal(vi3, slvi3)); + + vi.clear(); + vi3.clear(); + + check_expr(!(vi < vi3)); + fill(vi, svi, 1, 10); + + fill(vi3, svi3, 1, 10); + check_expr(!(vi < vi3)); + vi.push_front(0); + check_expr((vi < vi3)); + vi3.push_front(0); + vi.push_back(10); + check_expr((vi3 < vi)); + vi.erase(vi.begin()); + check_expr((vi3 < vi)); + + if ( EXPLICIT_TXN) + dbstl::commit_txn(penv); + +} + +// Use std algorithms to manipulate dbstl containers. +void TestVector::test_std_functions() +{ + ptint_vector::iterator itr1, itr; + ptint_vector::reverse_iterator ritr1, ritr; + vector<int>::iterator sitr, sitr1; + vector<int>::reverse_iterator rsitr, rsitr1; + ptint_vector vi(db, penv); + ptint_vector vi2(db2, penv); + ptint_vector vi3(db3, penv); + // test db_vector by applying it to each and every + // function in std algorithm + // + // for_each + // here after vi is supposed to be + // {6, 7, 8, 9, 10, 11, 12, 13, 14} + // + if (!TEST_AUTOCOMMIT) + dbstl::begin_txn(0, penv); + vi.clear(); + svi.clear(); + fill(vi, svi, 6, 9); + if (!TEST_AUTOCOMMIT) + dbstl::commit_txn(penv); + + if (EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + square squareobj; + cout<<"\nfor_each begin to end\n"; + for_each(vi.begin(), vi.end(), squareobj); + cout<<endl; + for_each(svi.begin(), svi.end(), squareobj); + cout<<"\nfor_each begin +2 to begin +6\n"; + for_each(vi.begin() + 2, vi.begin() + 6, squareobj); + cout<<endl; + for_each(svi.begin() + 2, svi.begin() + 6, squareobj); + + vector<int>::difference_type ssi = svi.rend() - svi.rbegin(); + ptint_vector::difference_type si; + si = vi.rend() - vi.rbegin(); + check_expr(ssi == si); + vector<int>::reverse_iterator sj = svi.rbegin() + 3; + cout<<"si, sj ="<<si<<'\t'<<*sj; + + //find + ptint tgt(12); + ptint_vector::iterator vpos = + find(vi.begin(), vi.end(), tgt); + check_expr(vpos != vi.end() && (ptint(*vpos) == tgt)); + vpos = find(vi.begin() + 3, vi.begin() + 7, tgt); + check_expr(vpos != vi.end() && (ptint(*vpos) == tgt)); + tgt = -123; + vpos = find(vi.begin(), vi.end(), tgt); + check_expr(vpos == vi.end()); + + // find_end + int subseq[] = {8, 9, 10}; +#ifdef WIN32 + // C++ STL specification requires this equivalence relation hold for + // any iterators: + // "itr1==itr2" <===> "&*itr1 == &*itr2" + // this means that each iterator don't hold value for themselvs, + // but refer to a shared piece of memory held by its container object, + // which is not true for dbstl. The impl of find_end in gcc's stl lib + // relies on this requirement, but not for MS's stl lib. So this test + // only runs on WIN32. + pprint(vi, "vi before find_end(): "); + vpos = find_end(vi.begin(), vi.end(), vi.begin(), vi.begin() + 1); + check_expr(vpos == vi.begin()); + vpos = find_end(vi.begin(), vi.end(), vi.begin() + 3, + vi.begin() + 5); + check_expr(vpos == vi.begin() + 3); + vpos = find_end(vi.begin() + 1, vi.end(), subseq, subseq + 3); + check_expr(vpos == vi.begin() + 2); +#endif + //search + vpos = search(vi.begin(), vi.end(), vi.begin(), vi.begin() + 1); + check_expr(vpos == vi.begin()); + vpos = search(vi.begin(), vi.end(), vi.begin() + 3, vi.begin() + 5); + check_expr(vpos == vi.begin() + 3); + vpos = search(vi.begin() + 1, vi.end(), subseq, subseq + 3); + check_expr(vpos == vi.begin() + 2); + + // find_first_of + vpos = find_first_of(vi.begin(), vi.end(), vi.begin(), + vi.begin() + 1); + check_expr(vpos == vi.begin()); + vpos = find_first_of(vi.begin() + 2, vi.begin() + 6, + vi.begin() + 4, vi.begin() + 5); + check_expr(vpos == vi.begin() + 4); + int subseq2[] = {9, 8, 10, 11}; + vpos = find_first_of(vi.begin() + 1, vi.begin() + 7, + subseq2, subseq2 + 4); + check_expr(vpos == vi.begin() + 2); + vpos = find_first_of(vi.begin() + 6, vi.end(), + subseq2, subseq2 + 4); + check_expr(vpos == vi.end()); + + //find_if + vpos = find_if(vi.begin(), vi.end(), is2digits); + check_expr(ptint(*vpos) == 10); + vpos = find_if(vi.begin() + 5, vi.begin() + 8, is2digits); + check_expr(ptint(*vpos) == 11); + vpos = find_if(vi.begin() + 1, vi.begin() + 3, is2digits); + check_expr(vpos == vi.begin() + 3); + + // count_if + ptint_vector::difference_type oddcnt = + count_if(vi.begin(), vi.end(), is_odd); + check_expr(oddcnt == 4); + oddcnt = count_if(vi.begin(), vi.begin() + 5, is_odd); + check_expr(oddcnt == 2); + oddcnt = count_if(vi.begin(), vi.begin(), is_odd); + check_expr(oddcnt == 0); + + // mismatch + pair<intvec_t::iterator , int*> resmm = mismatch(vi.begin(), + vi.begin() + 3, subseq); + check_expr(resmm.first == vi.begin() && resmm.second == subseq); + resmm = mismatch(vi.begin() + 2, vi.begin() + 5, subseq); + check_expr(resmm.first == vi.begin() + 5 && resmm.second == subseq + 3); + resmm = mismatch(vi.begin() + 2, vi.begin() + 4, subseq); + check_expr(resmm.first == vi.begin() + 4 && resmm.second == subseq + 2); + + //equal + check_expr (equal(vi.begin(), vi.begin() + 3, subseq) == false); + check_expr(equal(vi.begin() + 2, vi.begin() + 5, subseq) == true); + check_expr(equal(vi.begin() + 2, vi.begin() + 4, subseq) == true); + if ( EXPLICIT_TXN) { + dbstl::commit_txn(penv); + dbstl::begin_txn(0, penv); + } + //copy + pprint(vi2, "\nvi2 before copying"); + pprint(vi, "\nvi1 before copying"); + copy(vi.begin(), vi.begin() + 3, vi2.begin() + 1); + copy(svi.begin(), svi.begin() + 3, svi2.begin() + 1); + // vi2 should be 0, 6, 7, 8,4 + int vi22[] = { 0, 6, 7, 8,4}; + pprint(vi2, "\nvi2 after copying"); + check_expr(equal(vi2.begin(), vi2.end(), vi22) == true); + check_expr(is_equal(vi, svi)); + + // copy_backward + copy_backward(vi.begin(), vi.begin() + 3, vi.begin() + 8); + copy_backward(svi.begin(), svi.begin() + 3, svi.begin() + 8); + pprint(vi);// should be 6,7,8,9,10,6,7,8,14 + check_expr(is_equal(vi, svi)); + + copy_backward(vi.begin(), vi.begin() + 4, vi.begin() + 6); + copy_backward(svi.begin(), svi.begin() + 4, svi.begin() + 6); + pprint(vi);// should be 6,7, 6,7, 8, 9, 7, 8, 14 + check_expr(is_equal(vi, svi)); + copy_backward(vi.begin() + 7, vi.end(), vi.begin() + 5); + copy_backward(svi.begin() + 7, svi.end(), svi.begin() + 5); + pprint(vi);//should be 6,7,6,8,14,8,14,8,14 + check_expr(is_equal(vi, svi)); //here the check_expr fails but I think + //the values in vi are right, those in svi are wrong + + + // swap_ranges + swap_ranges(vi.begin() + 3, vi.begin() + 7, vi.begin() + 4); + swap_ranges(svi.begin() + 3, svi.begin() + 7, svi.begin() + 4); + check_expr(is_equal(vi, svi)); + + /* + * std::swap can only swap data of same type, so following tests + * do not compile, we can provide our own swap(T, ElementRef<T>) + * func to address this + */ + vector<ptint> spvi, spvi2; + spvi.insert(spvi.begin(), svi.begin(), svi.end()); + spvi2.insert(spvi2.begin(), svi2.begin(), svi2.end()); + swap_ranges(vi.begin() + 3, vi.begin() + 5, spvi.begin() + 6); + swap_ranges(spvi.begin() + 3, spvi.begin() + 5, vi.begin() + 6); + check_expr(is_equal(vi, spvi)); + + swap_ranges(spvi.begin() + 3, spvi.begin() + 7, vi.begin() + 5); + //swap back + swap_ranges(spvi.begin() + 3, spvi.begin() + 7, vi.begin() + 5); + check_expr(is_equal(vi, spvi)); + + transform(vi2.begin(), vi2.end(), vi.begin() + 2, + vi.begin() + 4, addup); + transform(spvi2.begin(), spvi2.end(), spvi.begin() + 2, + spvi.begin() + 4, addup); + check_expr(is_equal(vi, spvi)); + + replace(vi.begin(), vi.end(), 8, 88); + replace(spvi.begin(), spvi.end(), 8, 88); + check_expr(is_equal(vi, spvi)); + + generate(vi.begin(), vi.begin() + 2, randint); + generate(spvi.begin(), spvi.begin() + 2, randint); + pprint(vi); + check_expr(is_equal(vi, spvi)); + + remove(vi.begin(), vi.end(), -999); + remove(spvi.begin(), spvi.end(), -999); + pprint(vi, "\nafter remove"); + check_expr(is_equal(vi, spvi)); + + reverse(vi.begin(), vi.end()); + reverse(spvi.begin(), spvi.end()); + pprint(vi, "\nafter reverse"); + check_expr(is_equal(vi, spvi)); + + rotate(vi.begin() + 1, vi.begin() + 5, vi.end()); + rotate(spvi.begin() + 1, spvi.begin() + 5, spvi.end()); + pprint(vi, "\n after rotate"); + check_expr(is_equal(vi, spvi)); + + separator<ptint> part; + part.mid = 11; + partition(vi.begin(), vi.end(), part); + partition(spvi.begin(), spvi.end(), part); + pprint(vi, "\nafter partition"); + check_expr(is_equal(vi, spvi)); + + sort(vi.begin(), vi.end()); + sort(spvi.begin(), spvi.end()); + check_expr(is_equal(vi, spvi)); + + random_shuffle(vi.begin(), vi.end()); + random_shuffle(spvi.begin(), spvi.end()); + pprint(vi, "\nvi after random_shuffle"); + sort(vi.begin(), vi.end()); + sort(spvi.begin(), spvi.end()); + pprint(vi, "\nvi after sort"); + check_expr(is_equal(vi, spvi)); + + random_shuffle(vi2.begin(), vi2.end()); + random_shuffle(spvi2.begin(), spvi2.end()); +#ifdef WIN32 + // The implementation of __get_temporary_buffer in g++'s stl + // lib makes it impossible to correctly use ElementHolder or + // ElementRef<>, so this function dose not work with dbstl on gcc. + stable_sort(vi2.begin(), vi2.end()); + stable_sort(spvi2.begin(), spvi2.end()); +#else + sort(vi2.begin(), vi2.end()); + sort(spvi2.begin(), spvi2.end()); +#endif + check_expr(is_equal(vi2, spvi2)); + + random_shuffle(vi2.begin(), vi2.end()); + random_shuffle(spvi2.begin(), spvi2.end()); + pprint(vi2); + sort(vi2.begin(), vi2.end()); + sort(spvi2.begin(), spvi2.end()); + pprint(vi2); + check_expr(is_equal(vi2, spvi2)); + + vi3.clear(); + vi3.insert(vi3.begin(), (size_t)100, ptint(0)); + vector<ptint> spvi3(100); + merge(vi.begin(), vi.end(), vi2.begin(), vi2.end(), vi3.begin()); + merge(spvi.begin(), spvi.end(), spvi2.begin(), spvi2.end(), + spvi3.begin()); + pprint(vi3, "\n vi3 after merge vi1 with vi2:"); + check_expr(is_equal(vi3, spvi3)); + + spvi3.clear(); + vi3.clear(); + sort(vi2.begin(), vi2.end()); + sort(spvi2.begin(), spvi2.end()); + pprint(vi2, "\nvi2 after sort:"); + vi3.insert(vi3.begin(), vi2.begin(), vi2.end()); + pprint(vi3, "\nvi3 after insert vi2 at beginning"); + spvi3.insert(spvi3.begin(), spvi2.begin(), spvi2.end()); + vi3.insert(vi3.begin(), vi.begin(), vi.end()); + spvi3.insert(spvi3.begin(), spvi.begin(), spvi.end()); + pprint(vi3, "\nvi3: v1 v2 combined in this order"); +#ifdef WIN32 + // The implementation of __get_temporary_buffer in g++'s stl + // lib makes it impossible to correctly use ElementHolder or + // ElementRef<>, so this function dose not work with dbstl on gcc. + inplace_merge(vi3.begin(), vi3.begin() + (vi.end() - vi.begin()), + vi3.end()); + inplace_merge(spvi3.begin(), spvi3.begin() + (spvi.end() - + spvi.begin()), spvi3.end()); +#endif + check_expr(is_equal(vi3, spvi3)); + make_heap(vi3.begin(), vi3.end()); + make_heap(spvi3.begin(), spvi3.end()); + check_expr(is_equal(vi3, spvi3)); + cout<<endl<<"pop_heap test"<<endl; + + int r ; + int rdcnt = 0; + while (vi3.size() > 0) { + rdcnt++; + + pop_heap(vi3.begin(), vi3.end()); + vi3.pop_back(); + pop_heap(spvi3.begin(), spvi3.end()); + spvi3.pop_back(); + pprint(vi3); + + } + cout<<endl<<"push_heap test"<<endl; + rdcnt = 0; + while (vi3.size() < 10) { + rdcnt++; + r = rand(); + vi3.push_back(ptint(r)); + push_heap(vi3.begin(), vi3.end()); + spvi3.push_back(ptint(r)); + push_heap(spvi3.begin(), spvi3.end()); + check_expr(is_equal(vi3, spvi3)); + } + + vi.clear(); + vi2.clear(); + vi3.clear(); + if ( EXPLICIT_TXN) + dbstl::commit_txn(penv); + +} // void test_std_functions() + +void TestVector::test_primitive() +{ + + int i; + + if ( EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + + + db_vector<int, ElementHolder<int> > ivi(db, penv); + vector<int> spvi4; + fill(ivi, spvi4); + check_expr(is_equal(ivi, spvi4)); + ivi.clear(false); + + db_vector<int, ElementHolder<int> > ivi2(db, penv); + vector<int> spvi5; + fill(ivi2, spvi5); + check_expr(is_equal(ivi2, spvi5)); + size_t vsz = ivi2.size(); + for (i = 0; i < (int)vsz - 1; i++) { + ivi2[i] += 3; + ivi2[i]--; + ivi2[i] <<= 2; + ivi2[i] = (~ivi2[i] | ivi2[i] & ivi2[i + 1] ^ (2 * (-ivi2[i + 1]) + ivi2[i]) * 3) / (ivi2[i] * ivi2[i + 1] + 1); + + spvi5[i] += 3; + spvi5[i]--; + spvi5[i] <<= 2; + spvi5[i] = (~spvi5[i] | spvi5[i] & spvi5[i + 1] ^ (2 * (-spvi5[i + 1]) + spvi5[i]) * 3) / (spvi5[i] * spvi5[i + 1] + 1); + } + check_expr(is_equal(ivi2, spvi5)); + ivi2.clear(false); + + db_vector<ptype<int> > ivi3(db, penv); + vector<int> spvi6; + fill(ivi3, spvi6); + check_expr(is_equal(ivi3, spvi6)); + ivi3.clear(false); + + typedef db_vector<double, ElementHolder<double> > dbl_vct_t; + dbl_vct_t dvi(db, penv); + vector<double> dsvi; + for (i = 0; i < 10; i++) { + dvi.push_back(i * 3.14); + dsvi.push_back(i * 3.14); + } + check_expr(is_equal(dvi, dsvi)); + + dbl_vct_t::iterator ditr; + vector<double>::iterator sditr; + for (ditr = dvi.begin(), sditr = dsvi.begin(); + ditr != dvi.end(); ++ditr, ++sditr){ + *ditr *= 2; + *sditr *= 2; + } + + check_expr(is_equal(dvi, dsvi)); + + for (i = 0; i < 9; i++) { + dvi[i] /= (-dvi[i] / 3 + 2 * dvi[i + 1]) / (1 + dvi[i]) + 1; + dsvi[i] /= (-dsvi[i] / 3 + 2 * dsvi[i + 1]) / (1 + dsvi[i]) + 1; + } + cout<<"\ndvi after math operations: \n"; + pprint(dvi); + cout<<"\ndsvi after math operations: \n"; + for (i = 0; i <= 9; i++) + cout<<dsvi[i]<<" "; + for (i = 0; i < 10; i++) { + cout<<i<<"\t"; + check_expr((int)(dvi[i] * 100000) == (int)(dsvi[i] * 100000)); + } + + if ( EXPLICIT_TXN) + dbstl::commit_txn(penv); +} // test_primitive + +void TestVector::test_queue_stack() +{ + int i; + + if ( EXPLICIT_TXN) + dbstl::begin_txn(0, penv); + ptint_vector vi3(db3, penv); + // test whether db_vector works with std::queue, + // std::priority_queue and std::stack + cout<<"\n_testing db_vector working with std::queue\n"; + vi3.clear(); + + // std::queue test + intvec_t quev(quedb, penv); + quev.clear(); + std::queue<ptint, intvec_t> intq(quev); + std::queue<ptint> sintq; + check_expr(intq.empty()); + check_expr(intq.size() == 0); + for (i = 0; i < 100; i++) { + intq.push(ptint(i)); + sintq.push(i); + check_expr(intq.front() == 0); + check_expr(intq.back() == i); + } + check_expr(intq.size() == 100); + for (i = 0; i < 100; i++) { + check_expr(intq.front() == i); + check_expr(intq.back() == 99); + check_expr(intq.front() == sintq.front()); + check_expr(sintq.back() == intq.back()); + sintq.pop(); + intq.pop(); + } + check_expr(intq.size() == 0); + check_expr(intq.empty()); + quev.clear(); + + // std::priority_queue test + cout<<"\n_testing db_vector working with std::priority_queue\n"; + + std::vector<ptint> squev; + intvec_t pquev(pquedb, penv); + pquev.clear(); + std::priority_queue<ptint, intvec_t, ptintless_ft> intpq(ptintless, pquev); + std::priority_queue<ptint, vector<ptint>, ptintless_ft> + sintpq(ptintless, squev); + + check_expr(intpq.empty()); + check_expr(intpq.size() == 0); + ptint tmppq, tmppq1; + set<ptint> ptintset; + for (i = 0; i < 100; i++) { + for (;;) {// avoid duplicate + tmppq = rand(); + if (ptintset.count(tmppq) == 0) { + intpq.push(tmppq); + sintpq.push(tmppq); + ptintset.insert(tmppq); + break; + } + } + + } + check_expr(intpq.empty() == false); + check_expr(intpq.size() == 100); + for (i = 0; i < 100; i++) { + tmppq = intpq.top(); + tmppq1 = sintpq.top(); + if (i == 98 && tmppq != tmppq1) { + tmppq = intpq.top(); + } + if (i < 98) + check_expr(tmppq == tmppq1); + if (i == 97) + intpq.pop(); + else + intpq.pop(); + sintpq.pop(); + } + check_expr(intpq.empty()); + check_expr(intpq.size() == 0); + + + // std::stack test + cout<<"\n_testing db_vector working with std::stack\n"; + std::stack<ptint, intvec_t> intstk(quev); + std::stack<ptint> sintstk; + check_expr(intstk.size() == 0); + check_expr(intstk.empty()); + for (i = 0; i < 100; i++) { + intstk.push(ptint(i)); + sintstk.push(ptint(i)); + check_expr(intstk.top() == i); + check_expr(intstk.size() == (size_t)i + 1); + } + + for (i = 99; i >= 0; i--) { + check_expr(intstk.top() == ptint(i)); + check_expr(intstk.top() == sintstk.top()); + sintstk.pop(); + intstk.pop(); + check_expr(intstk.size() == (size_t)i); + } + check_expr(intstk.size() == 0); + check_expr(intstk.empty()); + + // Vector with no handles specified. + ptint_vector simple_vct(10); + vector<ptint> ssvct(10); + for (i = 0; i < 10; i++) { + simple_vct[i] = ptint(i); + ssvct[i] = ptint(i); + } + check_expr(is_equal(simple_vct, ssvct)); + + if ( EXPLICIT_TXN) + dbstl::commit_txn(penv); + + return; +} // test_queue_stack diff --git a/db-4.8.30/test_stl/run_base.sh b/db-4.8.30/test_stl/run_base.sh new file mode 100644 index 0000000..34e7c29 --- /dev/null +++ b/db-4.8.30/test_stl/run_base.sh @@ -0,0 +1,92 @@ +#run_test.sh +run_test() +{ +prog=$1 +mkdir -p ./dbenv +rm -rf dbenv/* +echo "Auto commit btree transaction tests:" +$prog -s b -m t -t a -T 200 -k 50 -l 100 -c 33554432 -n $2 >/dev/null +echo "Transaction btree tests:" +$prog -s b -m t -t e -T 200 -k 50 -l 100 -c 33554432 -n $2 >/dev/null +echo "CDS btree tests:" +$prog -s b -m c -T 200 -k 50 -l 100 -c 33554432 -n $2 >/dev/null +echo "DS btree tests:" +$prog -s b -T 200 -k 50 -l 100 -c 33554432 -n $2 >/dev/null +echo "Auto commit hash transaction tests:" +$prog -s h -m t -t a -T 200 -k 50 -l 100 -c 33554432 -n $2 >/dev/null +echo "Transaction hash tests:" +$prog -s h -m t -t e -T 200 -k 50 -l 100 -c 33554432 -n $2 >/dev/null +echo "CDS hash tests:" +$prog -s h -m c -T 200 -k 50 -l 100 -c 33554432 -n $2 >/dev/null +echo "DS hash tests:" +$prog -s h -T 200 -k 50 -l 100 -c 33554432 -n $2 >/dev/null +} + +run_mt() +{ +prog=$1 +echo "Transaction btree multithreaded tests:" +$prog -s b -m t -t e -T 200 -k 50 -l 100 -c 33554432 -M > mt_test_btree_tds.out +echo "Transaction btree multithreaded tests(auto commit):" +$prog -s b -m t -t e -T 200 -k 50 -l 100 -c 33554432 -M > mt_test_btree_tds_autocommit.out + +echo "Transaction hash multithreaded tests:" +$prog -s h -m t -t e -T 200 -k 50 -l 100 -c 33554432 -M > mt_test_hash_tds.out +echo "Transaction hash multithreaded tests:" +$prog -s h -m t -t e -T 200 -k 50 -l 100 -c 33554432 -M > mt_test_hash_tds_autocommit.out +# This test is not suitable for CDS mode because the writers will not stop inserting to +# the database until the reader reads enough key/data pairs, but the readers will never +# have a chance to open its cursor read any key/data pair since the write is writing to db. +} +run_tpcb() +{ +prog=$1 + +mkdir -p ./dbenv +rm -fr dbenv/* + +$prog -i +$prog -n $2 + +} +os=`uname -s` +ntimes=1 +mttest=0 +if test "$1" = "tpcb" ; then #running tpcb test. + if test $# -gt 1 ; then + ntimes=$2 + fi + + if test "$os" = "CYGWIN_NT-5.1" ; then + run_tpcb "../build_windows/Win32/Release/exstl_tpcb.exe" $ntimes + else + run_tpcb "../build_unix/exstl_tpcb" $ntimes + fi +else + if test "$1" = "mt" ; then #running ordinary test. + mttest=1 + elif test $# -eq 2 ; then + ntimes=$2 + fi + + if test "$os" = "CYGWIN_NT-5.1" ; then + echo "Debug version test" + if test $mttest -eq 1 ; then + run_mt "../build_windows/Win32/Debug/stl_test.exe" + else + run_test "../build_windows/Win32/Debug/stl_test.exe" $ntimes + fi + echo "Release version test" + if test $mttest -eq 1 ; then + run_mt "../build_windows/Win32/Release/stl_test.exe" + else + run_test "../build_windows/Win32/Release/stl_test.exe" $ntimes + fi + else + if test $mttest -eq 1 ; then + run_mt "../build_unix/test_dbstl" + else + run_test "../build_unix/test_dbstl" $ntimes + fi + fi +fi diff --git a/db-4.8.30/test_stl/run_base_profile.sh b/db-4.8.30/test_stl/run_base_profile.sh new file mode 100644 index 0000000..a0c9b6f --- /dev/null +++ b/db-4.8.30/test_stl/run_base_profile.sh @@ -0,0 +1,63 @@ +#run_test.sh +run_test() +{ +prog=$1 +mkdir -p ./dbenv +rm -f -r dbenv/* + +echo "Auto commit btree transaction tests:" >&2 + $prog -s b -m t -t a -T 200 -k 50 -l 100 -c 33554432 -n $total && mv gmon.out gmon${i}.out + i=`expr $i + 1` + +echo "Transaction btree tests:" >&2 + $prog -s b -m t -t e -T 200 -k 50 -l 100 -c 33554432 -n $total && mv gmon.out gmon${i}.out + i=`expr $i + 1` +echo "CDS btree tests:" >&2 + $prog -s b -m c -T 200 -k 50 -l 100 -c 33554432 -n $total && mv gmon.out gmon${i}.out + i=`expr $i + 1` + +echo "DS btree tests:" >&2 + $prog -s b -T 200 -k 50 -l 100 -c 33554432 -n $total && mv gmon.out gmon${i}.out + i=`expr $i + 1` + +echo "Auto commit hash transaction tests:" >&2 + $prog -s h -m t -t a -T 200 -k 50 -l 100 -c 33554432 -n $total && mv gmon.out gmon${i}.out + i=`expr $i + 1` + +echo "Transaction hash tests:" >&2 + $prog -s h -m t -t e -T 200 -k 50 -l 100 -c 33554432 -n $total && mv gmon.out gmon${i}.out + i=`expr $i + 1` + +echo "CDS hash tests:" >&2 + $prog -s h -m c -T 200 -k 50 -l 100 -c 33554432 -n $total && mv gmon.out gmon${i}.out + i=`expr $i + 1` + +echo "DS hash tests:" >&2 + $prog -s h -T 200 -k 50 -l 100 -c 33554432 -n $total && mv gmon.out gmon${i}.out + i=`expr $i + 1` +} + +if test $# -ne 1 ; then + echo "Usage: sh run_test.sh number-of-run-in-a-loop" + exit 1 +fi + +total=$1 +i=0 +os=`uname -s` + +if test $os = "CYGWIN_NT-5.1" ; then + run_test "../build_windows/Win32/Debug/test.exe" +else + run_test "../build_unix/test_dbstl" +fi + +ii=0 +profiles="" + +while [ $ii -lt $i ]; do + profiles="${profiles} gmon${ii}.out" + ii=`expr $ii + 1` +done +echo "Generating profiling report..." >&2 +gprof $1/.libs/test_dbstl $profiles > gprof.out diff --git a/db-4.8.30/test_stl/run_msdbstl.sh b/db-4.8.30/test_stl/run_msdbstl.sh new file mode 100644 index 0000000..62e5c74 --- /dev/null +++ b/db-4.8.30/test_stl/run_msdbstl.sh @@ -0,0 +1,77 @@ +#! /bin/sh + +MS_TEST_PATH="ms_examples" + +cnt=0 +run_test() +{ +prog=$1 +rm -f ms_db_stl_result.out +$prog -e d -s h -c 67108864 < ./ms_examples/ms_db_stl.in > ms_db_stl_result.out +echo "ms db stl test and ms std stl test result diff: " +diff ./ms_db_stl_result.out ./ms_examples/ms_db_stl_result.expected > ms_db_stl-std_stl-results$cnt.diff +cnt=`expr $cnt + 1` + +rm -f ms_db_stl_result.out +$prog -e d -s b -c 67108864 <./ms_examples/ms_db_stl.in > ms_db_stl_result.out +echo "ms db stl test and ms std stl test result diff: " +diff ms_db_stl_result.out ./ms_examples/ms_db_stl_result.expected > ms_db_stl-std_stl-results$cnt.diff +cnt=`expr $cnt + 1` + +rm -f ms_db_stl_result.out +$prog -e c -s h -c 67108864 <ms_examples/ms_db_stl.in > ms_db_stl_result.out +echo "ms db stl test and ms std stl test result diff: " +diff ms_db_stl_result.out ./ms_examples/ms_db_stl_result.expected > ms_db_stl-std_stl-results$cnt.diff +cnt=`expr $cnt + 1` + +rm -f ms_db_stl_result.out +$prog -e c -s b -c 67108864 <ms_examples/ms_db_stl.in > ms_db_stl_result.out +echo "ms db stl test and ms std stl test result diff: " +diff ms_db_stl_result.out ./ms_examples/ms_db_stl_result.expected > ms_db_stl-std_stl-results$cnt.diff +cnt=`expr $cnt + 1` + +rm -f ms_db_stl_result.out +$prog -e t -s h -t a -c 67108864 <ms_examples/ms_db_stl.in > ms_db_stl_result.out +echo "ms db stl test and ms std stl test result diff: " +diff ms_db_stl_result.out ./ms_examples/ms_db_stl_result.expected > ms_db_stl-std_stl-results$cnt.diff +cnt=`expr $cnt + 1` + +rm -f ms_db_stl_result.out +$prog -e t -s h -t e -c 67108864 <ms_examples/ms_db_stl.in > ms_db_stl_result.out +echo "ms db stl test and ms std stl test result diff: " +diff ms_db_stl_result.out ./ms_examples/ms_db_stl_result.expected > ms_db_stl-std_stl-results$cnt.diff +cnt=`expr $cnt + 1` + +rm -f ms_db_stl_result.out +$prog -e t -s b -t a -c 67108864 <ms_examples/ms_db_stl.in > ms_db_stl_result.out +echo "ms db stl test and ms std stl test result diff: " +diff ms_db_stl_result.out ./ms_examples/ms_db_stl_result.expected > ms_db_stl-std_stl-results$cnt.diff +cnt=`expr $cnt + 1` + +rm -f ms_db_stl_result.out +$prog -e t -s b -t e -c 67108864 <ms_examples/ms_db_stl.in > ms_db_stl_result.out +echo "ms db stl test and ms std stl test result diff: " +diff ms_db_stl_result.out ./ms_examples/ms_db_stl_result.expected > ms_db_stl-std_stl-results$cnt.diff +cnt=`expr $cnt + 1` + +rm -f ms_db_stl_result.out +$prog <ms_examples/ms_db_stl.in > ms_db_stl_result.out +echo "ms db stl test and ms std stl test result diff: " +diff ms_db_stl_result.out ./ms_examples/ms_db_stl_result.expected > ms_db_stl-std_stl-results$cnt.diff +cnt=`expr $cnt + 1` + +} +os=`uname -s` +#ms_example_std_stl +oldwd=`pwd` +if test $os = "CYGWIN_NT-5.1" ; then + prog=../build_windows/Win32/Debug/stl_test_msexamples.exe + run_test $prog + prog=../build_windows/Win32/Release/stl_test_msexamples.exe + run_test $prog +else + prog=./ms_examples/ms_example_db_stl + run_test $prog +fi +cd $oldwd + diff --git a/db-4.8.30/test_stl/run_stlport.sh b/db-4.8.30/test_stl/run_stlport.sh new file mode 100644 index 0000000..44b1ae2 --- /dev/null +++ b/db-4.8.30/test_stl/run_stlport.sh @@ -0,0 +1,24 @@ +run_test() +{ +prog=$1 +out=$2.out +dif=$2.diff +rm -f $out +rm -f $dif +$prog > $out +if [ $# -gt 2 ]; then + dos2unix -U $out +fi +diff $out ./stlport/stl_test.expected > $dif +} + +os=`uname -s` +if test $os = "CYGWIN_NT-5.1" ; then + prog=../build_windows/Win32/Debug/stl_test_stlport.exe + run_test $prog "stlport_results_dbg" 1 + prog=../build_windows/Win32/Release/stl_test_stlport.exe + run_test $prog "stlport_results_rel" 1 +else + prog=./stlport/stl_port_test + run_test $prog "stlport_results" +fi |