gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/avfs.test (about) 1 # 2021-03-06 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 # This file implements tests for the appendvfs extension. 13 # 14 # Tests performed: 15 # avfs-1.0. Test that an appendvfs DB can be added to an empty (ZLF) file. 16 # avfs-1.1. Test that the DB can be read with correct content upon reopen. 17 # avfs-1.2. Test that an appendvfs DB can be added to a simple text file. 18 # avfs-1.3. Test that the DB can be read with correct content upon reopen. 19 # avfs-1.4. Test that appended DB is aligned to default page boundary. 20 # avfs-2.1. Test that the simple text file retains its initial text. 21 # avfs-3.1. Test that the appendvfs can grow and shrink, remaining intact. 22 # avfs-3.2. Test that appendvfs is intact after grow/shrink/close/reopen. 23 # avfs-3.3. Test that appendvfs can grow by many pages and be written. 24 # avfs-3.4. Test that grown appendvfs can be reopened and appear intact. 25 # avfs-3.5. Test that much grown appendvfs can shrink and reopen intact. 26 # avfs-4.1. Test shell's ability to append to a non-appendvfs file. 27 # avfs-4.2. Test shell's ability to append to empty or nonexistent file. 28 # avfs-4.3. Test shell's ability to reopen and alter an appendvfs file. 29 # avfs-5.1. Test appendvfs refusal to open too-tiny DB appended onto ZLF. 30 # avfs-5.2. Test appendvfs refusal to open too-tiny DB appended on other. 31 # ... 32 # (more to come) 33 34 set testdir [file dirname $argv0] 35 source $testdir/tester.tcl 36 set ::testprefix avfs 37 38 # Do not attempt this test if SQLITE_OMIT_VIRTUALTABLE is defined. 39 # 40 ifcapable !vtab { 41 finish_test 42 return 43 } 44 45 set CLI [test_find_cli] 46 db close 47 # forcedelete test.db 48 49 load_static_extension db appendvfs 50 51 set ::fa avfs.adb 52 set ::fza avfs.sdb 53 forcedelete $::fa $::fza 54 set ::result {} 55 56 proc shellDoesAr {} { 57 set shdo "sh_app1.sql" 58 forcedelete $shdo 59 set fd [open $shdo w] 60 puts $fd ".help\n.q" 61 close $fd 62 set res [catchcmd "-batch -cmd \".read $shdo\""] 63 return [regexp {^.archive} [lindex $res 1]] 64 } 65 66 set ::vf "&vfs=apndvfs" 67 68 # Return file offset of appendvfs portion of a file, or {} if none such. 69 proc fosAvfs {fname} { 70 if {[file size $fname] < 25} { 71 return {} 72 } 73 if {[catch {set fd [open $fname rb]}]} { 74 return {} 75 } 76 seek $fd -25 end 77 set am [read $fd 17] 78 set ao [read $fd 8] 79 close $fd 80 if {$am ne "Start-Of-SQLite3-"} { 81 return {} 82 } 83 binary scan $ao "W" rvo 84 return $rvo 85 } 86 87 do_test 1.0 { 88 set results {} 89 set out [open $::fza wb] 90 close $out 91 sqlite3 adb "file:$::fza?mode=rwc$::vf" -uri 1 92 adb eval { 93 PRAGMA page_size=1024; 94 PRAGMA cache_size=10; 95 CREATE TABLE t1(a TEXT); 96 INSERT INTO t1 VALUES ('dog'),('cat'); 97 SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a); 98 } { lappend results $pets } 99 adb close 100 lappend results [fosAvfs $fza] 101 set ::result [join $results " | "] 102 } {cat,dog | 0} 103 104 do_test 1.1 { 105 set results {} 106 sqlite3 adb "file:$::fza?mode=rw$::vf" -uri 1 107 adb eval { 108 SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a DESC); 109 } { lappend results $pets } 110 adb close 111 set ::result [join $results " | "] 112 } {dog,cat} 113 114 do_test 1.2 { 115 set results {} 116 set out [open $::fa wb] 117 set ::tlo { "Just some text," "and more text," "ending at 3 lines." } 118 puts $out [join $::tlo "\n"] 119 close $out 120 set adbSz [file size $::fa] 121 sqlite3 adb "file:$::fa?mode=rwc$::vf" -uri 1 122 adb eval { 123 PRAGMA auto_vacuum = 0; 124 PRAGMA page_size=512; 125 PRAGMA cache_size=0; 126 CREATE TABLE t1(a TEXT); 127 INSERT INTO t1 VALUES ('dog'),('cat'),('pig'); 128 SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a); 129 } { lappend results $pets } 130 adb close 131 set adaSz [file size $::fa] 132 lappend results "Bytes before/after $adbSz/$adaSz" 133 set ::result [join $results " | "] 134 } {cat,dog,pig | Bytes before/after 50/5145} 135 136 do_test 1.3 { 137 set results {} 138 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1 139 adb eval { 140 SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a DESC); 141 } { lappend results $pets } 142 adb close 143 set ::result [join $results " | "] 144 } {pig,dog,cat} 145 146 do_test 1.4 { 147 set ::result [fosAvfs $fa] 148 } {4096} 149 150 do_test 2.1 { 151 set in [open $::fa r] 152 set tli {} 153 for {set i [llength $::tlo]} {$i > 0} {incr i -1} { 154 lappend tli [gets $in] 155 } 156 close $in 157 if { [join $tli ":"] ne [join $::tlo ":"] } { 158 set ::result "Appendee changed." 159 } else { 160 set ::result "Appendee intact." 161 } 162 } {Appendee intact.} 163 164 # Set of repeatable random integers for a couple tests. 165 set ::nrint 50000 166 proc rint {v} { 167 return [::tcl::mathfunc::int [expr $v * 100000]] 168 } 169 array set ::randints [list 0 [rint [::tcl::mathfunc::srand 0]]] 170 for {set i 1} {$i < $::nrint} {incr i} { 171 set ::randints($i) [rint [::tcl::mathfunc::rand]] 172 } 173 174 do_test 3.1 { 175 set results {} 176 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1 177 adb eval { 178 DROP TABLE t1; 179 PRAGMA cache_size=10; 180 CREATE TABLE ri (i INTEGER); 181 BEGIN; 182 } 183 for {set i 0} {$i < $::nrint} {incr i} { 184 set r $::randints($i) 185 set s $::randints([incr i]) 186 set t $::randints([incr i]) 187 set u $::randints([incr i]) 188 set v $::randints([incr i]) 189 adb eval { 190 INSERT INTO ri VALUES ($r),($s),($t),($u),($v) 191 } 192 } 193 adb eval { 194 COMMIT; 195 SELECT integrity_check as ic FROM pragma_integrity_check(); 196 } { lappend results $ic } 197 set adbSz [file size $::fa] 198 set qr {} 199 adb eval { 200 SELECT count(*) as ic FROM ri; 201 DELETE FROM ri WHERE (i % 50) <> 25; 202 SELECT integrity_check as ic FROM pragma_integrity_check(); 203 VACUUM; 204 SELECT integrity_check as ic FROM pragma_integrity_check(); 205 SELECT count(*) as ic FROM ri; 206 } { lappend qr $ic } 207 adb close 208 set adaSz [file size $::fa] 209 set adba [expr ($adbSz + 0.1)/$adaSz] 210 # lappend results $adba 211 set results [concat $results [lrange $qr 0 2]] 212 lappend results [expr {$adba > 10.0}] 213 set ::result [join $results " | "] 214 } "ok | $::nrint | ok | ok | 1" 215 216 do_test 3.2 { 217 set results {} 218 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1 219 adb eval { 220 SELECT integrity_check as ic FROM pragma_integrity_check(); 221 } { lappend results $ic } 222 adb close 223 set ::result [join $results " | "] 224 } {ok} 225 226 # avfs-3.3. Test that appendvfs can grow by many pages and be written. 227 do_test 3.3 { 228 set results {} 229 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1 230 set npages 300 231 adb eval { BEGIN } 232 while {$npages > 0} { 233 adb eval { INSERT INTO ri VALUES (randomblob(1500)) } 234 incr npages -1 235 } 236 adb eval { COMMIT } 237 adb eval { 238 SELECT integrity_check as ic FROM pragma_integrity_check(); 239 } { lappend results $ic } 240 adb close 241 set adaSzr [expr [file size $::fa] / 300.0 / 1500 ] 242 set okSzr [expr $adaSzr > 1.0 && $adaSzr < 1.3 ] 243 lappend results $okSzr 244 set ::result [join $results " | "] 245 } {ok | 1} 246 247 # avfs-3.4. Test that grown appendvfs can be reopened and appear intact. 248 do_test 3.4 { 249 set results {} 250 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1 251 adb eval { 252 SELECT integrity_check as ic FROM pragma_integrity_check(); 253 } { lappend results $ic } 254 adb close 255 set ::result $ic 256 } {ok} 257 258 # avfs-3.5. Test that much grown appendvfs can shrink and reopen intact. 259 do_test 3.5 { 260 set results {} 261 set adbsz [file size $::fa] 262 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1 263 adb eval { 264 DELETE FROM ri WHERE rowid % 8 <> 0; 265 SELECT integrity_check as ic FROM pragma_integrity_check(); 266 VACUUM; 267 SELECT integrity_check as ic FROM pragma_integrity_check(); 268 } { lappend results $ic } 269 adb close 270 set adasz [file size $::fa] 271 lappend results [expr {$adbsz/$adasz > 5}] 272 sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1 273 adb eval { 274 SELECT integrity_check as ic FROM pragma_integrity_check(); 275 } { lappend results $ic } 276 adb close 277 set ::result [join $results " | "] 278 } {ok | ok | 1 | ok} 279 280 set ::cliDoesAr [shellDoesAr] 281 282 do_test 4.1 { 283 set shdo "sh_app1.sql" 284 set shod "sh_app1.adb" 285 forcedelete $shdo $shod 286 set ofd [open $shdo w] 287 if {$::cliDoesAr} { 288 puts $ofd ".ar -c" 289 } else { 290 puts $ofd "pragma page_size=512;" 291 puts $ofd "create table sqlar (a);" 292 } 293 puts $ofd ".tables" 294 puts $ofd ".q" 295 close $ofd 296 set ofd [open $shod wb] 297 puts $ofd "Some text." 298 close $ofd 299 set res [catchcmd "-append -batch -init $shdo $shod" ""] 300 lappend res [fosAvfs $shod] 301 forcedelete $shdo $shod 302 set ::result [join $res " | "] 303 } {0 | sqlar | 4096} 304 305 do_test 4.2 { 306 set shdo "sh_app1.sql" 307 set shod "sh_app1.adb" 308 forcedelete $shdo $shod 309 set ofd [open $shdo w] 310 if {$::cliDoesAr} { 311 puts $ofd ".ar -c" 312 } else { 313 puts $ofd "pragma page_size=512;" 314 puts $ofd "create table sqlar (a);" 315 } 316 puts $ofd ".tables" 317 puts $ofd ".q" 318 close $ofd 319 set ofd [open $shod wb] 320 close $ofd 321 set res [catchcmd "-append -batch -init $shdo $shod" ""] 322 lappend res [fosAvfs $shod] 323 forcedelete $shdo ; # Leave $shod for next test. 324 set ::result [join $res " | "] 325 } {0 | sqlar | 0} 326 327 do_test 4.3 { 328 set shdo "sh_app1.sql" 329 set shod "sh_app1.adb" ; # Same as test 4.2, reusing ADB. 330 forcedelete $shdo 331 set ofd [open $shdo w] 332 if {$::cliDoesAr} { 333 puts $ofd ".ar -u $shdo" 334 puts $ofd "select count(*) from sqlar where name = '$shdo';" 335 } else { 336 puts $ofd "insert into sqlar values (1);" 337 puts $ofd "select count(*) from sqlar;" 338 } 339 puts $ofd ".q" 340 close $ofd 341 set res [catchcmd "-append -batch -init $shdo $shod" ""] 342 sqlite3 adb "file:$shod?mode=rw$::vf" -uri 1 343 adb eval { 344 SELECT count(*) as n FROM sqlar 345 } { lappend res $n } 346 adb close 347 forcedelete $shdo $shod; 348 set ::result [join $res " | "] 349 } {0 | 1 | 1} 350 351 do_test 5.1 { 352 set fake "faketiny.sdb" 353 forcedelete $fake 354 set ofd [open $fake wb] 355 puts -nonewline $ofd "SQLite format 3" 356 puts -nonewline $ofd [binary format "c" 0] 357 puts -nonewline $ofd "Start-Of-SQLite3-" 358 puts -nonewline $ofd [binary format "W" 0] 359 close $ofd 360 if {[catch {sqlite3 adb "file:$fake?mode=rw$::vf" -uri 1}]} { 361 set res "Open failed." 362 } else { 363 adb close 364 set res "Opened when should not." 365 } 366 forcedelete $fake 367 set ::result $res 368 } {Open failed.} 369 370 do_test 5.2 { 371 set fake "faketiny.sdb" 372 forcedelete $fake 373 set ofd [open $fake wb] 374 set fakeAppendee "Dog ate my homework.\n" 375 puts -nonewline $ofd $fakeAppendee 376 puts -nonewline $ofd "SQLite format 3" 377 puts -nonewline $ofd [binary format "c" 0] 378 puts -nonewline $ofd "Start-Of-SQLite3-" 379 puts -nonewline $ofd [binary format "W" [string length $fakeAppendee]] 380 close $ofd 381 if {[catch {sqlite3 adb "file:$fake?mode=rw$::vf" -uri 1}]} { 382 set res "Open failed." 383 } else { 384 adb close 385 set res "Opened when should not." 386 } 387 forcedelete $fake 388 set ::result $res 389 } {Open failed.} 390 391 forcedelete $::fa $::fza 392 393 unset -nocomplain ::fa ::fza ::tlo ::result ::randints ::nrint ::cliDoesAr 394 395 finish_test