Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add tests (and associated fixes) to restore coverage of rtree.c. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
b06f4695bdab244d9c764c082cd434a7 |
User & Date: | dan 2010-08-30 15:43:45.000 |
Context
2010-08-30
| ||
16:15 | Fix a problem in pagerfault.test uncovered by the previous change. (check-in: b6719ce328 user: dan tags: trunk) | |
15:43 | Add tests (and associated fixes) to restore coverage of rtree.c. (check-in: b06f4695bd user: dan tags: trunk) | |
15:02 | Remove the sqlite3BtreeFactory() wrapper routine. All modules now call sqlite3BtreeOpen() directly. (check-in: 0900e35348 user: drh tags: trunk) | |
Changes
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
1102 1103 1104 1105 1106 1107 1108 | */ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ RtreeGeomBlob *p; RtreeGeometry *pGeom; int nBlob; /* Check that value is actually a blob. */ | | | | | | 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 | */ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ RtreeGeomBlob *p; RtreeGeometry *pGeom; int nBlob; /* Check that value is actually a blob. */ if( !sqlite3_value_type(pValue)==SQLITE_BLOB ) return SQLITE_ERROR; /* Check that the blob is roughly the right size. */ nBlob = sqlite3_value_bytes(pValue); if( nBlob<sizeof(RtreeGeomBlob) || ((nBlob-sizeof(RtreeGeomBlob))%sizeof(double))!=0 ){ return SQLITE_ERROR; } pGeom = (RtreeGeometry *)sqlite3_malloc(sizeof(RtreeGeometry) + nBlob); if( !pGeom ) return SQLITE_NOMEM; memset(pGeom, 0, sizeof(RtreeGeometry)); p = (RtreeGeomBlob *)&pGeom[1]; memcpy(p, sqlite3_value_blob(pValue), nBlob); if( p->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=(sizeof(RtreeGeomBlob) + (p->nParam-1)*sizeof(double)) ){ sqlite3_free(pGeom); return SQLITE_ERROR; } pGeom->pContext = p->pContext; pGeom->nParam = p->nParam; pGeom->aParam = p->aParam; pCons->xGeom = p->xGeom; |
︙ | ︙ | |||
1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 | ** sqlite uses an internal cost of 0.0). */ pIdxInfo->estimatedCost = 10.0; return SQLITE_OK; } if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ u8 op = 0; switch( p->op ){ case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break; case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break; case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break; case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; | > > > | > > | > | | | | | | | | | < < | | | | | | | | | | | < | 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 | ** sqlite uses an internal cost of 0.0). */ pIdxInfo->estimatedCost = 10.0; return SQLITE_OK; } if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ int j, opmsk; static const unsigned char compatible[] = { 0, 0, 1, 1, 2, 2 }; u8 op = 0; switch( p->op ){ case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break; case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break; case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break; case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; default: assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH ); op = RTREE_MATCH; break; } assert( op!=0 ); /* Make sure this particular constraint has not been used before. ** If it has been used before, ignore it. ** ** A <= or < can be used if there is a prior >= or >. ** A >= or > can be used if there is a prior < or <=. ** A <= or < is disqualified if there is a prior <=, <, or ==. ** A >= or > is disqualified if there is a prior >=, >, or ==. ** A == is disqualifed if there is any prior constraint. */ assert( compatible[RTREE_EQ & 7]==0 ); assert( compatible[RTREE_LT & 7]==1 ); assert( compatible[RTREE_LE & 7]==1 ); assert( compatible[RTREE_GT & 7]==2 ); assert( compatible[RTREE_GE & 7]==2 ); cCol = p->iColumn - 1 + 'a'; opmsk = compatible[op & 7]; for(j=0; j<iIdx; j+=2){ if( zIdxStr[j+1]==cCol && (compatible[zIdxStr[j] & 7] & opmsk)!=0 ){ op = 0; break; } } if( op ){ assert( iIdx<sizeof(zIdxStr)-1 ); zIdxStr[iIdx++] = op; zIdxStr[iIdx++] = cCol; pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); |
︙ | ︙ |
Changes to ext/rtree/rtree3.test.
︙ | ︙ | |||
201 202 203 204 205 206 207 208 209 | } do_faultsim_test rtree3-8 -faults oom-* -prep { catch { db close } } -body { sqlite3 db test.db } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | } do_faultsim_test rtree3-8 -faults oom-* -prep { catch { db close } } -body { sqlite3 db test.db } do_faultsim_test rtree3-9 -faults oom-* -prep { sqlite3 db :memory: } -body { set rc [register_cube_geom db] if {$rc != "SQLITE_OK"} { error $rc } } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} } do_test rtree3-10.prep { faultsim_delete_and_reopen execsql { CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2, z1, z2); INSERT INTO rt VALUES(1, 10, 10, 10, 11, 11, 11); INSERT INTO rt VALUES(2, 5, 6, 6, 7, 7, 8); } faultsim_save_and_close } {} do_faultsim_test rtree3-10 -faults oom-* -prep { faultsim_restore_and_reopen register_cube_geom db execsql { SELECT * FROM rt } } -body { execsql { SELECT ii FROM rt WHERE ii MATCH cube(4.5, 5.5, 6.5, 1, 1, 1) } } -test { faultsim_test_result {0 2} } finish_test |
Changes to ext/rtree/rtree8.test.
︙ | ︙ | |||
125 126 127 128 129 130 131 | #------------------------------------------------------------------------- # Test that trying to use the MATCH operator with the r-tree module does # not confuse it. # populate_t1 10 do_catchsql_test rtree8-3.1 { SELECT * FROM t1 WHERE x1 MATCH '1234' | | | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | #------------------------------------------------------------------------- # Test that trying to use the MATCH operator with the r-tree module does # not confuse it. # populate_t1 10 do_catchsql_test rtree8-3.1 { SELECT * FROM t1 WHERE x1 MATCH '1234' } {1 {SQL logic error or missing database}} #------------------------------------------------------------------------- # Test a couple of invalid arguments to rtreedepth(). # do_catchsql_test rtree8-4.1 { SELECT rtreedepth('hello world') } {1 {Invalid argument to rtreedepth()}} |
︙ | ︙ |
Changes to ext/rtree/rtree9.test.
︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | } {1 1.0 2.0 1.0 2.0 1.0 2.0} do_execsql_test rtree9-1.3 { SELECT * FROM rt WHERE id MATCH cube(3, 3, 3, 2, 2, 2); } {} do_execsql_test rtree9-1.4 { DELETE FROM rt; } {} for {set i 0} {$i < 1000} {incr i} { set x [expr $i%10] set y [expr ($i/10)%10] set z [expr ($i/100)%10] execsql { INSERT INTO rt VALUES($i, $x, $x+1, $y, $y+1, $z, $z+1) } } | > < > > > > > > > > > > > > > > > > > > > > > > | > > > > > | > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | } {1 1.0 2.0 1.0 2.0 1.0 2.0} do_execsql_test rtree9-1.3 { SELECT * FROM rt WHERE id MATCH cube(3, 3, 3, 2, 2, 2); } {} do_execsql_test rtree9-1.4 { DELETE FROM rt; } {} for {set i 0} {$i < 1000} {incr i} { set x [expr $i%10] set y [expr ($i/10)%10] set z [expr ($i/100)%10] execsql { INSERT INTO rt VALUES($i, $x, $x+1, $y, $y+1, $z, $z+1) } } do_execsql_test rtree9-2.1 { SELECT id FROM rt WHERE id MATCH cube(2.5, 2.5, 2.5, 1, 1, 1) ORDER BY id; } {222 223 232 233 322 323 332 333} do_execsql_test rtree9-2.2 { SELECT id FROM rt WHERE id MATCH cube(5.5, 5.5, 5.5, 1, 1, 1) ORDER BY id; } {555 556 565 566 655 656 665 666} do_execsql_test rtree9-3.1 { CREATE VIRTUAL TABLE rt32 USING rtree_i32(id, x1, x2, y1, y2, z1, z2); } {} for {set i 0} {$i < 1000} {incr i} { set x [expr $i%10] set y [expr ($i/10)%10] set z [expr ($i/100)%10] execsql { INSERT INTO rt32 VALUES($i, $x, $x+1, $y, $y+1, $z, $z+1) } } do_execsql_test rtree9-3.2 { SELECT id FROM rt32 WHERE id MATCH cube(3, 3, 3, 1, 1, 1) ORDER BY id; } {222 223 224 232 233 234 242 243 244 322 323 324 332 333 334 342 343 344 422 423 424 432 433 434 442 443 444} do_execsql_test rtree9-3.3 { SELECT id FROM rt32 WHERE id MATCH cube(5.5, 5.5, 5.5, 1, 1, 1) ORDER BY id; } {555 556 565 566 655 656 665 666} do_catchsql_test rtree9-4.1 { SELECT id FROM rt32 WHERE id MATCH cube(5.5, 5.5, 1, 1, 1) ORDER BY id; } {1 {SQL logic error or missing database}} for {set x 2} {$x<200} {incr x 2} { do_catchsql_test rtree9-4.2.[expr $x/2] { SELECT id FROM rt WHERE id MATCH randomblob($x) } {1 {SQL logic error or missing database}} } do_catchsql_test rtree9-4.3 { SELECT id FROM rt WHERE id MATCH CAST( (cube(5.5, 5.5, 5.5, 1, 1, 1) || X'1234567812345678') AS blob ) } {1 {SQL logic error or missing database}} finish_test |
Changes to src/test_rtree.c.
︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | double depth; }; static void cube_context_free(void *p){ sqlite3_free(p); } static int gHere = 42; /* ** Implementation of a simple r-tree geom callback to test for intersection ** of r-tree rows with a "cube" shape. Cubes are defined by six scalar ** coordinates as follows: ** | > > > > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | double depth; }; static void cube_context_free(void *p){ sqlite3_free(p); } /* ** The context pointer registered along with the 'cube' callback is ** always ((void *)&gHere). This is just to facilitate testing, it is not ** actually used for anything. */ static int gHere = 42; /* ** Implementation of a simple r-tree geom callback to test for intersection ** of r-tree rows with a "cube" shape. Cubes are defined by six scalar ** coordinates as follows: ** |
︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 | void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ #ifdef SQLITE_ENABLE_RTREE extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); sqlite3 *db; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; | > > | > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ #ifdef SQLITE_ENABLE_RTREE extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); extern const char *sqlite3TestErrorName(int); sqlite3 *db; int rc; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_rtree_geometry_callback(db, "cube", cube_geom, (void *)&gHere); Tcl_SetResult(interp, sqlite3TestErrorName(rc), TCL_STATIC); #endif return TCL_OK; } int Sqlitetestrtree_Init(Tcl_Interp *interp){ Tcl_CreateObjCommand(interp, "register_cube_geom", register_cube_geom, 0, 0); return TCL_OK; } |
Changes to test/malloc_common.tcl.
︙ | ︙ | |||
181 182 183 184 185 186 187 | } # The following procs are used as [do_one_faultsim_test] callbacks when # injecting OOM faults into test cases. # proc oom_injectstart {nRepeat iFail} { | | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | } # The following procs are used as [do_one_faultsim_test] callbacks when # injecting OOM faults into test cases. # proc oom_injectstart {nRepeat iFail} { sqlite3_memdebug_fail [expr $iFail-1] -repeat $nRepeat } proc oom_injectstop {} { sqlite3_memdebug_fail -1 } # The following procs are used as [do_one_faultsim_test] callbacks when # injecting IO error faults into test cases. |
︙ | ︙ |