| Index: third_party/sqlite/sqlite-src-3100200/test/threadtest3.c
|
| diff --git a/third_party/sqlite/sqlite-src-3080704/test/threadtest3.c b/third_party/sqlite/sqlite-src-3100200/test/threadtest3.c
|
| similarity index 84%
|
| copy from third_party/sqlite/sqlite-src-3080704/test/threadtest3.c
|
| copy to third_party/sqlite/sqlite-src-3100200/test/threadtest3.c
|
| index 084ca022a9808e83a78315b759c76f097bf14ff1..8d213c61f10bbfaa3ec4fca5e69979d39e94ad3b 100644
|
| --- a/third_party/sqlite/sqlite-src-3080704/test/threadtest3.c
|
| +++ b/third_party/sqlite/sqlite-src-3100200/test/threadtest3.c
|
| @@ -1,41 +1,41 @@
|
| -
|
| /*
|
| +** 2010-07-22
|
| +**
|
| +** The author disclaims copyright to this source code. In place of
|
| +** a legal notice, here is a blessing:
|
| +**
|
| +** May you do good and not evil.
|
| +** May you find forgiveness for yourself and forgive others.
|
| +** May you share freely, never taking more than you give.
|
| +**
|
| +*************************************************************************
|
| +**
|
| ** The code in this file runs a few multi-threaded test cases using the
|
| ** SQLite library. It can be compiled to an executable on unix using the
|
| ** following command:
|
| **
|
| ** gcc -O2 threadtest3.c sqlite3.c -ldl -lpthread -lm
|
| **
|
| -** Then run the compiled program. The exit status is non-zero if any tests
|
| -** failed (hopefully there is also some output to stdout to clarify what went
|
| -** wrong).
|
| +** Even though threadtest3.c is the only C source code file mentioned on
|
| +** the compiler command-line, #include macros are used to pull in additional
|
| +** C code files named "tt3_*.c".
|
| **
|
| -** There are three parts to the code in this file, in the following order:
|
| +** After compiling, run this program with an optional argument telling
|
| +** which test to run. All tests are run if no argument is given. The
|
| +** argument can be a glob pattern to match multiple tests. Examples:
|
| **
|
| -** 1. Code for the SQL aggregate function md5sum() copied from
|
| -** tclsqlite.c in the SQLite distribution. The names of all the
|
| -** types and functions in this section begin with "MD5" or "md5".
|
| +** ./a.out -- Run all tests
|
| +** ./a.out walthread3 -- Run the "walthread3" test
|
| +** ./a.out 'wal*' -- Run all of the wal* tests
|
| +** ./a.out --help -- List all available tests
|
| **
|
| -** 2. A set of utility functions that may be used to implement
|
| -** multi-threaded test cases. These are all called by test code
|
| -** via macros that help with error reporting. The macros are defined
|
| -** immediately below this comment.
|
| -**
|
| -** 3. The test code itself. And a main() routine to drive the test
|
| -** code.
|
| +** The exit status is non-zero if any test fails.
|
| */
|
|
|
| -/*************************************************************************
|
| -** Start of test code/infrastructure interface macros.
|
| -**
|
| -** The following macros constitute the interface between the test
|
| -** programs and the test infrastructure. Test infrastructure code
|
| -** does not itself use any of these macros. Test code should not
|
| -** call any of the macroname_x() functions directly.
|
| -**
|
| -** See the header comments above the corresponding macroname_x()
|
| -** function for a description of each interface.
|
| +/*
|
| +** The "Set Error Line" macro.
|
| */
|
| +#define SEL(e) ((e)->iLine = ((e)->rc ? (e)->iLine : __LINE__))
|
|
|
| /* Database functions */
|
| #define opendb(w,x,y,z) (SEL(w), opendb_x(w,x,y,z))
|
| @@ -47,10 +47,13 @@
|
| #define execsql_i64(x,y,...) (SEL(x), execsql_i64_x(x,y,__VA_ARGS__))
|
| #define execsql_text(x,y,z,...) (SEL(x), execsql_text_x(x,y,z,__VA_ARGS__))
|
| #define execsql(x,y,...) (SEL(x), (void)execsql_i64_x(x,y,__VA_ARGS__))
|
| +#define sql_script_printf(x,y,z,...) ( \
|
| + SEL(x), sql_script_printf_x(x,y,z,__VA_ARGS__) \
|
| +)
|
|
|
| /* Thread functions */
|
| -#define launch_thread(w,x,y,z) (SEL(w), launch_thread_x(w,x,y,z))
|
| -#define join_all_threads(y,z) (SEL(y), join_all_threads_x(y,z))
|
| +#define launch_thread(w,x,y,z) (SEL(w), launch_thread_x(w,x,y,z))
|
| +#define join_all_threads(y,z) (SEL(y), join_all_threads_x(y,z))
|
|
|
| /* Timer functions */
|
| #define setstoptime(y,z) (SEL(y), setstoptime_x(y,z))
|
| @@ -64,6 +67,9 @@
|
| #define filesize(y,z) (SEL(y), filesize_x(y,z))
|
| #define filecopy(x,y,z) (SEL(x), filecopy_x(x,y,z))
|
|
|
| +#define PTR2INT(x) ((int)((intptr_t)x))
|
| +#define INT2PTR(x) ((void*)((intptr_t)x))
|
| +
|
| /*
|
| ** End of test code/infrastructure interface macros.
|
| *************************************************************************/
|
| @@ -82,6 +88,13 @@
|
| #include <fcntl.h>
|
| #include <errno.h>
|
|
|
| +#include "test_multiplex.h"
|
| +
|
| +/* Required to link test_multiplex.c */
|
| +#ifndef SQLITE_OMIT_WSD
|
| +int sqlite3PendingByte = 0x40000000;
|
| +#endif
|
| +
|
| /*
|
| * This code implements the MD5 message-digest algorithm.
|
| * The algorithm is due to Ron Rivest. This code was
|
| @@ -115,7 +128,10 @@ struct MD5Context {
|
| int isInit;
|
| uint32 buf[4];
|
| uint32 bits[2];
|
| - unsigned char in[64];
|
| + union {
|
| + unsigned char in[64];
|
| + uint32 in32[16];
|
| + } u;
|
| };
|
| typedef struct MD5Context MD5Context;
|
|
|
| @@ -264,7 +280,7 @@ void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
|
| /* Handle any leading odd-sized chunks */
|
|
|
| if ( t ) {
|
| - unsigned char *p = (unsigned char *)ctx->in + t;
|
| + unsigned char *p = (unsigned char *)ctx->u.in + t;
|
|
|
| t = 64-t;
|
| if (len < t) {
|
| @@ -272,8 +288,8 @@ void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
|
| return;
|
| }
|
| memcpy(p, buf, t);
|
| - byteReverse(ctx->in, 16);
|
| - MD5Transform(ctx->buf, (uint32 *)ctx->in);
|
| + byteReverse(ctx->u.in, 16);
|
| + MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
|
| buf += t;
|
| len -= t;
|
| }
|
| @@ -281,16 +297,16 @@ void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
|
| /* Process data in 64-byte chunks */
|
|
|
| while (len >= 64) {
|
| - memcpy(ctx->in, buf, 64);
|
| - byteReverse(ctx->in, 16);
|
| - MD5Transform(ctx->buf, (uint32 *)ctx->in);
|
| + memcpy(ctx->u.in, buf, 64);
|
| + byteReverse(ctx->u.in, 16);
|
| + MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
|
| buf += 64;
|
| len -= 64;
|
| }
|
|
|
| /* Handle any remaining bytes of data. */
|
|
|
| - memcpy(ctx->in, buf, len);
|
| + memcpy(ctx->u.in, buf, len);
|
| }
|
|
|
| /*
|
| @@ -306,7 +322,7 @@ static void MD5Final(unsigned char digest[16], MD5Context *ctx){
|
|
|
| /* Set the first char of padding to 0x80. This is safe since there is
|
| always at least one byte free */
|
| - p = ctx->in + count;
|
| + p = ctx->u.in + count;
|
| *p++ = 0x80;
|
|
|
| /* Bytes of padding needed to make 64 bytes */
|
| @@ -316,25 +332,25 @@ static void MD5Final(unsigned char digest[16], MD5Context *ctx){
|
| if (count < 8) {
|
| /* Two lots of padding: Pad the first block to 64 bytes */
|
| memset(p, 0, count);
|
| - byteReverse(ctx->in, 16);
|
| - MD5Transform(ctx->buf, (uint32 *)ctx->in);
|
| + byteReverse(ctx->u.in, 16);
|
| + MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
|
|
|
| /* Now fill the next block with 56 bytes */
|
| - memset(ctx->in, 0, 56);
|
| + memset(ctx->u.in, 0, 56);
|
| } else {
|
| /* Pad block to 56 bytes */
|
| memset(p, 0, count-8);
|
| }
|
| - byteReverse(ctx->in, 14);
|
| + byteReverse(ctx->u.in, 14);
|
|
|
| /* Append length in bits and transform */
|
| - ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
|
| - ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];
|
| + ctx->u.in32[14] = ctx->bits[0];
|
| + ctx->u.in32[15] = ctx->bits[1];
|
|
|
| - MD5Transform(ctx->buf, (uint32 *)ctx->in);
|
| + MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
|
| byteReverse((unsigned char *)ctx->buf, 4);
|
| memcpy(digest, ctx->buf, 16);
|
| - memset(ctx, 0, sizeof(ctx)); /* In case it is sensitive */
|
| + memset(ctx, 0, sizeof(*ctx)); /* In case it is sensitive */
|
| }
|
|
|
| /*
|
| @@ -382,9 +398,9 @@ static void md5finalize(sqlite3_context *context){
|
| sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
| }
|
|
|
| -/*************************************************************************
|
| +/*
|
| ** End of copied md5sum() code.
|
| -*/
|
| +**************************************************************************/
|
|
|
| typedef sqlite3_int64 i64;
|
|
|
| @@ -398,9 +414,6 @@ typedef struct Thread Thread;
|
| /* Total number of errors in this process so far. */
|
| static int nGlobalErr = 0;
|
|
|
| -/* Set to true to run in "process" instead of "thread" mode. */
|
| -static int bProcessMode = 0;
|
| -
|
| struct Error {
|
| int rc;
|
| int iLine;
|
| @@ -421,10 +434,10 @@ struct Statement {
|
|
|
| struct Thread {
|
| int iTid; /* Thread number within test */
|
| - int iArg; /* Integer argument passed by caller */
|
| + void* pArg; /* Pointer argument passed by caller */
|
|
|
| pthread_t tid; /* Thread id */
|
| - char *(*xProc)(int, int); /* Thread main proc */
|
| + char *(*xProc)(int, void*); /* Thread main proc */
|
| Thread *pNext; /* Next in this list of threads */
|
| };
|
|
|
| @@ -441,8 +454,13 @@ static void free_err(Error *p){
|
|
|
| static void print_err(Error *p){
|
| if( p->rc!=SQLITE_OK ){
|
| - printf("Error: (%d) \"%s\" at line %d\n", p->rc, p->zErr, p->iLine);
|
| - nGlobalErr++;
|
| + int isWarn = 0;
|
| + if( p->rc==SQLITE_SCHEMA ) isWarn = 1;
|
| + if( sqlite3_strglob("* - no such table: *",p->zErr)==0 ) isWarn = 1;
|
| + printf("%s: (%d) \"%s\" at line %d\n", isWarn ? "Warning" : "Error",
|
| + p->rc, p->zErr, p->iLine);
|
| + if( !isWarn ) nGlobalErr++;
|
| + fflush(stdout);
|
| }
|
| }
|
|
|
| @@ -506,8 +524,9 @@ static void opendb_x(
|
| ){
|
| if( pErr->rc==SQLITE_OK ){
|
| int rc;
|
| + int flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
|
| if( bDelete ) unlink(zFile);
|
| - rc = sqlite3_open(zFile, &pDb->db);
|
| + rc = sqlite3_open_v2(zFile, &pDb->db, flags, 0);
|
| if( rc ){
|
| sqlite_error(pErr, pDb, "open");
|
| sqlite3_close(pDb->db);
|
| @@ -556,6 +575,22 @@ static void sql_script_x(
|
| }
|
| }
|
|
|
| +static void sql_script_printf_x(
|
| + Error *pErr, /* IN/OUT: Error code */
|
| + Sqlite *pDb, /* Database handle */
|
| + const char *zFormat, /* SQL printf format string */
|
| + ... /* Printf args */
|
| +){
|
| + va_list ap; /* ... printf arguments */
|
| + va_start(ap, zFormat);
|
| + if( pErr->rc==SQLITE_OK ){
|
| + char *zSql = sqlite3_vmprintf(zFormat, ap);
|
| + pErr->rc = sqlite3_exec(pDb->db, zSql, 0, 0, &pErr->zErr);
|
| + sqlite3_free(zSql);
|
| + }
|
| + va_end(ap);
|
| +}
|
| +
|
| static Statement *getSqlStatement(
|
| Error *pErr, /* IN/OUT: Error code */
|
| Sqlite *pDb, /* Database handle */
|
| @@ -624,11 +659,9 @@ static i64 execsql_i64_x(
|
| if( pErr->rc==SQLITE_OK ){
|
| sqlite3_stmt *pStmt; /* SQL statement to execute */
|
| va_list ap; /* ... arguments */
|
| - int i; /* Used to iterate through parameters */
|
| va_start(ap, pDb);
|
| pStmt = getAndBindSqlStatement(pErr, pDb, ap);
|
| if( pStmt ){
|
| - int rc;
|
| int first = 1;
|
| while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
| if( first && sqlite3_column_count(pStmt)>0 ){
|
| @@ -663,11 +696,9 @@ static char * execsql_text_x(
|
| if( pErr->rc==SQLITE_OK ){
|
| sqlite3_stmt *pStmt; /* SQL statement to execute */
|
| va_list ap; /* ... arguments */
|
| - int i; /* Used to iterate through parameters */
|
| va_start(ap, iSlot);
|
| pStmt = getAndBindSqlStatement(pErr, pDb, ap);
|
| if( pStmt ){
|
| - int rc;
|
| int first = 1;
|
| while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
| if( first && sqlite3_column_count(pStmt)>0 ){
|
| @@ -693,14 +724,13 @@ static void integrity_check_x(
|
| ){
|
| if( pErr->rc==SQLITE_OK ){
|
| Statement *pStatement; /* Statement to execute */
|
| - int rc; /* Return code */
|
| char *zErr = 0; /* Integrity check error */
|
|
|
| pStatement = getSqlStatement(pErr, pDb, "PRAGMA integrity_check");
|
| if( pStatement ){
|
| sqlite3_stmt *pStmt = pStatement->pStmt;
|
| while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
| - const char *z = sqlite3_column_text(pStmt, 0);
|
| + const char *z = (const char*)sqlite3_column_text(pStmt, 0);
|
| if( strcmp(z, "ok") ){
|
| if( zErr==0 ){
|
| zErr = sqlite3_mprintf("%s", z);
|
| @@ -721,14 +751,14 @@ static void integrity_check_x(
|
|
|
| static void *launch_thread_main(void *pArg){
|
| Thread *p = (Thread *)pArg;
|
| - return (void *)p->xProc(p->iTid, p->iArg);
|
| + return (void *)p->xProc(p->iTid, p->pArg);
|
| }
|
|
|
| static void launch_thread_x(
|
| Error *pErr, /* IN/OUT: Error code */
|
| Threadset *pThreads, /* Thread set */
|
| - char *(*xProc)(int, int), /* Proc to run */
|
| - int iArg /* Argument passed to thread proc */
|
| + char *(*xProc)(int, void*), /* Proc to run */
|
| + void *pArg /* Argument passed to thread proc */
|
| ){
|
| if( pErr->rc==SQLITE_OK ){
|
| int iTid = ++pThreads->iMaxTid;
|
| @@ -738,7 +768,7 @@ static void launch_thread_x(
|
| p = (Thread *)sqlite3_malloc(sizeof(Thread));
|
| memset(p, 0, sizeof(Thread));
|
| p->iTid = iTid;
|
| - p->iArg = iArg;
|
| + p->pArg = pArg;
|
| p->xProc = xProc;
|
|
|
| rc = pthread_create(&p->tid, NULL, launch_thread_main, (void *)p);
|
| @@ -767,6 +797,7 @@ static void join_all_threads_x(
|
| if( pErr->rc==SQLITE_OK ) system_error(pErr, rc);
|
| }else{
|
| printf("Thread %d says: %s\n", p->iTid, (ret==0 ? "..." : (char *)ret));
|
| + fflush(stdout);
|
| }
|
| sqlite3_free(p);
|
| }
|
| @@ -844,22 +875,28 @@ static void filecopy_x(
|
| ** Used by setstoptime() and timetostop().
|
| */
|
| static double timelimit = 0.0;
|
| -static sqlite3_vfs *pTimelimitVfs = 0;
|
| +
|
| +static double currentTime(void){
|
| + double t;
|
| + static sqlite3_vfs *pTimelimitVfs = 0;
|
| + if( pTimelimitVfs==0 ) pTimelimitVfs = sqlite3_vfs_find(0);
|
| + if( pTimelimitVfs->iVersion>=1 && pTimelimitVfs->xCurrentTimeInt64!=0 ){
|
| + sqlite3_int64 tm;
|
| + pTimelimitVfs->xCurrentTimeInt64(pTimelimitVfs, &tm);
|
| + t = tm/86400000.0;
|
| + }else{
|
| + pTimelimitVfs->xCurrentTime(pTimelimitVfs, &t);
|
| + }
|
| + return t;
|
| +}
|
|
|
| static void setstoptime_x(
|
| Error *pErr, /* IN/OUT: Error code */
|
| int nMs /* Milliseconds until "stop time" */
|
| ){
|
| if( pErr->rc==SQLITE_OK ){
|
| - double t;
|
| - int rc;
|
| - pTimelimitVfs = sqlite3_vfs_find(0);
|
| - rc = pTimelimitVfs->xCurrentTime(pTimelimitVfs, &t);
|
| - if( rc!=SQLITE_OK ){
|
| - pErr->rc = rc;
|
| - }else{
|
| - timelimit = t + ((double)nMs)/(1000.0*60.0*60.0*24.0);
|
| - }
|
| + double t = currentTime();
|
| + timelimit = t + ((double)nMs)/(1000.0*60.0*60.0*24.0);
|
| }
|
| }
|
|
|
| @@ -868,23 +905,12 @@ static int timetostop_x(
|
| ){
|
| int ret = 1;
|
| if( pErr->rc==SQLITE_OK ){
|
| - double t;
|
| - int rc;
|
| - rc = pTimelimitVfs->xCurrentTime(pTimelimitVfs, &t);
|
| - if( rc!=SQLITE_OK ){
|
| - pErr->rc = rc;
|
| - }else{
|
| - ret = (t >= timelimit);
|
| - }
|
| + double t = currentTime();
|
| + ret = (t >= timelimit);
|
| }
|
| return ret;
|
| }
|
|
|
| -/*
|
| -** The "Set Error Line" macro.
|
| -*/
|
| -#define SEL(e) ((e)->iLine = ((e)->rc ? (e)->iLine : __LINE__))
|
| -
|
|
|
| /*************************************************************************
|
| **************************************************************************
|
| @@ -895,7 +921,7 @@ static int timetostop_x(
|
| #define WALTHREAD1_NTHREAD 10
|
| #define WALTHREAD3_NTHREAD 6
|
|
|
| -static char *walthread1_thread(int iTid, int iArg){
|
| +static char *walthread1_thread(int iTid, void *pArg){
|
| Error err = {0}; /* Error code and message */
|
| Sqlite db = {0}; /* SQLite database connection */
|
| int nIter = 0; /* Iterations so far */
|
| @@ -934,7 +960,7 @@ static char *walthread1_thread(int iTid, int iArg){
|
| return sqlite3_mprintf("%d iterations", nIter);
|
| }
|
|
|
| -static char *walthread1_ckpt_thread(int iTid, int iArg){
|
| +static char *walthread1_ckpt_thread(int iTid, void *pArg){
|
| Error err = {0}; /* Error code and message */
|
| Sqlite db = {0}; /* SQLite database connection */
|
| int nCkpt = 0; /* Checkpoints so far */
|
| @@ -966,6 +992,7 @@ static void walthread1(int nMs){
|
| "INSERT INTO t1 VALUES(randomblob(100));"
|
| "INSERT INTO t1 SELECT md5sum(x) FROM t1;"
|
| );
|
| + closedb(&err, &db);
|
|
|
| setstoptime(&err, nMs);
|
| for(i=0; i<WALTHREAD1_NTHREAD; i++){
|
| @@ -977,10 +1004,11 @@ static void walthread1(int nMs){
|
| print_and_free_err(&err);
|
| }
|
|
|
| -static char *walthread2_thread(int iTid, int iArg){
|
| +static char *walthread2_thread(int iTid, void *pArg){
|
| Error err = {0}; /* Error code and message */
|
| Sqlite db = {0}; /* SQLite database connection */
|
| int anTrans[2] = {0, 0}; /* Number of WAL and Rollback transactions */
|
| + int iArg = PTR2INT(pArg);
|
|
|
| const char *zJournal = "PRAGMA journal_mode = WAL";
|
| if( iArg ){ zJournal = "PRAGMA journal_mode = DELETE"; }
|
| @@ -1026,17 +1054,18 @@ static void walthread2(int nMs){
|
| setstoptime(&err, nMs);
|
| launch_thread(&err, &threads, walthread2_thread, 0);
|
| launch_thread(&err, &threads, walthread2_thread, 0);
|
| - launch_thread(&err, &threads, walthread2_thread, 1);
|
| - launch_thread(&err, &threads, walthread2_thread, 1);
|
| + launch_thread(&err, &threads, walthread2_thread, (void*)1);
|
| + launch_thread(&err, &threads, walthread2_thread, (void*)1);
|
| join_all_threads(&err, &threads);
|
|
|
| print_and_free_err(&err);
|
| }
|
|
|
| -static char *walthread3_thread(int iTid, int iArg){
|
| +static char *walthread3_thread(int iTid, void *pArg){
|
| Error err = {0}; /* Error code and message */
|
| Sqlite db = {0}; /* SQLite database connection */
|
| i64 iNextWrite; /* Next value this thread will write */
|
| + int iArg = PTR2INT(pArg);
|
|
|
| opendb(&err, &db, "test.db", 0);
|
| sql_script(&err, &db, "PRAGMA wal_autocheckpoint = 10");
|
| @@ -1087,14 +1116,14 @@ static void walthread3(int nMs){
|
|
|
| setstoptime(&err, nMs);
|
| for(i=0; i<WALTHREAD3_NTHREAD; i++){
|
| - launch_thread(&err, &threads, walthread3_thread, i);
|
| + launch_thread(&err, &threads, walthread3_thread, INT2PTR(i));
|
| }
|
| join_all_threads(&err, &threads);
|
|
|
| print_and_free_err(&err);
|
| }
|
|
|
| -static char *walthread4_reader_thread(int iTid, int iArg){
|
| +static char *walthread4_reader_thread(int iTid, void *pArg){
|
| Error err = {0}; /* Error code and message */
|
| Sqlite db = {0}; /* SQLite database connection */
|
|
|
| @@ -1108,7 +1137,7 @@ static char *walthread4_reader_thread(int iTid, int iArg){
|
| return 0;
|
| }
|
|
|
| -static char *walthread4_writer_thread(int iTid, int iArg){
|
| +static char *walthread4_writer_thread(int iTid, void *pArg){
|
| Error err = {0}; /* Error code and message */
|
| Sqlite db = {0}; /* SQLite database connection */
|
| i64 iRow = 1;
|
| @@ -1148,7 +1177,7 @@ static void walthread4(int nMs){
|
| print_and_free_err(&err);
|
| }
|
|
|
| -static char *walthread5_thread(int iTid, int iArg){
|
| +static char *walthread5_thread(int iTid, void *pArg){
|
| Error err = {0}; /* Error code and message */
|
| Sqlite db = {0}; /* SQLite database connection */
|
| i64 nRow;
|
| @@ -1280,7 +1309,7 @@ static void cgt_pager_1(int nMs){
|
| ** is an attempt to find a bug reported to us.
|
| */
|
|
|
| -static char *dynamic_triggers_1(int iTid, int iArg){
|
| +static char *dynamic_triggers_1(int iTid, void *pArg){
|
| Error err = {0}; /* Error code and message */
|
| Sqlite db = {0}; /* SQLite database connection */
|
| int nDrop = 0;
|
| @@ -1326,12 +1355,13 @@ static char *dynamic_triggers_1(int iTid, int iArg){
|
| nDrop++;
|
| }
|
| }
|
| + closedb(&err, &db);
|
|
|
| print_and_free_err(&err);
|
| return sqlite3_mprintf("%d created, %d dropped", nCreate, nDrop);
|
| }
|
|
|
| -static char *dynamic_triggers_2(int iTid, int iArg){
|
| +static char *dynamic_triggers_2(int iTid, void *pArg){
|
| Error err = {0}; /* Error code and message */
|
| Sqlite db = {0}; /* SQLite database connection */
|
| i64 iVal = 0;
|
| @@ -1352,6 +1382,7 @@ static char *dynamic_triggers_2(int iTid, int iArg){
|
| nDelete++;
|
| } while( iVal );
|
| }
|
| + closedb(&err, &db);
|
|
|
| print_and_free_err(&err);
|
| return sqlite3_mprintf("%d inserts, %d deletes", nInsert, nDelete);
|
| @@ -1376,15 +1407,16 @@ static void dynamic_triggers(int nMs){
|
| "CREATE TABLE t8(x, y);"
|
| "CREATE TABLE t9(x, y);"
|
| );
|
| + closedb(&err, &db);
|
|
|
| setstoptime(&err, nMs);
|
|
|
| sqlite3_enable_shared_cache(1);
|
| launch_thread(&err, &threads, dynamic_triggers_2, 0);
|
| launch_thread(&err, &threads, dynamic_triggers_2, 0);
|
| - sqlite3_enable_shared_cache(0);
|
|
|
| sleep(2);
|
| + sqlite3_enable_shared_cache(0);
|
|
|
| launch_thread(&err, &threads, dynamic_triggers_2, 0);
|
| launch_thread(&err, &threads, dynamic_triggers_1, 0);
|
| @@ -1398,19 +1430,21 @@ static void dynamic_triggers(int nMs){
|
|
|
| #include "tt3_checkpoint.c"
|
| #include "tt3_index.c"
|
| +#include "tt3_lookaside1.c"
|
| +#include "tt3_vacuum.c"
|
| +#include "tt3_stress.c"
|
|
|
| int main(int argc, char **argv){
|
| struct ThreadTest {
|
| - void (*xTest)(int);
|
| - const char *zTest;
|
| - int nMs;
|
| + void (*xTest)(int); /* Routine for running this test */
|
| + const char *zTest; /* Name of this test */
|
| + int nMs; /* How long to run this test, in milliseconds */
|
| } aTest[] = {
|
| { walthread1, "walthread1", 20000 },
|
| { walthread2, "walthread2", 20000 },
|
| { walthread3, "walthread3", 20000 },
|
| { walthread4, "walthread4", 20000 },
|
| { walthread5, "walthread5", 1000 },
|
| - { walthread5, "walthread5", 1000 },
|
|
|
| { cgt_pager_1, "cgt_pager_1", 0 },
|
| { dynamic_triggers, "dynamic_triggers", 20000 },
|
| @@ -1419,42 +1453,67 @@ int main(int argc, char **argv){
|
| { checkpoint_starvation_2, "checkpoint_starvation_2", 10000 },
|
|
|
| { create_drop_index_1, "create_drop_index_1", 10000 },
|
| + { lookaside1, "lookaside1", 10000 },
|
| + { vacuum1, "vacuum1", 10000 },
|
| + { stress1, "stress1", 10000 },
|
| + { stress2, "stress2", 60000 },
|
| };
|
| + static char *substArgv[] = { 0, "*", 0 };
|
| + int i, iArg;
|
| + int nTestfound = 0;
|
|
|
| - int i;
|
| - char *zTest = 0;
|
| - int nTest = 0;
|
| - int bTestfound = 0;
|
| - int bPrefix = 0;
|
| -
|
| - if( argc>2 ) goto usage;
|
| - if( argc==2 ){
|
| - zTest = argv[1];
|
| - nTest = strlen(zTest);
|
| - if( zTest[nTest-1]=='*' ){
|
| - nTest--;
|
| - bPrefix = 1;
|
| - }
|
| + sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
|
| + if( argc<2 ){
|
| + argc = 2;
|
| + argv = substArgv;
|
| }
|
|
|
| - sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
|
| + /* Loop through the command-line arguments to ensure that each argument
|
| + ** selects at least one test. If not, assume there is a typo on the
|
| + ** command-line and bail out with the usage message. */
|
| + for(iArg=1; iArg<argc; iArg++){
|
| + const char *zArg = argv[iArg];
|
| + if( zArg[0]=='-' ){
|
| + if( sqlite3_stricmp(zArg, "-multiplexor")==0 ){
|
| + /* Install the multiplexor VFS as the default */
|
| + int rc = sqlite3_multiplex_initialize(0, 1);
|
| + if( rc!=SQLITE_OK ){
|
| + fprintf(stderr, "Failed to install multiplexor VFS (%d)\n", rc);
|
| + return 253;
|
| + }
|
| + }
|
| + else {
|
| + goto usage;
|
| + }
|
|
|
| - for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
|
| - char const *z = aTest[i].zTest;
|
| - int n = strlen(z);
|
| - if( !zTest || ((bPrefix || n==nTest) && 0==strncmp(zTest, z, nTest)) ){
|
| - printf("Running %s for %d seconds...\n", z, aTest[i].nMs/1000);
|
| - aTest[i].xTest(aTest[i].nMs);
|
| - bTestfound++;
|
| + continue;
|
| + }
|
| +
|
| + for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
|
| + if( sqlite3_strglob(zArg, aTest[i].zTest)==0 ) break;
|
| + }
|
| + if( i>=sizeof(aTest)/sizeof(aTest[0]) ) goto usage;
|
| + }
|
| +
|
| + for(iArg=1; iArg<argc; iArg++){
|
| + if( argv[iArg][0]=='-' ) continue;
|
| + for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
|
| + char const *z = aTest[i].zTest;
|
| + if( sqlite3_strglob(argv[iArg],z)==0 ){
|
| + printf("Running %s for %d seconds...\n", z, aTest[i].nMs/1000);
|
| + fflush(stdout);
|
| + aTest[i].xTest(aTest[i].nMs);
|
| + nTestfound++;
|
| + }
|
| }
|
| }
|
| - if( bTestfound==0 ) goto usage;
|
| + if( nTestfound==0 ) goto usage;
|
|
|
| - printf("Total of %d errors across all tests\n", nGlobalErr);
|
| + printf("%d errors out of %d tests\n", nGlobalErr, nTestfound);
|
| return (nGlobalErr>0 ? 255 : 0);
|
|
|
| usage:
|
| - printf("Usage: %s [testname|testprefix*]\n", argv[0]);
|
| + printf("Usage: %s [-multiplexor] [testname|testprefix*]...\n", argv[0]);
|
| printf("Available tests are:\n");
|
| for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
|
| printf(" %s\n", aTest[i].zTest);
|
| @@ -1462,5 +1521,3 @@ int main(int argc, char **argv){
|
|
|
| return 254;
|
| }
|
| -
|
| -
|
|
|