testodbcdriver.cpp

来自「MySQL数据库开发源码 值得一看哦」· C++ 代码 · 共 2,237 行 · 第 1/5 页

CPP
2,237
字号
/* Copyright (C) 2003 MySQL AB   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* Copyright (C) 2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* * testOdbcDriver * * Test of ODBC and SQL using a fixed set of tables. */#include <ndb_global.h>#undef test#include <ndb_version.h>#include <kernel/ndb_limits.h>#include <Bitmask.hpp>#include <kernel/AttributeList.hpp>#ifdef ndbODBC#include <NdbApi.hpp>#endif#include <sqlext.h>#undef BOOL#include <NdbMain.h>#include <NdbOut.hpp>#include <NdbThread.h>#include <NdbMutex.h>#include <NdbCondition.h>#include <NdbTick.h>#include <NdbSleep.h>#ifdef ndbODBC#include <NdbTest.hpp>#else#define NDBT_OK			0#define NDBT_FAILED		1#define NDBT_WRONGARGS		2static intNDBT_ProgramExit(int rcode){    const char* rtext = "Unknown";    switch (rcode) {    case NDBT_OK:	rtext = "OK";	break;    case NDBT_FAILED:	rtext = "Failed";	break;    case NDBT_WRONGARGS:	rtext = "Wrong arguments";	break;    };    ndbout_c("\nNDBT_ProgramExit: %d - %s\n", rcode, rtext);    return rcode;}#endif#ifdef DMALLOC#include <dmalloc.h>#endif#define arraySize(x)	(sizeof(x)/sizeof(x[0]))#define SQL_ATTR_NDB_TUPLES_FETCHED	66601// options#define MAX_THR		128		// max threadsstruct Opt {    const char* m_name[100];    unsigned m_namecnt;    bool m_core;    unsigned m_depth;    const char* m_dsn;    unsigned m_errs;    const char* m_fragtype;    unsigned m_frob;    const char* m_home;    unsigned m_loop;    bool m_nogetd;    bool m_noputd;    bool m_nosort;    unsigned m_scale;    bool m_serial;    const char* m_skip[100];    unsigned m_skipcnt;    unsigned m_subloop;    const char* m_table;    unsigned m_threads;    unsigned m_trace;    unsigned m_v;    Opt() :	m_namecnt(0),	m_core(false),	m_depth(5),	m_dsn("NDB"),	m_errs(0),        m_fragtype(0),        m_frob(0),	m_home(0),	m_loop(1),	m_nogetd(false),	m_noputd(false),	m_nosort(false),	m_scale(100),	m_serial(false),	m_skipcnt(0),	m_subloop(1),	m_table(0),	m_threads(1),	m_trace(0),	m_v(1) {	for (unsigned i = 0; i < arraySize(m_name); i++)	    m_name[i] = 0;	for (unsigned i = 0; i < arraySize(m_skip); i++)	    m_skip[i] = 0;    }};static Opt opt;static void listCases();static void listTables();static void printusage(){    Opt d;    ndbout	<< "usage: testOdbcDriver [options]" << endl	<< "-case name  run only named tests (substring match - can be repeated)" << endl	<< "-core       dump core on failure" << endl	<< "-depth N    join depth - default " << d.m_depth << endl	<< "-dsn string data source name - default " << d.m_dsn << endl	<< "-errs N     allow N errors before quitting - default " << d.m_errs << endl        << "-fragtype t fragment type single/small/medium/large" << d.m_errs << endl        << "-frob X     case-dependent tweak (number)" << endl	<< "-home dir   set NDB_HOME (contains Ndb.cfg)" << endl	<< "-loop N     loop N times (0 = forever) - default " << d.m_loop << endl	<< "-nogetd     do not use SQLGetData - default " << d.m_nogetd << endl	<< "-noputd     do not use SQLPutData - default " << d.m_noputd << endl	<< "-nosort     no order-by in verify scan (checks non-Pk values only)" << endl	<< "-scale N    row count etc - default " << d.m_scale << endl	<< "-serial     run multi-threaded test cases one at a time" << endl	<< "-skip name  skip named tests (substring match - can be repeated)" << endl	<< "-subloop N  loop count per case (same threads) - default " << d.m_subloop << endl	<< "-table T    do only table T (table name on built-in list)" << endl	<< "-threads N  number of threads (max " << MAX_THR << ") - default " << d.m_threads << endl	<< "-trace N    trace in NDB ODBC driver - default " << d.m_trace << endl	<< "-v N        verbosity - default " << d.m_v << endl	;    listCases();    listTables();}static voidfatal(const char* fmt, ...){    va_list ap;    char buf[200];    va_start(ap, fmt);    vsnprintf(buf, sizeof(buf), fmt, ap);    va_end(ap);    ndbout << buf << endl;    if (opt.m_errs != 0) {	opt.m_errs--;	return;    }    if (opt.m_core)	abort();    NDBT_ProgramExit(NDBT_FAILED);    exit(1);}static voidcleanprint(const char* s, unsigned n){    for (unsigned i = 0; i < n; i++) {	char b[10];	if (0x20 < s[i] && s[i] <= 0x7e)	    sprintf(b, "%c", s[i]);	else	    sprintf(b, "\\%02x", (unsigned)s[i]);	ndbout << b;    }}// global mutexstatic NdbMutex my_mutex = NDB_MUTEX_INITIALIZER;static void lock_mutex() { NdbMutex_Lock(&my_mutex); }static void unlock_mutex() { NdbMutex_Unlock(&my_mutex); }// semaphore zeroed before each call to a test routinestatic unsigned my_sema = 0;// print mutexstatic NdbMutex out_mutex = NDB_MUTEX_INITIALIZER;static NdbOut& lock(NdbOut& out) { NdbMutex_Lock(&out_mutex); return out; }static NdbOut& unlock(NdbOut& out) { NdbMutex_Unlock(&out_mutex); return out; }static unsignedurandom(unsigned n){    assert(n != 0);    unsigned i = random();    return i % n;}// test casesstruct Test;struct Case {    enum Mode {	Single = 1,		// single thread	Serial = 2,		// all threads but one at a time	Thread = 3		// all threads in parallel    };    const char* m_name;    void (*m_func)(Test& test);    Mode m_mode;    unsigned m_stuff;    const char* m_desc;    Case(const char* name, void (*func)(Test& test), Mode mode, unsigned stuff, const char* desc) :	m_name(name),	m_func(func),	m_mode(mode),	m_stuff(stuff),	m_desc(desc) {    }    const char* modename() const {	const char* s = "?";	if (m_mode == Case::Single)	    return "Single";	if (m_mode == Case::Serial)	    return "Serial";	if (m_mode == Case::Thread)	    return "Thread";	return "?";    }    bool matchcase() const {	if (opt.m_namecnt == 0)	    return ! skipcase();	for (unsigned i = 0; i < opt.m_namecnt; i++) {	    if (strstr(m_name, opt.m_name[i]) != 0)		return ! skipcase();	}	return false;    }private:    bool skipcase() const {	for (unsigned i = 0; i < opt.m_skipcnt; i++) {	    if (strstr(m_name, opt.m_skip[i]) != 0)		return true;	}	return false;    }};// calculate valuesstruct Calc {    enum { m_mul = 1000000 };    unsigned m_no;    unsigned m_base;    unsigned m_salt;		// modifies non-PK values    bool m_const;		// base non-PK values on PK of row 0    Calc(unsigned no) :	m_no(no),	m_salt(0),	m_const(false) {	m_base = m_no * m_mul;    }    void calcPk(unsigned rownum, char* v, unsigned n) const {	char b[10];	sprintf(b, "%08x", m_base + rownum);	for (unsigned i = 0; i < n; i++) {	    char c = i < n - 1 ? b[i % 8] : 0;	    v[i] = c;	}    }    void calcPk(unsigned rownum, long* v) const {	*v = m_base + rownum;    }    void hashPk(unsigned* hash, const char* v, unsigned n) const {	for (unsigned i = 0; i < n; i++) {	    *hash ^= (v[i] << i);	}    }    void hashPk(unsigned* hash, long v) const {	*hash ^= v;    }    void calcNk(unsigned hash, char* v, unsigned n, SQLINTEGER* ind, bool null) const {	unsigned m = hash % n;	for (unsigned i = 0; i < n; i++) {	    char c = i < m ? 'a' + (hash + i) % ('z' - 'a' + 1) : i < n - 1 ? ' ' : 0;	    v[i] = c;	}	*ind = null && hash % 9 == 0 ? SQL_NULL_DATA : SQL_NTS;    }    void calcNk(unsigned hash, long* v, SQLINTEGER* ind, bool null) const {	*v = long(hash);	*ind = null && hash % 7 == 0 ? SQL_NULL_DATA : 0;    }    void calcNk(unsigned hash, double* v, SQLINTEGER* ind, bool null) const {	*v = long(hash) / 1000.0;	*ind = null && hash % 5 == 0 ? SQL_NULL_DATA : 0;    }    bool verify(const char* v1, SQLINTEGER ind1, const char* v2, SQLINTEGER ind2, unsigned n) {	if (ind1 == SQL_NULL_DATA && ind2 == SQL_NULL_DATA)	    return true;	if (ind1 != SQL_NULL_DATA && ind2 != SQL_NULL_DATA)	    if (memcmp(v1, v2, n) == 0)		return true;	if (ind1 == SQL_NULL_DATA)	    v1 = "NULL";	if (ind2 == SQL_NULL_DATA)	    v2 = "NULL";	ndbout << "verify failed: got ";	if (ind1 == SQL_NULL_DATA)	    ndbout << "NULL";	else	    cleanprint(v1, n);	ndbout << " != ";	if (ind2 == SQL_NULL_DATA)	    ndbout << "NULL";	else	    cleanprint(v2, n);	ndbout << endl;	return false;    }    bool verify(long v1, SQLINTEGER ind1, long v2, SQLINTEGER ind2) {	char buf1[40], buf2[40];	if (ind1 == SQL_NULL_DATA && ind2 == SQL_NULL_DATA)	    return true;	if (ind1 != SQL_NULL_DATA && ind2 != SQL_NULL_DATA)	    if (v1 == v2)		return true;	if (ind1 == SQL_NULL_DATA)	    strcpy(buf1, "NULL");	else	    sprintf(buf1, "%ld", v1);	if (ind2 == SQL_NULL_DATA)	    strcpy(buf2, "NULL");	else	    sprintf(buf2, "%ld", v2);	ndbout << "verify failed: got " << buf1 << " != " << buf2 << endl;	return false;    }    bool verify(double v1, SQLINTEGER ind1, double v2, SQLINTEGER ind2) {	char buf1[40], buf2[40];	if (ind1 == SQL_NULL_DATA && ind2 == SQL_NULL_DATA)	    return true;	if (ind1 != SQL_NULL_DATA && ind2 != SQL_NULL_DATA)	    if (fabs(v1 - v2) < 1)	// XXX		return true;	if (ind1 == SQL_NULL_DATA)	    strcpy(buf1, "NULL");	else	    sprintf(buf1, "%.10f", v1);	if (ind2 == SQL_NULL_DATA)	    strcpy(buf2, "NULL");	else	    sprintf(buf2, "%.10f", v2);	ndbout << "verify failed: got " << buf1 << " != " << buf2 << endl;	return false;    }};#if defined(NDB_SOLARIS) || defined(NDB_LINUX) || defined(NDB_MACOSX)#define HAVE_SBRK#else#undef HAVE_SBRK#endifstruct Timer {    Timer() :	m_cnt(0),	m_calls(0),	m_on(0),	m_msec(0)#ifndef NDB_WIN32	,	m_brk(0),	m_incr(0)#endif	{    }    void timerOn() {	m_cnt = 0;	m_calls = 0;	m_on = NdbTick_CurrentMillisecond();#ifdef HAVE_SBRK	m_brk = (int)sbrk(0);#endif    }    void timerOff() {	m_msec = NdbTick_CurrentMillisecond() - m_on;	if (m_msec <= 0)	    m_msec = 1;#ifdef HAVE_SBRK	m_incr = (int)sbrk(0) - m_brk;	if (m_incr < 0)	    m_incr = 0;#endif    }    void timerCnt(unsigned cnt) {	m_cnt += cnt;    }    void timerCnt(const Timer& timer) {	m_cnt += timer.m_cnt;	m_calls += timer.m_calls;    }    friend NdbOut& operator<<(NdbOut& out, const Timer& timer) {	out << timer.m_cnt << " ( " << 1000 * timer.m_cnt / timer.m_msec << "/sec )";#ifdef HAVE_SBRK	out << " - " << timer.m_incr << " sbrk";	if (opt.m_namecnt != 0) {	// per case meaningless if many cases	    if (timer.m_cnt > 0)		out << " ( " << timer.m_incr / timer.m_cnt << "/cnt )";	}

⌨️ 快捷键说明

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