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