3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
13 # This file implements tests for the appendvfs extension.
16 # avfs-1.0. Test that an appendvfs DB can be added to an empty (ZLF) file.
17 # avfs-1.1. Test that the DB can be read with correct content upon reopen.
18 # avfs-1.2. Test that an appendvfs DB can be added to a simple text file.
19 # avfs-1.3. Test that the DB can be read with correct content upon reopen.
20 # avfs-1.4. Test that appended DB is aligned to default page boundary.
21 # avfs-2.1. Test that the simple text file retains its initial text.
22 # avfs-3.1. Test that the appendvfs can grow and shrink, remaining intact.
23 # avfs-3.2. Test that appendvfs is intact after grow/shrink/close/reopen.
24 # avfs-3.3. Test that appendvfs can grow by many pages and be written.
25 # avfs-3.4. Test that grown appendvfs can be reopened and appear intact.
26 # avfs-3.5. Test that much grown appendvfs can shrink and reopen intact.
27 # avfs-4.1. Test shell's ability to append to a non-appendvfs file.
28 # avfs-4.2. Test shell's ability to append to empty or nonexistent file.
29 # avfs-4.3. Test shell's ability to reopen and alter an appendvfs file.
30 # avfs-5.1. Test appendvfs refusal to open too-tiny DB appended onto ZLF.
31 # avfs-5.2. Test appendvfs refusal to open too-tiny DB appended on other.
35 set testdir [file dirname $argv0]
36 source $testdir/tester.tcl
39 # Do not attempt this test if SQLITE_OMIT_VIRTUALTABLE is defined.
46 set CLI [test_find_cli]
50 load_static_extension db appendvfs
54 forcedelete $::fa $::fza
58 set shdo "sh_app1.sql"
63 set res [catchcmd "-batch -cmd \".read $shdo\""]
64 return [regexp {^.archive} [lindex $res 1]]
67 set ::vf "&vfs=apndvfs"
69 # Return file offset of appendvfs portion of a file, or {} if none such.
70 proc fosAvfs {fname} {
71 if {[file size $fname] < 25} {
74 if {[catch {set fd [open $fname rb]}]} {
81 if {$am ne "Start-Of-SQLite3-"} {
84 binary scan $ao "W" rvo
90 set out [open $::fza wb]
92 sqlite3 adb "file:$::fza?mode=rwc$::vf" -uri 1
94 PRAGMA page_size=1024;
96 CREATE TABLE t1(a TEXT);
97 INSERT INTO t1 VALUES ('dog'),('cat');
98 SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a);
99 } { lappend results $pets }
101 lappend results [fosAvfs $fza]
102 set ::result [join $results " | "]
107 sqlite3 adb "file:$::fza?mode=rw$::vf" -uri 1
109 SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a DESC);
110 } { lappend results $pets }
112 set ::result [join $results " | "]
117 set out [open $::fa wb]
118 set ::tlo { "Just some text," "and more text," "ending at 3 lines." }
119 puts $out [join $::tlo "\n"]
121 set adbSz [file size $::fa]
122 sqlite3 adb "file:$::fa?mode=rwc$::vf" -uri 1
124 PRAGMA auto_vacuum = 0;
125 PRAGMA page_size=512;
127 CREATE TABLE t1(a TEXT);
128 INSERT INTO t1 VALUES ('dog'),('cat'),('pig');
129 SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a);
130 } { lappend results $pets }
132 set adaSz [file size $::fa]
133 lappend results "Bytes before/after $adbSz/$adaSz"
134 set ::result [join $results " | "]
135 } {cat,dog,pig | Bytes before/after 50/5145}
139 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
141 SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a DESC);
142 } { lappend results $pets }
144 set ::result [join $results " | "]
148 set ::result [fosAvfs $fa]
152 set in [open $::fa r]
154 for {set i [llength $::tlo]} {$i > 0} {incr i -1} {
155 lappend tli [gets $in]
158 if { [join $tli ":"] ne [join $::tlo ":"] } {
159 set ::result "Appendee changed."
161 set ::result "Appendee intact."
165 # Set of repeatable random integers for a couple tests.
168 return [::tcl::mathfunc::int [expr $v * 100000]]
170 array set ::randints [list 0 [rint [::tcl::mathfunc::srand 0]]]
171 for {set i 1} {$i < $::nrint} {incr i} {
172 set ::randints($i) [rint [::tcl::mathfunc::rand]]
177 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
180 PRAGMA cache_size=10;
181 CREATE TABLE ri (i INTEGER);
184 for {set i 0} {$i < $::nrint} {incr i} {
185 set r $::randints($i)
186 set s $::randints([incr i])
187 set t $::randints([incr i])
188 set u $::randints([incr i])
189 set v $::randints([incr i])
191 INSERT INTO ri VALUES ($r),($s),($t),($u),($v)
196 SELECT integrity_check as ic FROM pragma_integrity_check();
197 } { lappend results $ic }
198 set adbSz [file size $::fa]
201 SELECT count(*) as ic FROM ri;
202 DELETE FROM ri WHERE (i % 50) <> 25;
203 SELECT integrity_check as ic FROM pragma_integrity_check();
205 SELECT integrity_check as ic FROM pragma_integrity_check();
206 SELECT count(*) as ic FROM ri;
209 set adaSz [file size $::fa]
210 set adba [expr ($adbSz + 0.1)/$adaSz]
211 # lappend results $adba
212 set results [concat $results [lrange $qr 0 2]]
213 lappend results [expr {$adba > 10.0}]
214 set ::result [join $results " | "]
215 } "ok | $::nrint | ok | ok | 1"
219 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
221 SELECT integrity_check as ic FROM pragma_integrity_check();
222 } { lappend results $ic }
224 set ::result [join $results " | "]
227 # avfs-3.3. Test that appendvfs can grow by many pages and be written.
230 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
233 while {$npages > 0} {
234 adb eval { INSERT INTO ri VALUES (randomblob(1500)) }
239 SELECT integrity_check as ic FROM pragma_integrity_check();
240 } { lappend results $ic }
242 set adaSzr [expr [file size $::fa] / 300.0 / 1500 ]
243 set okSzr [expr $adaSzr > 1.0 && $adaSzr < 1.3 ]
244 lappend results $okSzr
245 set ::result [join $results " | "]
248 # avfs-3.4. Test that grown appendvfs can be reopened and appear intact.
251 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
253 SELECT integrity_check as ic FROM pragma_integrity_check();
254 } { lappend results $ic }
259 # avfs-3.5. Test that much grown appendvfs can shrink and reopen intact.
262 set adbsz [file size $::fa]
263 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
265 DELETE FROM ri WHERE rowid % 8 <> 0;
266 SELECT integrity_check as ic FROM pragma_integrity_check();
268 SELECT integrity_check as ic FROM pragma_integrity_check();
269 } { lappend results $ic }
271 set adasz [file size $::fa]
272 lappend results [expr {$adbsz/$adasz > 5}]
273 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
275 SELECT integrity_check as ic FROM pragma_integrity_check();
276 } { lappend results $ic }
278 set ::result [join $results " | "]
281 set ::cliDoesAr [shellDoesAr]
284 set shdo "sh_app1.sql"
285 set shod "sh_app1.adb"
286 forcedelete $shdo $shod
287 set ofd [open $shdo w]
291 puts $ofd "pragma page_size=512;"
292 puts $ofd "create table sqlar (a);"
297 set ofd [open $shod wb]
298 puts $ofd "Some text."
300 set res [catchcmd "-append -batch -init $shdo $shod" ""]
301 lappend res [fosAvfs $shod]
302 forcedelete $shdo $shod
303 set ::result [join $res " | "]
307 set shdo "sh_app1.sql"
308 set shod "sh_app1.adb"
309 forcedelete $shdo $shod
310 set ofd [open $shdo w]
314 puts $ofd "pragma page_size=512;"
315 puts $ofd "create table sqlar (a);"
320 set ofd [open $shod wb]
322 set res [catchcmd "-append -batch -init $shdo $shod" ""]
323 lappend res [fosAvfs $shod]
324 forcedelete $shdo ; # Leave $shod for next test.
325 set ::result [join $res " | "]
329 set shdo "sh_app1.sql"
330 set shod "sh_app1.adb" ; # Same as test 4.2, reusing ADB.
332 set ofd [open $shdo w]
334 puts $ofd ".ar -u $shdo"
335 puts $ofd "select count(*) from sqlar where name = '$shdo';"
337 puts $ofd "insert into sqlar values (1);"
338 puts $ofd "select count(*) from sqlar;"
342 set res [catchcmd "-append -batch -init $shdo $shod" ""]
343 sqlite3 adb "file:$shod?mode=rw$::vf" -uri 1
345 SELECT count(*) as n FROM sqlar
348 forcedelete $shdo $shod;
349 set ::result [join $res " | "]
353 set fake "faketiny.sdb"
355 set ofd [open $fake wb]
356 puts -nonewline $ofd "SQLite format 3"
357 puts -nonewline $ofd [binary format "c" 0]
358 puts -nonewline $ofd "Start-Of-SQLite3-"
359 puts -nonewline $ofd [binary format "W" 0]
361 if {[catch {sqlite3 adb "file:$fake?mode=rw$::vf" -uri 1}]} {
362 set res "Open failed."
365 set res "Opened when should not."
372 set fake "faketiny.sdb"
374 set ofd [open $fake wb]
375 set fakeAppendee "Dog ate my homework.\n"
376 puts -nonewline $ofd $fakeAppendee
377 puts -nonewline $ofd "SQLite format 3"
378 puts -nonewline $ofd [binary format "c" 0]
379 puts -nonewline $ofd "Start-Of-SQLite3-"
380 puts -nonewline $ofd [binary format "W" [string length $fakeAppendee]]
382 if {[catch {sqlite3 adb "file:$fake?mode=rw$::vf" -uri 1}]} {
383 set res "Open failed."
386 set res "Opened when should not."
392 forcedelete $::fa $::fza
394 unset -nocomplain ::fa ::fza ::tlo ::result ::randints ::nrint ::cliDoesAr