quota.test 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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. set testdir [file dirname $argv0]
  13. source $testdir/tester.tcl
  14. # If SQLITE_CURDIR is not defined, omit this file.
  15. ifcapable !curdir {
  16. finish_test
  17. return
  18. }
  19. source $testdir/malloc_common.tcl
  20. unset -nocomplain defaultVfs
  21. set defaultVfs [file_control_vfsname db]
  22. db close
  23. do_test quota-1.1 { sqlite3_quota_initialize nosuchvfs 1 } {SQLITE_ERROR}
  24. do_test quota-1.2 { sqlite3_quota_initialize "" 1 } {SQLITE_OK}
  25. do_test quota-1.3 { sqlite3_quota_initialize "" 1 } {SQLITE_MISUSE}
  26. do_test quota-1.4 { sqlite3_quota_shutdown } {SQLITE_OK}
  27. do_test quota-1.5 { sqlite3_quota_initialize "" 0 } {SQLITE_OK}
  28. do_test quota-1.6 { sqlite3_quota_shutdown } {SQLITE_OK}
  29. do_test quota-1.7 { sqlite3_quota_initialize "" 1 } {SQLITE_OK}
  30. do_test quota-1.8 { sqlite3_quota_shutdown } {SQLITE_OK}
  31. #-------------------------------------------------------------------------
  32. # Some simple warm-body tests with a single database file in rollback
  33. # mode:
  34. #
  35. # quota-2.1.*: Test that SQLITE_FULL is returned if the database would
  36. # exceed the configured quota.
  37. #
  38. # quota-2.2.*: Test that SQLITE_FULL is not returned and the database
  39. # grows if the callback extends the quota when the database
  40. # attempts to grow beyond the configured quota.
  41. #
  42. # quota-2.3.*: Open and close a db that is not part of any quota group. At
  43. # one point this was causing mutex refs to be leaked.
  44. #
  45. # quota-2.4.*: Try to shutdown the quota system before closing the db
  46. # file. Check that this fails and the quota system still works
  47. # afterwards. Then close the database and successfully shut
  48. # down the quota system.
  49. #
  50. sqlite3_quota_initialize "" 1
  51. unset -nocomplain quota_request_ok
  52. proc quota_check {filename limitvar size} {
  53. upvar $limitvar limit
  54. lappend ::quota [set limit] $size
  55. if {[info exists ::quota_request_ok]} { set limit $size }
  56. }
  57. do_test quota-2.1.1 {
  58. sqlite3_quota_set *test.db 4096 quota_check
  59. } {SQLITE_OK}
  60. do_test quota-2.1.2 {
  61. sqlite3 db test.db
  62. execsql {
  63. PRAGMA page_size=1024;
  64. PRAGMA auto_vacuum=OFF;
  65. PRAGMA journal_mode=DELETE;
  66. }
  67. set ::quota [list]
  68. execsql {
  69. CREATE TABLE t1(a, b);
  70. INSERT INTO t1 VALUES(1, randomblob(1100));
  71. INSERT INTO t1 VALUES(2, randomblob(1100));
  72. }
  73. set ::quota
  74. } {}
  75. do_test quota-2.1.2.1 {
  76. file_control_vfsname db
  77. } quota/$defaultVfs
  78. do_test quota-2.1.3 { file size test.db } {4096}
  79. do_test quota-2.1.4 {
  80. catchsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
  81. } {1 {database or disk is full}}
  82. do_test quota-2.1.5 { set ::quota } {4096 5120}
  83. set ::quota_request_ok 1
  84. set ::quota [list]
  85. do_test quota-2.2.1 {
  86. execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
  87. } {}
  88. do_test quota-2.2.2 { set ::quota } {4096 5120}
  89. do_test quota-2.2.3 { file size test.db } {5120}
  90. unset ::quota_request_ok
  91. do_test quota-2.3.1 {
  92. sqlite3 db2 bak.db
  93. db2 close
  94. } {}
  95. do_test quota-2.4.1 {
  96. sqlite3_quota_shutdown
  97. } {SQLITE_MISUSE}
  98. set ::quota [list]
  99. do_test quota-2.4.2 {
  100. catchsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
  101. } {1 {database or disk is full}}
  102. do_test quota-2.4.3 { set ::quota } {5120 6144}
  103. do_test quota-2.4.4 { file size test.db } {5120}
  104. do_test quota-2.4.99 {
  105. db close
  106. sqlite3_quota_shutdown
  107. } {SQLITE_OK}
  108. #-------------------------------------------------------------------------
  109. # Try some tests with more than one connection to a database file. Still
  110. # in rollback mode.
  111. #
  112. # quota-3.1.*: Two connections to a single database file.
  113. #
  114. # quota-3.2.*: Two connections to each of several database files (that
  115. # are in the same quota group).
  116. #
  117. proc quota_check {filename limitvar size} {
  118. upvar $limitvar limit
  119. lappend ::quota [set limit] $size
  120. if {[info exists ::quota_request_ok]} { set limit $size }
  121. }
  122. do_test quota-3.1.1 {
  123. forcedelete test.db
  124. sqlite3_quota_initialize "" 1
  125. sqlite3_quota_set *test.db 4096 quota_check
  126. } {SQLITE_OK}
  127. do_test quota-3.1.2 {
  128. sqlite3 db test.db
  129. execsql {
  130. PRAGMA page_size = 1024;
  131. PRAGMA journal_mode = delete;
  132. PRAGMA auto_vacuum = off;
  133. CREATE TABLE t1(a PRIMARY KEY, b);
  134. INSERT INTO t1 VALUES(1, 'one');
  135. }
  136. file size test.db
  137. } {3072}
  138. do_test quota-3.1.3 {
  139. sqlite3 db2 test.db
  140. set ::quota [list]
  141. execsql { CREATE TABLE t2(a, b) } db2
  142. set ::quota
  143. } {}
  144. do_test quota-3.1.4 {
  145. catchsql { CREATE TABLE t3(a, b) }
  146. } {1 {database or disk is full}}
  147. do_test quota-3.1.5 {
  148. set ::quota_request_ok 1
  149. execsql { CREATE TABLE t3(a, b) }
  150. } {}
  151. do_test quota-3.1.6 {
  152. db close
  153. db2 close
  154. sqlite3_quota_set *test.db 0 {}
  155. } {SQLITE_OK}
  156. do_test quota-3.2.1 {
  157. delete_file force test.db test2.db
  158. sqlite3_quota_set * 4096 {}
  159. sqlite3 db1a test.db
  160. sqlite3 db2a test2.db
  161. foreach db {db1a db2a} {
  162. execsql {
  163. PRAGMA page_size = 1024;
  164. PRAGMA journal_mode = delete;
  165. PRAGMA auto_vacuum = off;
  166. CREATE TABLE t1(a, b);
  167. } $db
  168. }
  169. sqlite3 db1b test.db
  170. sqlite3 db2b test2.db
  171. list [file size test.db] [file size test2.db]
  172. } {2048 2048}
  173. catch { unset ::quota_request_ok }
  174. do_test quota-3.2.2 { execsql { INSERT INTO t1 VALUES('x', 'y') } db1a } {}
  175. do_test quota-3.2.3 { execsql { INSERT INTO t1 VALUES('v', 'w') } db1b } {}
  176. do_test quota-3.2.4 { execsql { INSERT INTO t1 VALUES('t', 'u') } db2a } {}
  177. do_test quota-3.2.5 { execsql { INSERT INTO t1 VALUES('r', 's') } db2b } {}
  178. do_test quota-3.2.6 {
  179. catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1a
  180. } {1 {database or disk is full}}
  181. do_test quota-3.2.7 {
  182. catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1b
  183. } {1 {database or disk is full}}
  184. do_test quota-3.2.8 {
  185. catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2a
  186. } {1 {database or disk is full}}
  187. do_test quota-3.2.9 {
  188. catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2b
  189. } {1 {database or disk is full}}
  190. set ::quota [list]
  191. proc quota_callback {file limitvar size} {
  192. upvar $limitvar limit
  193. if {$::tcl_platform(platform)=="windows"} {
  194. set file [ lindex [string map {\\ \/} $file] 0 ]
  195. }
  196. lappend ::quota $file $size
  197. set limit 0
  198. }
  199. sqlite3_quota_set * 4096 quota_callback
  200. do_test quota-3.3.1 {
  201. execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1a
  202. execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1b
  203. execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2a
  204. execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2b
  205. set ::quota
  206. } [list [file join [get_pwd] test.db] 5120]
  207. do_test quota-3.2.X {
  208. foreach db {db1a db2a db2b db1b} { catch { $db close } }
  209. sqlite3_quota_set * 0 {}
  210. } {SQLITE_OK}
  211. #-------------------------------------------------------------------------
  212. # Quotas are deleted when unused and when their limit is set to zero
  213. #
  214. # Return a list of all currently defined quotas. Each quota is identified
  215. # by its pattern.
  216. proc quota_list {} {
  217. set allq {}
  218. foreach q [sqlite3_quota_dump] {
  219. lappend allq [lindex $q 0]
  220. }
  221. return [lsort $allq]
  222. }
  223. proc quota_size {name} {
  224. set allq {}
  225. foreach q [sqlite3_quota_dump] {
  226. if {[lindex $q 0]==$name} {return [lindex $q 2]}
  227. }
  228. return 0
  229. }
  230. do_test quota-4.1.1 {
  231. sqlite3_quota_set *test.db 0 {}
  232. quota_list
  233. } {}
  234. do_test quota-4.1.2 {
  235. sqlite3_quota_set *test.db 4096 {}
  236. quota_list
  237. } {*test.db}
  238. do_test quota-4.1.3 {
  239. sqlite3_quota_set *test2.db 0 {}
  240. quota_list
  241. } {*test.db}
  242. do_test quota-4.1.4 {
  243. sqlite3_quota_set *test2.db 100000 {}
  244. quota_list
  245. } {*test.db *test2.db}
  246. do_test quota-4.1.5 {
  247. sqlite3_quota_set *test.db 0 {}
  248. quota_list
  249. } {*test2.db}
  250. do_test quota-4.1.6 {
  251. forcedelete test2.db test2.db-journal test2.db-wal
  252. sqlite3 db test2.db
  253. db eval {CREATE TABLE t2(x); INSERT INTO t2 VALUES('tab-t2');}
  254. quota_list
  255. } {*test2.db}
  256. do_test quota-4.1.7 {
  257. catchsql {INSERT INTO t2 VALUES(zeroblob(200000))}
  258. } {1 {database or disk is full}}
  259. do_test quota-4.1.8 {
  260. sqlite3 db2 test2.db
  261. db2 eval {SELECT * FROM t2}
  262. } {tab-t2}
  263. do_test quota-4.1.9 {
  264. sqlite3_quota_set *test2.db 0 {}
  265. catchsql {INSERT INTO t2 VALUES(zeroblob(200000))}
  266. } {0 {}}
  267. do_test quota-4.1.10 {
  268. quota_list
  269. } {*test2.db}
  270. do_test quota-4.1.11 {
  271. db2 close
  272. quota_list
  273. } {*test2.db}
  274. do_test quota-4.1.12 {
  275. db close
  276. quota_list
  277. } {}
  278. do_test quota-4.2.1 {
  279. sqlite3_quota_set A 1000 {}
  280. sqlite3_quota_set B 1000 {}
  281. sqlite3_quota_set C 1000 {}
  282. sqlite3_quota_set D 1000 {}
  283. quota_list
  284. } {A B C D}
  285. do_test quota-4.2.2 {
  286. sqlite3_quota_set C 0 {}
  287. sqlite3_quota_set B 0 {}
  288. quota_list
  289. } {A D}
  290. do_test quota-4.2.3 {
  291. sqlite3_quota_set A 0 {}
  292. sqlite3_quota_set D 0 {}
  293. quota_list
  294. } {}
  295. do_test quota-4.2.4 {
  296. sqlite3_quota_set A 1000 {}
  297. sqlite3_quota_set B 1000 {}
  298. sqlite3_quota_set C 1000 {}
  299. sqlite3_quota_set A 0 {}
  300. sqlite3_quota_set B 0 {}
  301. sqlite3_quota_set C 0 {}
  302. quota_list
  303. } {}
  304. do_test quota-4.2.5 {
  305. sqlite3_quota_set A 1000 {}
  306. sqlite3_quota_set B 1000 {}
  307. sqlite3_quota_set C 1000 {}
  308. sqlite3_quota_set C 0 {}
  309. sqlite3_quota_set B 0 {}
  310. sqlite3_quota_set A 0 {}
  311. quota_list
  312. } {}
  313. do_test quota-4.3.1 {
  314. sqlite3_quota_set A 1000 quota_callback
  315. sqlite3 db A
  316. sqlite3_quota_set A 0 quota_callback
  317. db close
  318. quota_list
  319. } {}
  320. unset -nocomplain quotagroup
  321. if {$tcl_platform(platform)=="windows"} {
  322. set quotagroup *\\quota-test-A?.db
  323. } else {
  324. set quotagroup */quota-test-A?.db
  325. }
  326. foreach file [glob -nocomplain quota-test-A*] {
  327. forcedelete $file
  328. }
  329. do_test quota-4.4.1 {
  330. set ::quota {}
  331. sqlite3_quota_set $::quotagroup 10000 quota_callback
  332. forcedelete ./quota-test-A1.db ./quota-test-A2.db
  333. sqlite3 db ./quota-test-A1.db
  334. db eval {
  335. CREATE TABLE t1(x);
  336. INSERT INTO t1 VALUES(randomblob(5000));
  337. }
  338. quota_list
  339. } [list $quotagroup]
  340. do_test quota-4.4.2 {
  341. expr {$::quota==""}
  342. } {1}
  343. do_test quota-4.4.3 {
  344. db close
  345. sqlite3 db ./quota-test-A2.db
  346. db eval {
  347. CREATE TABLE t1(x);
  348. INSERT INTO t1 VALUES(randomblob(5000));
  349. }
  350. quota_list
  351. } [list $quotagroup]
  352. do_test quota-4.4.4 {
  353. expr {$::quota!=""}
  354. } {1}
  355. do_test quota-4.4.5 {
  356. db close
  357. sqlite3_quota_set $::quotagroup 0 {}
  358. sqlite3_quota_dump
  359. } {}
  360. do_test quota-4.4.6 {
  361. sqlite3_quota_set $quotagroup 10000 quota_callback
  362. sqlite3 db quota-test-A1.db
  363. db eval {SELECT count(*) FROM sqlite_master}
  364. quota_size $quotagroup
  365. } [file size quota-test-A1.db]
  366. do_test quota-4.4.7 {
  367. sqlite3_quota_file quota-test-A2.db
  368. quota_size $::quotagroup
  369. } [expr {[file size quota-test-A1.db]+[file size quota-test-A2.db]}]
  370. unset -nocomplain quotagroup
  371. if {$tcl_platform(platform)=="windows"} {
  372. set quotagroup *\\quota-test-B*
  373. } else {
  374. set quotagroup */quota-test-B*
  375. }
  376. foreach file [glob -nocomplain quota-test-B*] {
  377. forcedelete $file
  378. }
  379. do_test quota-4.5.1 {
  380. sqlite3_quota_set $::quotagroup 100000 quota_callback
  381. quota_size $::quotagroup
  382. } {0}
  383. do_test quota-4.5.2 {
  384. sqlite3_quota_file quota-test-B1.txt
  385. quota_size $::quotagroup
  386. } {0}
  387. proc add_to_file {name n} {
  388. set out [open $name a]
  389. fconfigure $out -translation binary
  390. puts -nonewline $out [string repeat x $n]
  391. close $out
  392. }
  393. do_test quota-4.5.3 {
  394. add_to_file quota-test-B1.txt 123
  395. sqlite3_quota_file quota-test-B1.txt
  396. quota_size $::quotagroup
  397. } {123}
  398. do_test quota-4.5.4 {
  399. add_to_file quota-test-B2.txt 234
  400. sqlite3_quota_file quota-test-B2.txt
  401. quota_size $::quotagroup
  402. } {357}
  403. do_test quota-4.5.5 {
  404. add_to_file quota-test-B1.txt 2000
  405. sqlite3_quota_file quota-test-B1.txt
  406. quota_size $::quotagroup
  407. } {2357}
  408. do_test quota-4.5.6 {
  409. forcedelete quota-test-B1.txt
  410. sqlite3_quota_file quota-test-B1.txt
  411. quota_size $::quotagroup
  412. } {234}
  413. do_test quota-4.5.7 {
  414. forcedelete quota-test-B2.txt
  415. sqlite3_quota_file quota-test-B2.txt
  416. quota_size $::quotagroup
  417. } {0}
  418. do_test quota-4.5.8 {
  419. add_to_file quota-test-B3.txt 1234
  420. sqlite3_quota_file quota-test-B3.txt
  421. quota_size $::quotagroup
  422. } {1234}
  423. do_test quota-4.5.9 {
  424. sqlite3_quota_set $quotagroup 0 {}
  425. quota_size $::quotagroup
  426. } {0}
  427. do_test quota-4.9.1 {
  428. db close
  429. sqlite3_quota_set A 1000 quota_callback
  430. sqlite3_quota_shutdown
  431. } {SQLITE_OK}
  432. do_test quota-4.9.2 {
  433. quota_list
  434. } {}
  435. #-------------------------------------------------------------------------
  436. # The following tests test that the quota VFS handles malloc and IO
  437. # errors.
  438. #
  439. sqlite3_quota_initialize "" 1
  440. sqlite3_quota_set *test.db 4096 {}
  441. do_faultsim_test quota-5.1 -prep {
  442. catch {db close}
  443. } -body {
  444. sqlite3 db test2.db
  445. }
  446. do_faultsim_test quota-5.2 -prep {
  447. catch {db close}
  448. } -body {
  449. sqlite3 db test.db
  450. }
  451. catch { db close }
  452. forcedelete test.db
  453. do_test quota-5.3.prep {
  454. sqlite3 db test.db
  455. execsql {
  456. PRAGMA auto_vacuum = 1;
  457. PRAGMA page_size = 1024;
  458. CREATE TABLE t1(a, b);
  459. INSERT INTO t1 VALUES(10, zeroblob(1200));
  460. }
  461. faultsim_save_and_close
  462. } {}
  463. do_faultsim_test quota-5.3 -prep {
  464. faultsim_restore_and_reopen
  465. } -body {
  466. execsql { DELETE FROM t1 }
  467. }
  468. do_test quota-5.4.1 {
  469. catch { db close }
  470. forcedelete test.db
  471. file mkdir test.db
  472. list [catch { sqlite3 db test.db } msg] $msg
  473. } {1 {unable to open database file}}
  474. do_faultsim_test quota-5.5 -prep {
  475. catch { sqlite3_quota_shutdown }
  476. } -body {
  477. sqlite3_quota_initialize "" 1
  478. }
  479. do_faultsim_test quota-5.6 -prep {
  480. catch { sqlite3_quota_shutdown }
  481. sqlite3_quota_initialize "" 1
  482. } -body {
  483. sqlite3_quota_set * 4096 {}
  484. }
  485. catch { sqlite3_quota_shutdown }
  486. finish_test