1# 2017 December 9 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 15set testprefix zipfile 16 17ifcapable !vtab { 18 finish_test; return 19} 20if {[catch {load_static_extension db zipfile} error]} { 21 puts "Skipping zipfile tests, hit load error: $error" 22 finish_test; return 23} 24 25proc readfile {f} { 26 set fd [open $f] 27 fconfigure $fd -translation binary -encoding binary 28 set data [read $fd] 29 close $fd 30 set data 31} 32 33if {$::tcl_platform(platform)=="unix" && [catch {exec unzip}]==0} { 34 set ::UNZIP 1 35 load_static_extension db fileio 36 proc do_unzip {file} { 37 forcedelete test_unzip 38 file mkdir test_unzip 39 exec unzip -d test_unzip $file 40 41 set res [db eval { 42 SELECT replace(name,'test_unzip/',''),mode,mtime,data 43 FROM fsdir('test_unzip') 44 WHERE name!='test_unzip' 45 ORDER BY name 46 }] 47 set res 48 } 49} 50 51# Argument $file is the name of a zip archive on disk. This function 52# executes test cases to check that the results of each of the following 53# are the same: 54# 55# SELECT * FROM zipfile($file) 56# SELECT * FROM zipfile( readfile($file) ) 57# SELECT * FROM zipfile( 58# (SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file)) 59# ) 60# 61proc do_zipfile_blob_test {tn file} { 62 63 db func r readfile 64 set q1 {SELECT name,mode,mtime,method,quote(data) FROM zipfile($file)} 65 set q2 {SELECT name,mode,mtime,method,quote(data) FROM zipfile( r($file) )} 66 set q3 {SELECT name,mode,mtime,method,quote(data) FROM zipfile( 67 ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) 68 )} 69 70 71 set r1 [db eval $q1] 72 set r2 [db eval $q2] 73 set r3 [db eval $q3] 74 #puts $r1 75 #puts $r2 76 #puts $r3 77 78 uplevel [list do_test $tn.1 [list set {} $r2] $r1] 79 uplevel [list do_test $tn.2 [list set {} $r3] $r1] 80} 81 82# Argument $file is a zip file on disk. This command runs tests to: 83# 84# 1. Unpack the archive with unix command [unzip] and compare the 85# results to reading the same archive using the zipfile() table 86# valued function. 87# 88# 2. Creates a new archive with the same contents using the zipfile() 89# aggregate function as follows: 90# 91# SELECT writefile('test_unzip.zip', 92# ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) 93# ); 94# 95# Then tests that unpacking the new archive using [unzip] produces 96# the same results as in (1). 97# 98proc do_unzip_test {tn file} { 99 if {[info vars ::UNZIP]==""} { return } 100 db func sss strip_slash 101 102 db eval { 103 SELECT writefile('test_unzip.zip', 104 ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) 105 ); 106 } 107 108 set r1 [db eval { 109 SELECT sss(name),mode,mtime,data FROM zipfile($file) ORDER BY name 110 }] 111 set r2 [do_unzip $file] 112 set r3 [do_unzip test_unzip.zip] 113 114 uplevel [list do_test $tn.1 [list set {} $r2] $r1] 115 uplevel [list do_test $tn.2 [list set {} $r3] $r1] 116} 117proc strip_slash {in} { regsub {/$} $in {} } 118 119proc do_zip_tests {tn file} { 120 uplevel do_zipfile_blob_test $tn.1 $file 121 uplevel do_unzip_test $tn.2 $file 122} 123 124forcedelete test.zip 125do_execsql_test 1.0 { 126 CREATE VIRTUAL TABLE temp.zz USING zipfile('test.zip'); 127 PRAGMA table_info(zz); 128} { 129 0 name {} 1 {} 1 130 1 mode {} 0 {} 0 131 2 mtime {} 0 {} 0 132 3 sz {} 0 {} 0 133 4 rawdata {} 0 {} 0 134 5 data {} 0 {} 0 135 6 method {} 0 {} 0 136} 137 138do_catchsql_test 1.1.0.1 { 139 INSERT INTO zz(name, mode, mtime, sz, rawdata, method) 140 VALUES('f.txt', '-rw-r--r--', 1000000000, 5, 'abcde', 0); 141} {1 {constraint failed}} 142do_catchsql_test 1.1.0.1 { 143 INSERT INTO zz(name, mtime, sz, rawdata, method) 144 VALUES('g.txt', 1000000002, 5, '12345', 0); 145} {1 {constraint failed}} 146 147do_execsql_test 1.1.1 { 148 INSERT INTO zz(name, mode, mtime, data, method) 149 VALUES('f.txt', '-rw-r--r--', 1000000000, 'abcde', 0); 150} 151do_execsql_test 1.1.2 { 152 INSERT INTO zz(name, mode, mtime, data, method) 153 VALUES('g.txt', NULL, 1000000002, '12345', 0); 154} 155 156do_execsql_test 1.2 { 157 SELECT name, mtime, data FROM zipfile('test.zip') 158} { 159 f.txt 1000000000 abcde 160 g.txt 1000000002 12345 161} 162do_zip_tests 1.2a test.zip 163 164do_execsql_test 1.3 { 165 INSERT INTO zz(name, mode, mtime, data) VALUES('h.txt', 166 '-rw-r--r--', 1000000004, 'aaaaaaaaaabbbbbbbbbb' 167 ); 168} 169do_zip_tests 1.3a test.zip 170 171do_execsql_test 1.4 { 172 SELECT name, mtime, data, method FROM zipfile('test.zip'); 173} { 174 f.txt 1000000000 abcde 0 175 g.txt 1000000002 12345 0 176 h.txt 1000000004 aaaaaaaaaabbbbbbbbbb 8 177} 178 179ifcapable json1 { 180 do_execsql_test 1.4.1 { 181 SELECT name, json_extract( zipfile_cds(z) , '$.crc32')!=0 182 FROM zipfile('test.zip'); 183 } { 184 f.txt 1 185 g.txt 1 186 h.txt 1 187 } 188} 189 190do_execsql_test 1.5.1 { 191 BEGIN; 192 INSERT INTO zz(name, mode, mtime, data, method) 193 VALUES('i.txt', '-rw-r--r--', 1000000006, 'zxcvb', 0); 194 SELECT name FROM zz; 195 COMMIT; 196} {f.txt g.txt h.txt i.txt} 197do_execsql_test 1.5.2 { 198 SELECT name FROM zz; 199} {f.txt g.txt h.txt i.txt} 200do_execsql_test 1.5.3 { 201 SELECT data FROM zz WHERE name='i.txt'; 202} {zxcvb} 203 204do_execsql_test 1.6.0 { 205 DELETE FROM zz WHERE name='g.txt'; 206 SELECT name FROM zz; 207} {f.txt h.txt i.txt} 208 209do_execsql_test 1.6.1 { 210 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 211} { 212 f.txt 33188 1000000000 abcde 0 213 h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8 214 i.txt 33188 1000000006 zxcvb 0 215} 216do_zip_tests 1.6.1a test.zip 217 218do_execsql_test 1.6.2 { 219 UPDATE zz SET mtime=4 WHERE name='i.txt'; 220 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 221} { 222 f.txt 33188 1000000000 abcde 0 223 h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8 224 i.txt 33188 4 zxcvb 0 225} 226 227do_execsql_test 1.6.3 { 228 UPDATE zz SET mode='-rw-r--r-x' WHERE name='h.txt'; 229 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 230} { 231 f.txt 33188 1000000000 abcde 0 232 h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8 233 i.txt 33188 4 zxcvb 0 234} 235do_zip_tests 1.6.3a test.zip 236 237do_execsql_test 1.6.4 { 238 UPDATE zz SET name = 'blue.txt' WHERE name='f.txt'; 239 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 240} { 241 blue.txt 33188 1000000000 abcde 0 242 h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8 243 i.txt 33188 4 zxcvb 0 244} 245do_zip_tests 1.6.4a test.zip 246 247do_execsql_test 1.6.5 { 248 UPDATE zz SET data = 'edcba' WHERE name='blue.txt'; 249 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 250} { 251 blue.txt 33188 1000000000 edcba 0 252 h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8 253 i.txt 33188 4 zxcvb 0 254} 255 256do_execsql_test 1.6.6 { 257 UPDATE zz SET mode=NULL, data = NULL WHERE name='blue.txt'; 258 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 259} { 260 blue.txt/ 16877 1000000000 {} 0 261 h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8 262 i.txt 33188 4 zxcvb 0 263} 264 265do_catchsql_test 1.6.7 { 266 UPDATE zz SET data=NULL WHERE name='i.txt' 267} {1 {constraint failed}} 268do_execsql_test 1.6.8 { 269 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 270} { 271 blue.txt/ 16877 1000000000 {} 0 272 h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8 273 i.txt 33188 4 zxcvb 0 274} 275 276#------------------------------------------------------------------------- 277db close 278forcedelete test.zip 279reset_db 280load_static_extension db fileio 281load_static_extension db zipfile 282do_execsql_test 2.1 { 283 CREATE VIRTUAL TABLE zzz USING zipfile('test.zip'); 284 INSERT INTO zzz(name, mode) VALUES('dirname', 'drwxr-xr-x'); 285 SELECT name, mode, data FROM zzz; 286} {dirname/ 16877 {}} 287do_execsql_test 2.2 { 288 INSERT INTO zzz(name, data) VALUES('dirname2', NULL); 289 INSERT INTO zzz(name, data) VALUES('dirname2/file1.txt', 'abcdefghijklmnop'); 290 SELECT name, mode, data FROM zzz; 291} { 292 dirname/ 16877 {} 293 dirname2/ 16877 {} 294 dirname2/file1.txt 33188 abcdefghijklmnop 295} 296 297do_catchsql_test 2.3 { 298 UPDATE zzz SET name = 'dirname3' WHERE name = 'dirname/'; 299} {0 {}} 300do_execsql_test 2.4 { 301 SELECT name, mode, data FROM zzz; 302} { 303 dirname3/ 16877 {} 304 dirname2/ 16877 {} 305 dirname2/file1.txt 33188 abcdefghijklmnop 306} 307do_zip_tests 2.4a test.zip 308 309# If on unix, check that the [unzip] utility can unpack our archive. 310# 311if {$::tcl_platform(platform)=="unix"} { 312 do_test 2.5.1 { 313 forcedelete dirname 314 forcedelete dirname2 315 set rc [catch { exec unzip test.zip > /dev/null } msg] 316 list $rc $msg 317 } {0 {}} 318 do_test 2.5.2 { file isdir dirname3 } 1 319 do_test 2.5.3 { file isdir dirname2 } 1 320 do_test 2.5.4 { file isdir dirname2/file1.txt } 0 321 do_test 2.5.5 { 322 set fd [open dirname2/file1.txt] 323 set data [read $fd] 324 close $fd 325 set data 326 } {abcdefghijklmnop} 327} 328 329#------------------------------------------------------------------------- 330reset_db 331forcedelete test.zip 332load_static_extension db zipfile 333 334do_execsql_test 3.0 { 335 CREATE VIRTUAL TABLE temp.x1 USING zipfile('test.zip'); 336 INSERT INTO x1(name, data) VALUES('dir1/', NULL); 337 INSERT INTO x1(name, data) VALUES('file1', '1234'); 338 INSERT INTO x1(name, data) VALUES('dir1/file2', '5678'); 339} 340foreach {tn fname} { 341 1 dir1 342 2 file1 343 3 dir1/file2 344} { 345 do_catchsql_test 3.1.$tn.0 { 346 INSERT INTO x1(name, data) VALUES($fname, NULL); 347 } {1 {constraint failed}} 348 do_catchsql_test 3.1.$tn.1 { 349 INSERT INTO x1(name, data) VALUES($fname || '/', NULL); 350 } {1 {constraint failed}} 351 do_catchsql_test 3.1.$tn.2 { 352 INSERT INTO x1(name, data) VALUES($fname, 'abcd'); 353 } {1 {constraint failed}} 354} 355 356do_catchsql_test 3.2 { 357 SELECT rowid FROM x1 358} {1 {no such column: rowid}} 359 360#------------------------------------------------------------------------- 361# Test some error conditions. 362# 363do_catchsql_test 4.1 { 364 CREATE VIRTUAL TABLE yyy USING zipfile(); 365} {1 {zipfile constructor requires one argument}} 366do_catchsql_test 4.2 { 367 CREATE VIRTUAL TABLE yyy USING zipfile('test.zip', 'test.zip'); 368} {1 {zipfile constructor requires one argument}} 369 370 371 372finish_test 373 374