From: dan Date: Wed, 25 Aug 2010 17:53:17 +0000 (+0000) Subject: Test cases to improve coverage of rtree module. Fixes associated with the same. X-Git-Tag: experimental~120 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=92e01aafe190af8846a46a31aff72ac0a27eaa2b;p=thirdparty%2Fsqlite.git Test cases to improve coverage of rtree module. Fixes associated with the same. FossilOrigin-Name: 865cec04e4d814f63fb71feb67de7f06f8d54035 --- diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index a0b45bbc78..c8e4ea2307 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -53,6 +53,9 @@ #define AssignCells splitNodeStartree #endif +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif #ifndef SQLITE_CORE #include "sqlite3ext.h" @@ -306,10 +309,8 @@ static void nodeReference(RtreeNode *p){ ** Clear the content of node p (set all bytes to 0x00). */ static void nodeZero(Rtree *pRtree, RtreeNode *p){ - if( p ){ - memset(&p->zData[2], 0, pRtree->iNodeSize-2); - p->isDirty = 1; - } + memset(&p->zData[2], 0, pRtree->iNodeSize-2); + p->isDirty = 1; } /* @@ -338,13 +339,11 @@ static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){ ** Add node pNode to the node hash table. */ static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){ - if( pNode ){ - int iHash; - assert( pNode->pNext==0 ); - iHash = nodeHash(pNode->iNode); - pNode->pNext = pRtree->aHash[iHash]; - pRtree->aHash[iHash] = pNode; - } + int iHash; + assert( pNode->pNext==0 ); + iHash = nodeHash(pNode->iNode); + pNode->pNext = pRtree->aHash[iHash]; + pRtree->aHash[iHash] = pNode; } /* @@ -366,11 +365,11 @@ static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){ ** assigned a node number when nodeWrite() is called to write the ** node contents out to the database. */ -static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent, int zero){ +static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){ RtreeNode *pNode; pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize); if( pNode ){ - memset(pNode, 0, sizeof(RtreeNode) + (zero?pRtree->iNodeSize:0)); + memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize); pNode->zData = (u8 *)&pNode[1]; pNode->nRef = 1; pNode->pParent = pParent; @@ -434,7 +433,7 @@ nodeAcquire( *ppNode = pNode; rc = sqlite3_reset(pRtree->pReadNode); - if( rc==SQLITE_OK && iNode==1 ){ + if( pNode && iNode==1 ){ pRtree->iDepth = readInt16(pNode->zData); } @@ -762,9 +761,15 @@ static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor){ ); switch( p->op ){ - case RTREE_LE: case RTREE_LT: bRes = p->rValuerValue>cell_max; break; - case RTREE_EQ: + case RTREE_LE: case RTREE_LT: + bRes = p->rValuerValue>cell_max; + break; + + default: assert( p->op==RTREE_EQ ); bRes = (p->rValue>cell_max || p->rValuerValue); break; case RTREE_GE: res = (coord>=p->rValue); break; case RTREE_GT: res = (coord>p->rValue); break; - case RTREE_EQ: res = (coord==p->rValue); break; + default: res = (coord==p->rValue); break; } if( !res ) return 1; @@ -900,13 +905,17 @@ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; int rc = SQLITE_OK; + /* RtreeCursor.pNode must not be NULL. If is is NULL, then this cursor is + ** already at EOF. It is against the rules to call the xNext() method of + ** a cursor that has already reached EOF. + */ + assert( pCsr->pNode ); + if( pCsr->iStrategy==1 ){ /* This "scan" is a direct lookup by rowid. There is no next entry. */ nodeRelease(pRtree, pCsr->pNode); pCsr->pNode = 0; - } - - else if( pCsr->pNode ){ + }else{ /* Move to the next entry that matches the configured constraints. */ int iHeight = 0; while( pCsr->pNode ){ @@ -1016,7 +1025,8 @@ static int rtreeFilter( i64 iRowid = sqlite3_value_int64(argv[0]); rc = findLeafNode(pRtree, iRowid, &pLeaf); pCsr->pNode = pLeaf; - if( pLeaf && rc==SQLITE_OK ){ + if( pLeaf ){ + assert( rc==SQLITE_OK ); pCsr->iCell = nodeRowidIndex(pRtree, pLeaf, iRowid); } }else{ @@ -1272,7 +1282,12 @@ static float cellOverlap( int ii; float overlap = 0.0; for(ii=0; iinDim*2); jj+=2){ @@ -1365,22 +1380,31 @@ static int ChooseLeaf( ** the smallest area. */ for(iCell=0; iCelliDepth-1) ){ overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell); } -#endif if( (iCell==0) || (overlapiNode==1 ){ - pRight = nodeNew(pRtree, pNode, 1); - pLeft = nodeNew(pRtree, pNode, 1); + pRight = nodeNew(pRtree, pNode); + pLeft = nodeNew(pRtree, pNode); pRtree->iDepth++; pNode->isDirty = 1; writeInt16(pNode->zData, pRtree->iDepth); }else{ pLeft = pNode; - pRight = nodeNew(pRtree, pLeft->pParent, 1); + pRight = nodeNew(pRtree, pLeft->pParent); nodeReference(pLeft); } @@ -2358,7 +2382,9 @@ static int rtreeUpdate( rtreeReference(pRtree); assert(nData>=1); +#if 0 assert(hashIsEmpty(pRtree)); +#endif /* If azData[0] is not an SQL NULL value, it is the rowid of a ** record to delete from the r-tree table. The following block does diff --git a/ext/rtree/rtree2.test b/ext/rtree/rtree2.test index 307e7e0208..4ffa880348 100644 --- a/ext/rtree/rtree2.test +++ b/ext/rtree/rtree2.test @@ -27,7 +27,7 @@ set ::NROW 1000 set ::NDEL 10 set ::NSELECT 100 -if {[info exists ISQUICK] && $ISQUICK} { +if {[info exists G(isquick)] && $G(isquick)} { set ::NROW 100 set ::NSELECT 10 } diff --git a/ext/rtree/rtree3.test b/ext/rtree/rtree3.test index 1ce131c53a..5076908f91 100644 --- a/ext/rtree/rtree3.test +++ b/ext/rtree/rtree3.test @@ -17,6 +17,7 @@ if {![info exists testdir]} { set testdir [file join [file dirname $argv0] .. .. test] } source $testdir/tester.tcl +source $testdir/malloc_common.tcl ifcapable !rtree { finish_test @@ -32,34 +33,61 @@ if {!$MEMDEBUG} { return } -do_malloc_test rtree3-1 -sqlbody { - BEGIN TRANSACTION; - CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2); - INSERT INTO rt VALUES(NULL, 3, 5, 7, 9); - INSERT INTO rt VALUES(NULL, 13, 15, 17, 19); - DELETE FROM rt WHERE ii = 1; - SELECT * FROM rt; - SELECT ii FROM rt WHERE ii = 2; - COMMIT; -} -do_malloc_test rtree3-2 -sqlprep { - CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2); - INSERT INTO rt VALUES(NULL, 3, 5, 7, 9); -} -sqlbody { - DROP TABLE rt; -} +if 1 { + +do_faultsim_test rtree3-1 -faults oom* -prep { + faultsim_delete_and_reopen +} -body { + execsql { + BEGIN TRANSACTION; + CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2); + INSERT INTO rt VALUES(NULL, 3, 5, 7, 9); + INSERT INTO rt VALUES(NULL, 13, 15, 17, 19); + DELETE FROM rt WHERE ii = 1; + SELECT * FROM rt; + SELECT ii FROM rt WHERE ii = 2; + COMMIT; + } +} +do_test rtree3-2.prep { + faultsim_delete_and_reopen + execsql { + CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2); + INSERT INTO rt VALUES(NULL, 3, 5, 7, 9); + } + faultsim_save_and_close +} {} +do_faultsim_test rtree3-2 -faults oom* -prep { + faultsim_restore_and_reopen +} -body { + execsql { DROP TABLE rt } +} + +do_malloc_test rtree3-3.prep { + faultsim_delete_and_reopen + execsql { + CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2); + INSERT INTO rt VALUES(NULL, 3, 5, 7, 9); + } + faultsim_save_and_close +} {} -do_malloc_test rtree3-3 -sqlprep { - CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2); - INSERT INTO rt VALUES(NULL, 3, 5, 7, 9); -} -tclbody { +do_faultsim_test rtree3-3a -faults oom* -prep { + faultsim_restore_and_reopen +} -body { db eval BEGIN for {set ii 0} {$ii < 100} {incr ii} { set f [expr rand()] db eval {INSERT INTO rt VALUES(NULL, $f*10.0, $f*10.0, $f*15.0, $f*15.0)} } db eval COMMIT +} +faultsim_save_and_close + +do_faultsim_test rtree3-3b -faults oom* -prep { + faultsim_restore_and_reopen +} -body { db eval BEGIN for {set ii 0} {$ii < 100} {incr ii} { set f [expr rand()] @@ -68,4 +96,28 @@ do_malloc_test rtree3-3 -sqlprep { db eval COMMIT } +} + +do_test rtree3-4.prep { + faultsim_delete_and_reopen + execsql { + BEGIN; + PRAGMA page_size = 512; + CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2); + } + for {set i 0} {$i < 1500} {incr i} { + execsql { INSERT INTO rt VALUES($i, $i, $i+1, $i, $i+1) } + } + execsql { COMMIT } + faultsim_save_and_close +} {} + +do_faultsim_test rtree3-4 -faults oom-transient -prep { + faultsim_restore_and_reopen +} -body { + db eval { SELECT count(*) FROM rt } +} -test { + faultsim_test_result {0 1500} +} + finish_test diff --git a/ext/rtree/rtree4.test b/ext/rtree/rtree4.test index fa0d606faf..715473bf02 100644 --- a/ext/rtree/rtree4.test +++ b/ext/rtree/rtree4.test @@ -23,7 +23,7 @@ ifcapable !rtree { } set ::NROW 2500 -if {[info exists ISQUICK] && $ISQUICK} { +if {[info exists G(isquick)] && $G(isquick)} { set ::NROW 250 } diff --git a/ext/rtree/rtree8.test b/ext/rtree/rtree8.test new file mode 100644 index 0000000000..e48dc12df8 --- /dev/null +++ b/ext/rtree/rtree8.test @@ -0,0 +1,126 @@ +# 2010 February 16 +# +# 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. +# +#*********************************************************************** +# +# + +if {![info exists testdir]} { + set testdir [file join [file dirname $argv0] .. .. test] +} +source $testdir/tester.tcl +ifcapable !rtree { finish_test ; return } + +#------------------------------------------------------------------------- +# The following block of tests - rtree8-1.* - feature reading and writing +# an r-tree table while there exist open cursors on it. +# +proc populate_t1 {n} { + execsql { DELETE FROM t1 } + for {set i 1} {$i <= $n} {incr i} { + execsql { INSERT INTO t1 VALUES($i, $i, $i+2) } + } +} + +# A DELETE while a cursor is reading the table. +# +do_test rtree8-1.1.1 { + execsql { PRAGMA page_size = 512 } + execsql { CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2) } + populate_t1 5 +} {} +do_test rtree8-1.1.2 { + set res [list] + db eval { SELECT * FROM t1 } { + lappend res $x1 $x2 + if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } } + } + set res +} {1 3 2 4 3 5} +do_test rtree8-1.1.3 { + execsql { SELECT * FROM t1 } +} {1 1 3 2 2 4 3 3 5} + +# Many SELECTs on the same small table. +# +proc nested_select {n} { + set ::max $n + db eval { SELECT * FROM t1 } { + if {$id == $n} { nested_select [expr $n+1] } + } + return $::max +} +do_test rtree8-1.2.1 { populate_t1 50 } {} +do_test rtree8-1.2.2 { nested_select 1 } {51} + +# This test runs many SELECT queries simultaneously against a large +# table, causing a collision in the hash-table used to store r-tree +# nodes internally. +# +populate_t1 1500 +do_execsql_test rtree8-1.3.1 { SELECT max(nodeno) FROM t1_node } {164} +do_test rtree8-1.3.2 { + set rowids [execsql {SELECT min(rowid) FROM t1_rowid GROUP BY nodeno}] + set stmt_list [list] + foreach row $rowids { + set stmt [sqlite3_prepare db "SELECT * FROM t1 WHERE id = $row" -1 tail] + sqlite3_step $stmt + lappend res_list [sqlite3_column_int $stmt 0] + lappend stmt_list $stmt + } +} {} +do_test rtree8-1.3.3 { set res_list } $rowids +do_execsql_test rtree8-1.3.4 { SELECT count(*) FROM t1 } {1500} +do_test rtree8-1.3.5 { + foreach stmt $stmt_list { sqlite3_finalize $stmt } +} {} + + +#------------------------------------------------------------------------- +# The following block of tests - rtree8-2.* - test a couple of database +# corruption cases. In this case things are not corrupted at the b-tree +# level, but the contents of the various tables used internally by an +# r-tree table are inconsistent. +# +populate_t1 50 +do_execsql_test rtree8-2.1.1 { SELECT max(nodeno) FROM t1_node } {5} +do_execsql_test rtree8-2.1.2 { DELETE FROM t1_node } {} +for {set i 1} {$i <= 50} {incr i} { + do_catchsql_test rtree8-2.1.3.$i { + SELECT * FROM t1 WHERE id = $i + } {1 {database disk image is malformed}} +} +do_catchsql_test rtree8-2.1.4 { + SELECT * FROM t1 +} {1 {database disk image is malformed}} +do_catchsql_test rtree8-2.1.5 { + DELETE FROM t1 +} {1 {database disk image is malformed}} + +do_execsql_test rtree8-2.1.6 { + DELETE FROM t1_node; + DELETE FROM t1_parent; + DELETE FROM t1_rowid; + DROP TABLE t1; + CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2); +} {} + +#------------------------------------------------------------------------- +# Test that trying to use the MATCH operator with the r-tree module does +# not confuse it. +# +breakpoint +populate_t1 10 +do_catchsql_test rtree8-3.1 { + SELECT * FROM t1 WHERE x1 MATCH '1234' +} {1 {}} + + +finish_test + diff --git a/manifest b/manifest index 688fdc247e..ed16861ae1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Replicate\sasserts\son\sunixOpen()\sto\swinOpen()\sin\sos_win.c. -D 2010-08-24T20:46:53 +C Test\scases\sto\simprove\scoverage\sof\srtree\smodule.\sFixes\sassociated\swith\sthe\ssame. +D 2010-08-25T17:53:17 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 543f91f24cd7fee774ecc0a61c19704c0c3e78fd F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -78,15 +78,16 @@ F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9 F ext/icu/icu.c 850e9a36567bbcce6bd85a4b68243cad8e3c2de2 F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 1a39ad566196d2342f4a5ef337e165b7a016e6cd +F ext/rtree/rtree.c 73a4df9b61bfdb39e29d9d8a9927d811bb0f3389 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test 51bb0cd0405970501e63258401ae5ad235a4f468 -F ext/rtree/rtree2.test 7b665c44d25e51b3098068d983a39902b2e2d7a1 -F ext/rtree/rtree3.test dece988c363368af8c11862995c762071894918f -F ext/rtree/rtree4.test 94fdd570ab5bc47244d87d4590023be43ac786bd +F ext/rtree/rtree2.test 47b90f549a59e667e9fb01338956ead6f66c8d9d +F ext/rtree/rtree3.test 5ffcb3f44fe925e7a2e6e1960f3d2bf628683db3 +F ext/rtree/rtree4.test 2adce44dc544f6eb570898c8d5270bdf6ca64bd8 F ext/rtree/rtree5.test 92508f5152a50110af6551fa5b769d1bbd7c4ef3 F ext/rtree/rtree6.test 903720aaab819764c3693aaac0affe8174104ac8 F ext/rtree/rtree7.test 6fd29fb8e13795c822f4ceeea92ab5d61c96976d +F ext/rtree/rtree8.test d226534180f063924ee9d5500d43aebaeba28c7e F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/tkt3363.test 2bf324f7908084a5f463de3109db9c6e607feb1b @@ -846,7 +847,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P d1ed743b6ed07ad0ee7d466932c5a83caa9489ee -R 4de3851ce739f58f5ec292f30759a537 -U shaneh -Z b2eb9e260c96bf7904a512bfdbfae9ac +P 40526d8390896ccb883c45afa70e7adb568d174f +R 34bbfc350aec51a2c8611327e89641b5 +U dan +Z ca03a4a4ecb8f93f6b9fcda928df5c52 diff --git a/manifest.uuid b/manifest.uuid index 401d4c42d5..6c1567bfc0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -40526d8390896ccb883c45afa70e7adb568d174f \ No newline at end of file +865cec04e4d814f63fb71feb67de7f06f8d54035 \ No newline at end of file