diff options
Diffstat (limited to 'test/zipfile.test')
-rw-r--r-- | test/zipfile.test | 887 |
1 files changed, 887 insertions, 0 deletions
diff --git a/test/zipfile.test b/test/zipfile.test new file mode 100644 index 0000000..4d09e08 --- /dev/null +++ b/test/zipfile.test @@ -0,0 +1,887 @@ +# 2017 December 9 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +package require Tcl 8.6 + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix zipfile + +ifcapable !vtab { + finish_test; return +} +if {[catch {load_static_extension db zipfile} error]} { + puts "Skipping zipfile tests, hit load error: $error" + finish_test; return +} +if {[catch {load_static_extension db fileio} error]} { + puts "Skipping zipfile tests, hit load error: $error" + finish_test; return +} + +proc readfile {f} { + set fd [open $f] + fconfigure $fd -translation binary -encoding binary + set data [read $fd] + close $fd + set data +} + +unset -nocomplain ::UNZIP + +if {[catch {exec unzip} msg]==0 && \ + [regexp -line {^UnZip \d+\.\d+ .*? Info-ZIP\.} $msg]} { + set ::UNZIP unzip + proc fix_stat_mode {name mode} { + if {$::tcl_platform(platform)=="windows"} { + # + # NOTE: Set or unset the write bits of the file permissions + # based on the read-only attribute because the Win32 + # version of UnZip does this. + # + set writebits 0x12; # 0o22 + set result $mode + if {[file attributes $name -readonly]} { + set result [expr {$result | $writebits}] + } else { + set result [expr {$result & ~$writebits}] + } + return $result + } else { + return $mode + } + } + proc do_unzip {file} { + forcedelete test_unzip + file mkdir test_unzip + exec $::UNZIP -d test_unzip $file + + db func modefix fix_stat_mode + + set res [db eval { + SELECT replace(name,'test_unzip/',''),modefix(name,mode),mtime,data + FROM fsdir('test_unzip') + WHERE name!='test_unzip' + ORDER BY name + }] + set res + } +} + + +# The argument is a blob (not a hex string) containing a zip archive. +# This proc removes the extended timestamp fields from the archive +# and returns the result. +# +proc remove_timestamps {blob} { + set hex [binary encode hex $blob] + set hex [string map {55540500 00000500} $hex] + binary decode hex $hex +} + + +# Argument $file is the name of a zip archive on disk. This function +# executes test cases to check that the results of each of the following +# are the same: +# +# SELECT * FROM zipfile($file) +# SELECT * FROM zipfile( readfile($file) ) +# SELECT * FROM zipfile( +# (SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file)) +# ) +# +proc do_zipfile_blob_test {tn file} { + + db func r readfile + set q1 {SELECT name,mode,mtime,method,quote(data) FROM zipfile($file)} + set q2 {SELECT name,mode,mtime,method,quote(data) FROM zipfile( r($file) )} + set q3 {SELECT name,mode,mtime,method,quote(data) FROM zipfile( + ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) + )} + + + set r1 [db eval $q1] + set r2 [db eval $q2] + set r3 [db eval $q3] + #puts $r1 + #puts $r2 + #puts $r3 + + uplevel [list do_test $tn.1 [list set {} $r2] $r1] + uplevel [list do_test $tn.2 [list set {} $r3] $r1] +} + +# Argument $file is a zip file on disk. This command runs tests to: +# +# 1. Unpack the archive with unix command [unzip] and compare the +# results to reading the same archive using the zipfile() table +# valued function. +# +# 2. Creates a new archive with the same contents using the zipfile() +# aggregate function as follows: +# +# SELECT writefile('test_unzip.zip', +# ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) +# ); +# +# Then tests that unpacking the new archive using [unzip] produces +# the same results as in (1). +# +proc do_unzip_test {tn file} { + db func sss strip_slash + + db eval { + SELECT writefile('test_unzip.zip', + ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) + ); + } + + set r1 [db eval { + SELECT sss(name),mode,mtime,data FROM zipfile($file) ORDER BY name + }] + set r2 [do_unzip $file] + set r3 [do_unzip test_unzip.zip] + + uplevel [list do_test $tn.1 [list set {} $r2] $r1] + uplevel [list do_test $tn.2 [list set {} $r3] $r1] +} +proc strip_slash {in} { regsub {/$} $in {} } + +proc do_zip_tests {tn file} { + uplevel do_zipfile_blob_test $tn.1 $file + if {[info exists ::UNZIP]} { + uplevel do_unzip_test $tn.2 $file + } +} + +forcedelete test.zip +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE temp.zz USING zipfile('test.zip'); + PRAGMA table_info(zz); +} { + 0 name {} 1 {} 1 + 1 mode {} 0 {} 0 + 2 mtime {} 0 {} 0 + 3 sz {} 0 {} 0 + 4 rawdata {} 0 {} 0 + 5 data {} 0 {} 0 + 6 method {} 0 {} 0 +} + +do_catchsql_test 1.1.0.1 { + INSERT INTO zz(name, mode, mtime, sz, rawdata, method) + VALUES('f.txt', '-rw-r--r--', 1000000000, 5, 'abcde', 0); +} {1 {rawdata must be NULL}} +do_catchsql_test 1.1.0.2 { + INSERT INTO zz(name, mtime, sz, data, method) + VALUES('g.txt', 1000000002, 5, '12345', 0); +} {1 {sz must be NULL}} +do_catchsql_test 1.1.0.3 { + INSERT INTO zz(name, mtime, rawdata, method) + VALUES('g.txt', 1000000002, '12345', 0); +} {1 {rawdata must be NULL}} +do_catchsql_test 1.1.0.4 { + INSERT INTO zz(name, data, method) + VALUES('g.txt', '12345', 7); +} {1 {unknown compression method: 7}} + +do_execsql_test 1.1.1 { + INSERT INTO zz(name, mode, mtime, data, method) + VALUES('f.txt', '-rw-r--r--', 1000000000, 'abcde', 0); +} +do_execsql_test 1.1.2 { + INSERT INTO zz(name, mode, mtime, data, method) + VALUES('g.txt', NULL, 1000000002, '12345', 0); +} + +do_execsql_test 1.2 { + SELECT name, mtime, data FROM zipfile('test.zip') +} { + f.txt 1000000000 abcde + g.txt 1000000002 12345 +} +do_zip_tests 1.2a test.zip + +do_execsql_test 1.3 { + INSERT INTO zz(name, mode, mtime, data) VALUES('h.txt', + '-rw-r--r--', 1000000004, 'aaaaaaaaaabbbbbbbbbb' + ); +} +do_zip_tests 1.3a test.zip + +do_execsql_test 1.4 { + SELECT name, mtime, data, method FROM zipfile('test.zip'); +} { + f.txt 1000000000 abcde 0 + g.txt 1000000002 12345 0 + h.txt 1000000004 aaaaaaaaaabbbbbbbbbb 8 +} + +ifcapable json1 { + do_execsql_test 1.4.1 { + SELECT name, json_extract( zipfile_cds(z) , '$.crc32')!=0 + FROM zipfile('test.zip'); + } { + f.txt 1 + g.txt 1 + h.txt 1 + } +} +do_catchsql_test 1.4.2 { + SELECT zipfile_cds(mode) FROM zipfile('test.zip'); +} {0 {{} {} {}}} + +do_execsql_test 1.5.1 { + BEGIN; + INSERT INTO zz(name, mode, mtime, data, method) + VALUES('i.txt', '-rw-r--r--', 1000000006, 'zxcvb', 0); + SELECT name FROM zz; + COMMIT; +} {f.txt g.txt h.txt i.txt} +do_execsql_test 1.5.2 { + SELECT name FROM zz; +} {f.txt g.txt h.txt i.txt} +do_execsql_test 1.5.3 { + SELECT data FROM zz WHERE name='i.txt'; +} {zxcvb} + +do_execsql_test 1.6.0 { + DELETE FROM zz WHERE name='g.txt'; + SELECT name FROM zz; +} {f.txt h.txt i.txt} + +do_execsql_test 1.6.1 { + SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); +} { + f.txt 33188 1000000000 abcde 0 + h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8 + i.txt 33188 1000000006 zxcvb 0 +} +do_zip_tests 1.6.1a test.zip + +do_execsql_test 1.6.2 { + UPDATE zz SET mtime=4 WHERE name='i.txt'; + SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); +} { + f.txt 33188 1000000000 abcde 0 + h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8 + i.txt 33188 4 zxcvb 0 +} + +if {$::tcl_platform(platform)=="unix"} { + set modes -rw-r--r-x + set perms 33189 +} else { + set modes -rw-r--r--; # no execute bits on Win32 + set perms 33188 +} + +do_execsql_test 1.6.3 { + UPDATE zz SET mode=$modes WHERE name='h.txt'; + SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); +} [string map [list %perms% $perms] { + f.txt 33188 1000000000 abcde 0 + h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 + i.txt 33188 4 zxcvb 0 +}] +do_zip_tests 1.6.3a test.zip + +do_execsql_test 1.6.4 { + UPDATE zz SET name = 'blue.txt' WHERE name='f.txt'; + SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); +} [string map [list %perms% $perms] { + blue.txt 33188 1000000000 abcde 0 + h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 + i.txt 33188 4 zxcvb 0 +}] +do_zip_tests 1.6.4a test.zip + +do_execsql_test 1.6.5 { + UPDATE zz SET data = 'edcba' WHERE name='blue.txt'; + SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); +} [string map [list %perms% $perms] { + blue.txt 33188 1000000000 edcba 0 + h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 + i.txt 33188 4 zxcvb 0 +}] + +do_execsql_test 1.6.6 { + UPDATE zz SET mode=NULL, data = NULL WHERE name='blue.txt'; + SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); +} [string map [list %perms% $perms] { + blue.txt/ 16877 1000000000 {} 0 + h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 + i.txt 33188 4 zxcvb 0 +}] + +do_catchsql_test 1.6.7 { + UPDATE zz SET data=NULL WHERE name='i.txt' +} {1 {zipfile: mode does not match data}} +do_execsql_test 1.6.8 { + SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); +} [string map [list %perms% $perms] { + blue.txt/ 16877 1000000000 {} 0 + h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 + i.txt 33188 4 zxcvb 0 +}] + +do_execsql_test 1.6.9 { + UPDATE zz SET data = '' WHERE name='i.txt'; + SELECT name,mode,mtime,data,method from zipfile('test.zip'); +} [string map [list %perms% $perms] { + blue.txt/ 16877 1000000000 {} 0 + h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 + i.txt 33188 4 {} 0 +}] + +do_execsql_test 1.6.10 { + SELECT a.name, a.data + FROM zz AS a, zz AS b + WHERE a.name=+b.name AND +a.mode=b.mode +} { + blue.txt/ {} + h.txt aaaaaaaaaabbbbbbbbbb + i.txt {} +} + +do_execsql_test 1.6.11 { + SELECT name, data FROM zz WHERE name LIKE '%txt' +} { + h.txt aaaaaaaaaabbbbbbbbbb + i.txt {} +} + +do_execsql_test 1.7 { + DELETE FROM zz; + SELECT * FROM zz; +} {} + +#------------------------------------------------------------------------- +db close +forcedelete test.zip +reset_db +load_static_extension db fileio +load_static_extension db zipfile +do_execsql_test 2.1 { + CREATE VIRTUAL TABLE zzz USING zipfile('test.zip'); + INSERT INTO zzz(name, mode) VALUES('dirname', 'drwxr-xr-x'); + SELECT name, mode, data FROM zzz; +} {dirname/ 16877 {}} +do_execsql_test 2.2 { + INSERT INTO zzz(name, data) VALUES('dirname2', NULL); + INSERT INTO zzz(name, data) VALUES('dirname2/file1.txt', 'abcdefghijklmnop'); + SELECT name, mode, data FROM zzz; +} { + dirname/ 16877 {} + dirname2/ 16877 {} + dirname2/file1.txt 33188 abcdefghijklmnop +} + +do_catchsql_test 2.3 { + UPDATE zzz SET name = 'dirname3' WHERE name = 'dirname/'; +} {0 {}} +do_execsql_test 2.4 { + SELECT name, mode, data FROM zzz; +} { + dirname3/ 16877 {} + dirname2/ 16877 {} + dirname2/file1.txt 33188 abcdefghijklmnop +} +do_zip_tests 2.4a test.zip + +# Check that the [unzip] utility can unpack our archive. +# +if {[info exists ::UNZIP]} { + do_test 2.5.1 { + forcedelete dirname + forcedelete dirname2 + if {$::tcl_platform(platform)=="unix"} { + set null /dev/null + } else { + set null NUL + } + set rc [catch { exec $::UNZIP test.zip > $null } msg] + list $rc $msg + } {0 {}} + do_test 2.5.2 { file isdir dirname3 } 1 + do_test 2.5.3 { file isdir dirname2 } 1 + do_test 2.5.4 { file isdir dirname2/file1.txt } 0 + do_test 2.5.5 { + set fd [open dirname2/file1.txt] + set data [read $fd] + close $fd + set data + } {abcdefghijklmnop} +} + +#------------------------------------------------------------------------- +reset_db +forcedelete test.zip +load_static_extension db zipfile +load_static_extension db fileio + +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE temp.x1 USING zipfile('test.zip'); + INSERT INTO x1(name, data) VALUES('dir1/', NULL); + INSERT INTO x1(name, data) VALUES('file1', '1234'); + INSERT INTO x1(name, data) VALUES('dir1/file2', '5678'); +} +foreach {tn fname} { + 1 dir1 + 2 file1 + 3 dir1/file2 +} { + do_catchsql_test 3.1.$tn.0 { + INSERT INTO x1(name, data) VALUES($fname, NULL); + } [list 1 "duplicate name: \"$fname/\""] + do_catchsql_test 3.1.$tn.1 { + INSERT INTO x1(name, data) VALUES($fname || '/', NULL); + } [list 1 "duplicate name: \"$fname/\""] + do_catchsql_test 3.1.$tn.2 { + INSERT INTO x1(name, data) VALUES($fname, 'abcd'); + } [list 1 "duplicate name: \"$fname\""] +} + +do_catchsql_test 3.2 { + SELECT rowid FROM x1 +} {1 {no such column: rowid}} + +#------------------------------------------------------------------------- +# Test some error conditions. +# +do_catchsql_test 4.1 { + CREATE VIRTUAL TABLE yyy USING zipfile(); +} {1 {zipfile constructor requires one argument}} +do_catchsql_test 4.2 { + CREATE VIRTUAL TABLE yyy USING zipfile('test.zip', 'test.zip'); +} {1 {zipfile constructor requires one argument}} + +do_catchsql_test 4.3 { + SELECT * FROM zipfile() +} {1 {zipfile() function requires an argument}} + +do_catchsql_test 4.4 { + SELECT * FROM zipfile('/path/that/does/not/exist') +} {1 {cannot open file: /path/that/does/not/exist}} + +foreach {tn mode} { + 1 abcd + 2 brwxrwxrwx + 3 lrwxrrxrwx +} { + do_catchsql_test 4.5.$tn { + WITH m(m) AS ( SELECT $mode) + SELECT zipfile('a.txt', m, 1000, 'xyz') FROM m + } [list 1 "zipfile: parse error in mode: $mode"] +} + +do_catchsql_test 4.6 { + WITH c(name,data) AS ( SELECT 'a.txt', 'abc') + SELECT zipfile(name) FROM c +} {1 {wrong number of arguments to function zipfile()}} + +do_catchsql_test 4.7 { + WITH c(name,data) AS ( + SELECT 'a.txt', 'abc' UNION ALL + SELECT NULL, 'def' + ) + SELECT zipfile(name,data) FROM c +} {1 {first argument to zipfile() must be non-NULL}} + +do_catchsql_test 4.8 { + WITH c(name,data,method) AS ( + SELECT 'a.txt', 'abc', 0 + UNION SELECT 'b.txt', 'def', 8 + UNION SELECT 'c.txt', 'ghi', 16 + ) + SELECT zipfile(name,NULL,NULL,data,method) FROM c +} {1 {illegal method value: 16}} + +do_catchsql_test 4.9 { + WITH c(name,data) AS ( + SELECT 'a.txt', 'abc' + UNION SELECT 'b.txt', 'def' + UNION SELECT 'c.txt/', 'ghi' + ) + SELECT zipfile(name,NULL,NULL,data) FROM c +} {1 {non-directory name must not end with /}} + +#-------------------------------------------------------------------------- + +db func rt remove_timestamps +do_execsql_test 5.0 { + WITH c(name,mtime,data) AS ( + SELECT 'a.txt', 946684800, 'abc' + ) + SELECT name,mtime,data FROM zipfile( + ( SELECT rt( zipfile(name,NULL,mtime,data,NULL) ) FROM c ) + ) +} { + a.txt 946684800 abc +} + +if {[info exists ::UNZIP]} { +ifcapable datetime { + forcedelete test1.zip test2.zip + do_test 6.0 { + execsql { + WITH c(name,mtime,data) AS ( + SELECT 'a.txt', 946684800, 'abc' UNION ALL + SELECT 'b.txt', 1000000000, 'abc' UNION ALL + SELECT 'c.txt', 1111111000, 'abc' + ) + SELECT writefile('test1.zip', rt( zipfile(name, NULL, mtime, data) ) ), + writefile('test2.zip', ( zipfile(name, NULL, mtime, data) ) ) + FROM c; + } + forcedelete test_unzip + file mkdir test_unzip + exec $::UNZIP -d test_unzip test1.zip + + db eval { + SELECT name, strftime('%s', mtime, 'unixepoch', 'localtime') + FROM fsdir('test_unzip') WHERE name!='test_unzip' + ORDER BY name + } + } [list {*}{ + test_unzip/a.txt 946684800 + test_unzip/b.txt 1000000000 + test_unzip/c.txt 1111111000 + }] + + # fsdir() issue reported on the mailing list on 2018-03-14 by Jack Thaw. + do_test 6.0b { + db eval { + SELECT sum(name LIKE '%/a.txt') + FROM (VALUES(1),(2),(3)) CROSS JOIN fsdir('test_unzip') + } + } {3} + + do_execsql_test 6.1 { + SELECT name, mtime, data FROM zipfile('test1.zip') + } { + a.txt 946684800 abc + b.txt 1000000000 abc + c.txt 1111111000 abc + } + + do_test 6.2 { + forcedelete test_unzip + file mkdir test_unzip + exec $::UNZIP -d test_unzip test2.zip + + db eval { + SELECT name, mtime + FROM fsdir('test_unzip') WHERE name!='test_unzip' + ORDER BY name + } + } [list {*}{ + test_unzip/a.txt 946684800 + test_unzip/b.txt 1000000000 + test_unzip/c.txt 1111111000 + }] + + do_execsql_test 6.3 { + SELECT name, mtime, sz, rawdata, data FROM zipfile('test2.zip') + } { + a.txt 946684800 3 abc abc + b.txt 1000000000 3 abc abc + c.txt 1111111000 3 abc abc + } +} +} + +#------------------------------------------------------------------------- +# Force an IO error by truncating the zip archive to zero bytes in size +# while it is being read. +forcedelete test.zip +do_test 7.0 { + execsql { + WITH c(name,data) AS ( + SELECT '1', randomblob(1000000) UNION ALL + SELECT '2', randomblob(1000000) UNION ALL + SELECT '3', randomblob(1000000) + ) + SELECT writefile('test.zip', zipfile(name, data) ) FROM c; + } + + list [catch { + db eval { SELECT name, data FROM zipfile('test.zip') } { + if {$name==2} { close [open test.zip w+] } + } + } msg] $msg +} {1 {error in fread()}} + +forcedelete test.zip +do_execsql_test 8.0.1 { + CREATE VIRTUAL TABLE zz USING zipfile('test.zip'); + BEGIN; + INSERT INTO zz(name, data) VALUES('a.txt', '1'); + INSERT INTO zz(name, data) VALUES('b.txt', '2'); + INSERT INTO zz(name, data) VALUES('c.txt', '1'); + INSERT INTO zz(name, data) VALUES('d.txt', '2'); + SELECT name, data FROM zz; +} { + a.txt 1 b.txt 2 c.txt 1 d.txt 2 +} +do_test 8.0.2 { + db eval { SELECT name, data FROM zz } { + if { $data=="2" } { db eval { DELETE FROM zz WHERE name=$name } } + } + execsql { SELECT name, data FROM zz } +} {a.txt 1 c.txt 1} +do_test 8.0.3 { + db eval { SELECT name, data FROM zz } { + db eval { DELETE FROM zz WHERE name=$name } + } + execsql { SELECT name, data FROM zz } +} {} +execsql COMMIT + +catch { forcedelete test_unzip } +catch { file mkdir test_unzip } +do_execsql_test 8.1.1 { + CREATE VIRTUAL TABLE nogood USING zipfile('test_unzip'); +} +do_catchsql_test 8.1.2 { + INSERT INTO nogood(name, data) VALUES('abc', 'def'); +} {1 {zipfile: failed to open file test_unzip for writing}} + +do_execsql_test 8.2.1 { + DROP TABLE nogood; + BEGIN; + CREATE VIRTUAL TABLE nogood USING zipfile('test_unzip'); +} +do_catchsql_test 8.2.2 { + INSERT INTO nogood(name, data) VALUES('abc', 'def'); +} {1 {zipfile: failed to open file test_unzip for writing}} +do_execsql_test 8.2.3 { + COMMIT; +} + +forcedelete test.zip +do_execsql_test 8.3.1 { + BEGIN; + CREATE VIRTUAL TABLE ok USING zipfile('test.zip'); + INSERT INTO ok(name, data) VALUES ('sqlite3', 'elf'); + COMMIT; +} + +#------------------------------------------------------------------------- +# Test that the zipfile aggregate correctly adds and removes "/" from +# the ends of directory file names. +do_execsql_test 9.0 { + WITH src(nm) AS ( + VALUES('dir1') UNION ALL + VALUES('dir2/') UNION ALL + VALUES('dir3//') UNION ALL + VALUES('dir4///') UNION ALL + VALUES('/') + ) + SELECT name FROM zipfile((SELECT zipfile(nm, NULL) FROM src)) +} {dir1/ dir2/ dir3/ dir4/ /} + +#------------------------------------------------------------------------- +# INSERT OR REPLACE and INSERT OR IGNORE +# +catch {db close} +forcedelete test.zip test.db +sqlite3 db :memory: +load_static_extension db zipfile +load_static_extension db fileio + +do_execsql_test 10.0 { + CREATE VIRTUAL TABLE z USING zipfile('test.zip'); +} {} +do_catchsql_test 10.1 { + INSERT INTO z(name,data) VALUES('a0','one'),('a0','two'); +} {1 {duplicate name: "a0"}} +do_execsql_test 10.2 { + SELECT name, data FROM z; +} {a0 one} +do_execsql_test 10.3 { + REPLACE INTO z(name,data) VALUES('a0','three'),('a0','four'); +} {} +do_execsql_test 10.4 { + SELECT name, data FROM z; +} {a0 four} +do_execsql_test 10.5 { + INSERT OR IGNORE INTO z(name,data) VALUES('a0','five'),('a0','six'); +} {} +do_execsql_test 10.6 { + SELECT name, data FROM z; +} {a0 four} + +do_execsql_test 11.1 { + DELETE FROM z; +} {} +do_execsql_test 11.2 { + SELECT name, data FROM z; +} {} +do_execsql_test 11.3 { + INSERT INTO z (name,data) VALUES ('b0','one'); + SELECT name, data FROM z; +} {b0 one} +do_execsql_test 11.4 { + UPDATE z SET name = 'b1' WHERE name = 'b0'; + SELECT name, data FROM z; +} {b1 one} +do_execsql_test 11.5 { + INSERT INTO z (name,data) VALUES ('b0','one'); + SELECT name, data FROM z ORDER BY name; +} {b0 one b1 one} +do_catchsql_test 11.6 { + UPDATE z SET name = 'b1' WHERE name = 'b0'; +} {1 {duplicate name: "b1"}} +do_execsql_test 11.7 { + UPDATE z SET data = 'two' WHERE name = 'b0'; + SELECT name, data FROM z ORDER BY name; +} {b0 two b1 one} +do_catchsql_test 11.8 { + UPDATE z SET name = 'b1'; +} {1 {duplicate name: "b1"}} +do_catchsql_test 11.9 { + UPDATE z SET name = 'b2'; +} {1 {duplicate name: "b2"}} +do_execsql_test 11.10 { + UPDATE z SET name = name; + SELECT name, data FROM z ORDER BY name; +} {b0 two b2 one} +do_execsql_test 11.11 { + UPDATE z SET name = name || 'suffix'; + SELECT name, data FROM z ORDER BY name; +} {b0suffix two b2suffix one} + + +if {$tcl_platform(platform)!="windows"} { + do_test 12.0 { + catch { file delete -force subdir } + foreach {path sz} { + subdir/x1.txt 143 + subdir/x2.txt 153 + } { + set dir [file dirname $path] + catch { file mkdir $dir } + set fd [open $path w] + puts -nonewline $fd [string repeat 1 $sz] + close $fd + } + } {} + + do_execsql_test 12.1 { + SELECT name FROM fsdir('subdir') ORDER BY 1; + } {subdir subdir/x1.txt subdir/x2.txt} + + do_execsql_test 12.2 { + CREATE TABLE d AS SELECT 'subdir' d; + CREATE TABLE x AS SELECT 1 x; + } + + do_execsql_test 12.4 { + SELECT name FROM d JOIN x JOIN fsdir(d) ORDER BY 1; + } {subdir subdir/x1.txt subdir/x2.txt} + + do_execsql_test 12.5 { + SELECT name FROM d JOIN x JOIN fsdir('.', d) ORDER BY 1; + } {. ./x1.txt ./x2.txt} +} + +# 2019-12-18 Yongheng and Rui fuzzer +# +do_execsql_test 13.10 { + DROP TABLE IF EXISTS t0; + DROP TABLE IF EXISTS t1; + CREATE TABLE t0(a,b,c,d,e,f,g); + REPLACE INTO t0(c,b,f) VALUES(10,10,10); + CREATE VIRTUAL TABLE t1 USING zipfile('h.zip'); + REPLACE INTO t1 SELECT * FROM t0; + SELECT quote(name),quote(mode),quote(mtime),quote(sz),quote(rawdata), + quote(data),quote(method) FROM t1; +} {'' 10 10 2 X'3130' X'3130' 0} + +# 2019-12-23 Yongheng and Rui fuzzer +# Run using valgrind to see the problem. +# +do_execsql_test 14.10 { + DROP TABLE t1; + CREATE TABLE t1(x char); + INSERT INTO t1(x) VALUES('1'); + INSERT INTO t1(x) SELECT zipfile(x, 'xyz') FROM t1; + INSERT INTO t1(x) SELECT zipfile(x, 'uvw') FROM t1; + SELECT count(*) FROM t1; + PRAGMA integrity_check; +} {3 ok} + +# 2019-12-26 More problems in zipfile from the Yongheng and Rui fuzzer +# +do_execsql_test 15.10 { + DROP TABLE IF EXISTS t1; + CREATE VIRTUAL TABLE t1 USING zipfile(null); + REPLACE INTO t1 VALUES(null,null,0,null,null,null,null); +} {} +do_execsql_test 15.20 { + DROP TABLE IF EXISTS t2; + CREATE VIRTUAL TABLE t2 USING zipfile(null); + REPLACE INTO t2 values(null,null,null,null,null,10,null); +} {} + +# 2020-01-02 Yongheng fuzzer discovery +# +do_catchsql_test 16.10 { + DELETE FROM zipfile; +} {1 {zipfile: missing filename}} +do_catchsql_test 16.20 { + REPLACE INTO zipfile VALUES(null,null,null,null,null,123,null); +} {1 {zipfile: missing filename}} + +# 2021-04-22 forum https://sqlite.org/forum/forumpost/d82289d69f +do_execsql_test 17.1 { + WITH vlist(x) AS ( + VALUES(9223372036854775807), + (-9223372036854775808), + (9223372036854775806), + (-9223372036854775807) + ) + SELECT DISTINCT typeof(zipfile(0,0,x,0)) FROM vlist; +} {blob} + +# 2023-01-04 +# https://sqlite.org/forum/forumpost/d1c96a9032e564f8 +# Call to fopen() with a NULL filename. +# +do_catchsql_test 18.1 { + SELECT * FROM zipfile(NULL); +} {1 {cannot open file: }} + +# 2023-05-03 https://sqlite.org/forum/info/f03f1e4c5a5c9959 +# +do_test 19.1 { + sqlite3 db :memory: + load_static_extension db zipfile + forcedelete zipfile19.zip + db eval { + CREATE VIRTUAL TABLE t1 USING zipfile('zipfile19.zip'); + INSERT INTO t1 DEFAULT VALUES; + } + db close + sqlite3 db :memory: + load_static_extension db zipfile + db eval { + CREATE VIRTUAL TABLE v0 USING zipfile('zipfile19.zip'); + SAVEPOINT y; + DELETE FROM v0 WHERE 9; + INSERT INTO v0 DEFAULT VALUES; + } +} {} +forcedelete zipfile19.zip + +finish_test |