1# 2010 September 1 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# 12 13set testdir [file dirname $argv0] 14source $testdir/tester.tcl 15source $testdir/malloc_common.tcl 16 17db close 18 19do_test quota-1.1 { sqlite3_quota_initialize nosuchvfs 1 } {SQLITE_ERROR} 20do_test quota-1.2 { sqlite3_quota_initialize "" 1 } {SQLITE_OK} 21do_test quota-1.3 { sqlite3_quota_initialize "" 1 } {SQLITE_MISUSE} 22do_test quota-1.4 { sqlite3_quota_shutdown } {SQLITE_OK} 23 24do_test quota-1.5 { sqlite3_quota_initialize "" 0 } {SQLITE_OK} 25do_test quota-1.6 { sqlite3_quota_shutdown } {SQLITE_OK} 26do_test quota-1.7 { sqlite3_quota_initialize "" 1 } {SQLITE_OK} 27do_test quota-1.8 { sqlite3_quota_shutdown } {SQLITE_OK} 28 29 30#------------------------------------------------------------------------- 31# Some simple warm-body tests with a single database file in rollback 32# mode: 33# 34# quota-2.1.*: Test that SQLITE_FULL is returned if the database would 35# exceed the configured quota. 36# 37# quota-2.2.*: Test that SQLITE_FULL is not returned and the database 38# grows if the callback extends the quota when the database 39# attempts to grow beyond the configured quota. 40# 41# quota-2.3.*: Open and close a db that is not part of any quota group. At 42# one point this was causing mutex refs to be leaked. 43# 44# quota-2.4.*: Try to shutdown the quota system before closing the db 45# file. Check that this fails and the quota system still works 46# afterwards. Then close the database and successfully shut 47# down the quota system. 48# 49sqlite3_quota_initialize "" 1 50 51proc quota_check {filename limitvar size} { 52 upvar $limitvar limit 53 54 lappend ::quota [set limit] $size 55 if {[info exists ::quota_request_ok]} { set limit $size } 56} 57 58do_test quota-2.1.1 { 59 sqlite3_quota_set *test.db 4096 quota_check 60} {SQLITE_OK} 61do_test quota-2.1.2 { 62 sqlite3 db test.db 63 execsql { 64 PRAGMA page_size=1024; 65 PRAGMA auto_vacuum=OFF; 66 PRAGMA journal_mode=DELETE; 67 } 68 set ::quota [list] 69 execsql { 70 CREATE TABLE t1(a, b); 71 INSERT INTO t1 VALUES(1, randomblob(1100)); 72 INSERT INTO t1 VALUES(2, randomblob(1100)); 73 } 74 set ::quota 75} {} 76do_test quota-2.1.3 { file size test.db } {4096} 77do_test quota-2.1.4 { 78 catchsql { INSERT INTO t1 VALUES(3, randomblob(1100)) } 79} {1 {database or disk is full}} 80do_test quota-2.1.5 { set ::quota } {4096 5120} 81 82set ::quota_request_ok 1 83set ::quota [list] 84do_test quota-2.2.1 { 85 execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) } 86} {} 87do_test quota-2.2.2 { set ::quota } {4096 5120} 88do_test quota-2.2.3 { file size test.db } {5120} 89unset ::quota_request_ok 90 91do_test quota-2.3.1 { 92 sqlite3 db2 bak.db 93 db2 close 94} {} 95 96do_test quota-2.4.1 { 97 sqlite3_quota_shutdown 98} {SQLITE_MISUSE} 99set ::quota [list] 100do_test quota-2.4.2 { 101 catchsql { INSERT INTO t1 VALUES(3, randomblob(1100)) } 102} {1 {database or disk is full}} 103do_test quota-2.4.3 { set ::quota } {5120 6144} 104do_test quota-2.4.4 { file size test.db } {5120} 105do_test quota-2.4.99 { 106 db close 107 sqlite3_quota_shutdown 108} {SQLITE_OK} 109 110#------------------------------------------------------------------------- 111# Try some tests with more than one connection to a database file. Still 112# in rollback mode. 113# 114# quota-3.1.*: Two connections to a single database file. 115# 116# quota-3.2.*: Two connections to each of several database files (that 117# are in the same quota group). 118# 119proc quota_check {filename limitvar size} { 120 upvar $limitvar limit 121 lappend ::quota [set limit] $size 122 if {[info exists ::quota_request_ok]} { set limit $size } 123} 124 125do_test quota-3.1.1 { 126 file delete -force test.db 127 sqlite3_quota_initialize "" 1 128 sqlite3_quota_set *test.db 4096 quota_check 129} {SQLITE_OK} 130do_test quota-3.1.2 { 131 sqlite3 db test.db 132 execsql { 133 PRAGMA page_size = 1024; 134 PRAGMA journal_mode = delete; 135 PRAGMA auto_vacuum = off; 136 CREATE TABLE t1(a PRIMARY KEY, b); 137 INSERT INTO t1 VALUES(1, 'one'); 138 } 139 file size test.db 140} {3072} 141do_test quota-3.1.3 { 142 sqlite3 db2 test.db 143 set ::quota [list] 144 execsql { CREATE TABLE t2(a, b) } db2 145 set ::quota 146} {} 147do_test quota-3.1.4 { 148 catchsql { CREATE TABLE t3(a, b) } 149} {1 {database or disk is full}} 150do_test quota-3.1.5 { 151 set ::quota_request_ok 1 152 execsql { CREATE TABLE t3(a, b) } 153} {} 154do_test quota-3.1.6 { 155 db close 156 db2 close 157 sqlite3_quota_set *test.db 0 {} 158} {SQLITE_OK} 159 160do_test quota-3.2.1 { 161 file delete force test.db test2.db 162 163 sqlite3_quota_set * 4096 {} 164 sqlite3 db1a test.db 165 sqlite3 db2a test2.db 166 167 foreach db {db1a db2a} { 168 execsql { 169 PRAGMA page_size = 1024; 170 PRAGMA journal_mode = delete; 171 PRAGMA auto_vacuum = off; 172 CREATE TABLE t1(a, b); 173 } $db 174 } 175 176 sqlite3 db1b test.db 177 sqlite3 db2b test2.db 178 179 list [file size test.db] [file size test2.db] 180} {2048 2048} 181 182catch { unset ::quota_request_ok } 183 184do_test quota-3.2.2 { execsql { INSERT INTO t1 VALUES('x', 'y') } db1a } {} 185do_test quota-3.2.3 { execsql { INSERT INTO t1 VALUES('v', 'w') } db1b } {} 186do_test quota-3.2.4 { execsql { INSERT INTO t1 VALUES('t', 'u') } db2a } {} 187do_test quota-3.2.5 { execsql { INSERT INTO t1 VALUES('r', 's') } db2b } {} 188 189do_test quota-3.2.6 { 190 catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1a 191} {1 {database or disk is full}} 192do_test quota-3.2.7 { 193 catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1b 194} {1 {database or disk is full}} 195do_test quota-3.2.8 { 196 catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2a 197} {1 {database or disk is full}} 198do_test quota-3.2.9 { 199 catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2b 200} {1 {database or disk is full}} 201 202set ::quota [list] 203proc quota_callback {file limitvar size} { 204 upvar $limitvar limit 205 lappend ::quota $file $size 206 set limit 0 207} 208sqlite3_quota_set * 4096 quota_callback 209do_test quota-3.3.1 { 210 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1a 211 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1b 212 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2a 213 execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2b 214 set ::quota 215} [list [file join [pwd] test.db] 5120] 216 217do_test quota-3.2.X { 218 foreach db {db1a db2a db2b db1b} { catch { $db close } } 219 sqlite3_quota_set * 0 {} 220} {SQLITE_OK} 221 222#------------------------------------------------------------------------- 223# Quotas are deleted when unused and when there limit is set to zero 224# 225 226# Return a list of all currently defined quotas. Each quota is identified 227# by its pattern. 228proc quota_list {} { 229 set allq {} 230 foreach q [sqlite3_quota_dump] { 231 lappend allq [lindex $q 0] 232 } 233 return [lsort $allq] 234} 235 236do_test quota-4.1.1 { 237 sqlite3_quota_set *test.db 0 {} 238 quota_list 239} {} 240do_test quota-4.1.2 { 241 sqlite3_quota_set *test.db 4096 {} 242 quota_list 243} {*test.db} 244do_test quota-4.1.3 { 245 sqlite3_quota_set *test2.db 0 {} 246 quota_list 247} {*test.db} 248do_test quota-4.1.4 { 249 sqlite3_quota_set *test2.db 100000 {} 250 quota_list 251} {*test.db *test2.db} 252do_test quota-4.1.5 { 253 sqlite3_quota_set *test.db 0 {} 254 quota_list 255} {*test2.db} 256do_test quota-4.1.6 { 257 file delete -force test2.db test2.db-journal test2.db-wal 258 sqlite3 db test2.db 259 db eval {CREATE TABLE t2(x); INSERT INTO t2 VALUES('tab-t2');} 260 quota_list 261} {*test2.db} 262do_test quota-4.1.7 { 263 catchsql {INSERT INTO t2 VALUES(zeroblob(200000))} 264} {1 {database or disk is full}} 265do_test quota-4.1.8 { 266 sqlite3 db2 test2.db 267 db2 eval {SELECT * FROM t2} 268} {tab-t2} 269do_test quota-4.1.9 { 270 sqlite3_quota_set *test2.db 0 {} 271 catchsql {INSERT INTO t2 VALUES(zeroblob(200000))} 272} {0 {}} 273do_test quota-4.1.10 { 274 quota_list 275} {*test2.db} 276do_test quota-4.1.11 { 277 db2 close 278 quota_list 279} {*test2.db} 280do_test quota-4.1.12 { 281 db close 282 quota_list 283} {} 284 285do_test quota-4.2.1 { 286 sqlite3_quota_set A 1000 {} 287 sqlite3_quota_set B 1000 {} 288 sqlite3_quota_set C 1000 {} 289 sqlite3_quota_set D 1000 {} 290 quota_list 291} {A B C D} 292do_test quota-4.2.2 { 293 sqlite3_quota_set C 0 {} 294 sqlite3_quota_set B 0 {} 295 quota_list 296} {A D} 297do_test quota-4.2.3 { 298 sqlite3_quota_set A 0 {} 299 sqlite3_quota_set D 0 {} 300 quota_list 301} {} 302do_test quota-4.2.4 { 303 sqlite3_quota_set A 1000 {} 304 sqlite3_quota_set B 1000 {} 305 sqlite3_quota_set C 1000 {} 306 sqlite3_quota_set A 0 {} 307 sqlite3_quota_set B 0 {} 308 sqlite3_quota_set C 0 {} 309 quota_list 310} {} 311do_test quota-4.2.5 { 312 sqlite3_quota_set A 1000 {} 313 sqlite3_quota_set B 1000 {} 314 sqlite3_quota_set C 1000 {} 315 sqlite3_quota_set C 0 {} 316 sqlite3_quota_set B 0 {} 317 sqlite3_quota_set A 0 {} 318 quota_list 319} {} 320 321do_test quota-4.3.1 { 322 sqlite3_quota_set A 1000 quota_callback 323 sqlite3 db A 324 sqlite3_quota_set A 0 quota_callback 325 db close 326 quota_list 327} {} 328 329do_test quota-4.4.1 { 330 sqlite3_quota_set A 1000 quota_callback 331 sqlite3_quota_shutdown 332} {SQLITE_OK} 333do_test quota-4.4.2 { 334 quota_list 335} {} 336 337#------------------------------------------------------------------------- 338# The following tests test that the quota VFS handles malloc and IO 339# errors. 340# 341 342sqlite3_quota_initialize "" 1 343sqlite3_quota_set *test.db 4096 {} 344 345do_faultsim_test quota-5.1 -prep { 346 catch {db close} 347} -body { 348 sqlite3 db test2.db 349} 350do_faultsim_test quota-5.2 -prep { 351 catch {db close} 352} -body { 353 sqlite3 db test.db 354} 355 356catch { db close } 357file delete -force test.db 358 359do_test quota-5.3.prep { 360 sqlite3 db test.db 361 execsql { 362 PRAGMA auto_vacuum = 1; 363 PRAGMA page_size = 1024; 364 CREATE TABLE t1(a, b); 365 INSERT INTO t1 VALUES(10, zeroblob(1200)); 366 } 367 faultsim_save_and_close 368} {} 369do_faultsim_test quota-5.3 -prep { 370 faultsim_restore_and_reopen 371} -body { 372 execsql { DELETE FROM t1 } 373} 374 375do_test quota-5.4.1 { 376 catch { db close } 377 file delete -force test.db 378 file mkdir test.db 379 list [catch { sqlite3 db test.db } msg] $msg 380} {1 {unable to open database file}} 381 382do_faultsim_test quota-5.5 -prep { 383 catch { sqlite3_quota_shutdown } 384} -body { 385 sqlite3_quota_initialize "" 1 386} 387 388do_faultsim_test quota-5.6 -prep { 389 catch { sqlite3_quota_shutdown } 390 sqlite3_quota_initialize "" 1 391} -body { 392 sqlite3_quota_set * 4096 {} 393} 394 395catch { sqlite3_quota_shutdown } 396finish_test 397