github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/zipfile.test (about) 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 13 package require Tcl 8.6 14 15 set testdir [file dirname $argv0] 16 source $testdir/tester.tcl 17 set testprefix zipfile 18 19 ifcapable !vtab { 20 finish_test; return 21 } 22 if {[catch {load_static_extension db zipfile} error]} { 23 puts "Skipping zipfile tests, hit load error: $error" 24 finish_test; return 25 } 26 if {[catch {load_static_extension db fileio} error]} { 27 puts "Skipping zipfile tests, hit load error: $error" 28 finish_test; return 29 } 30 31 proc readfile {f} { 32 set fd [open $f] 33 fconfigure $fd -translation binary -encoding binary 34 set data [read $fd] 35 close $fd 36 set data 37 } 38 39 unset -nocomplain ::UNZIP 40 41 if {[catch {exec unzip} msg]==0 && \ 42 [regexp -line {^UnZip \d+\.\d+ .*? Info-ZIP\.} $msg]} { 43 set ::UNZIP unzip 44 proc fix_stat_mode {name mode} { 45 if {$::tcl_platform(platform)=="windows"} { 46 # 47 # NOTE: Set or unset the write bits of the file permissions 48 # based on the read-only attribute because the Win32 49 # version of UnZip does this. 50 # 51 set writebits 0x12; # 0o22 52 set result $mode 53 if {[file attributes $name -readonly]} { 54 set result [expr {$result | $writebits}] 55 } else { 56 set result [expr {$result & ~$writebits}] 57 } 58 return $result 59 } else { 60 return $mode 61 } 62 } 63 proc do_unzip {file} { 64 forcedelete test_unzip 65 file mkdir test_unzip 66 exec $::UNZIP -d test_unzip $file 67 68 db func modefix fix_stat_mode 69 70 set res [db eval { 71 SELECT replace(name,'test_unzip/',''),modefix(name,mode),mtime,data 72 FROM fsdir('test_unzip') 73 WHERE name!='test_unzip' 74 ORDER BY name 75 }] 76 set res 77 } 78 } 79 80 81 # The argument is a blob (not a hex string) containing a zip archive. 82 # This proc removes the extended timestamp fields from the archive 83 # and returns the result. 84 # 85 proc remove_timestamps {blob} { 86 set hex [binary encode hex $blob] 87 set hex [string map {55540500 00000500} $hex] 88 binary decode hex $hex 89 } 90 91 92 # Argument $file is the name of a zip archive on disk. This function 93 # executes test cases to check that the results of each of the following 94 # are the same: 95 # 96 # SELECT * FROM zipfile($file) 97 # SELECT * FROM zipfile( readfile($file) ) 98 # SELECT * FROM zipfile( 99 # (SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file)) 100 # ) 101 # 102 proc do_zipfile_blob_test {tn file} { 103 104 db func r readfile 105 set q1 {SELECT name,mode,mtime,method,quote(data) FROM zipfile($file)} 106 set q2 {SELECT name,mode,mtime,method,quote(data) FROM zipfile( r($file) )} 107 set q3 {SELECT name,mode,mtime,method,quote(data) FROM zipfile( 108 ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) 109 )} 110 111 112 set r1 [db eval $q1] 113 set r2 [db eval $q2] 114 set r3 [db eval $q3] 115 #puts $r1 116 #puts $r2 117 #puts $r3 118 119 uplevel [list do_test $tn.1 [list set {} $r2] $r1] 120 uplevel [list do_test $tn.2 [list set {} $r3] $r1] 121 } 122 123 # Argument $file is a zip file on disk. This command runs tests to: 124 # 125 # 1. Unpack the archive with unix command [unzip] and compare the 126 # results to reading the same archive using the zipfile() table 127 # valued function. 128 # 129 # 2. Creates a new archive with the same contents using the zipfile() 130 # aggregate function as follows: 131 # 132 # SELECT writefile('test_unzip.zip', 133 # ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) 134 # ); 135 # 136 # Then tests that unpacking the new archive using [unzip] produces 137 # the same results as in (1). 138 # 139 proc do_unzip_test {tn file} { 140 db func sss strip_slash 141 142 db eval { 143 SELECT writefile('test_unzip.zip', 144 ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) 145 ); 146 } 147 148 set r1 [db eval { 149 SELECT sss(name),mode,mtime,data FROM zipfile($file) ORDER BY name 150 }] 151 set r2 [do_unzip $file] 152 set r3 [do_unzip test_unzip.zip] 153 154 uplevel [list do_test $tn.1 [list set {} $r2] $r1] 155 uplevel [list do_test $tn.2 [list set {} $r3] $r1] 156 } 157 proc strip_slash {in} { regsub {/$} $in {} } 158 159 proc do_zip_tests {tn file} { 160 uplevel do_zipfile_blob_test $tn.1 $file 161 if {[info exists ::UNZIP]} { 162 uplevel do_unzip_test $tn.2 $file 163 } 164 } 165 166 forcedelete test.zip 167 do_execsql_test 1.0 { 168 CREATE VIRTUAL TABLE temp.zz USING zipfile('test.zip'); 169 PRAGMA table_info(zz); 170 } { 171 0 name {} 1 {} 1 172 1 mode {} 0 {} 0 173 2 mtime {} 0 {} 0 174 3 sz {} 0 {} 0 175 4 rawdata {} 0 {} 0 176 5 data {} 0 {} 0 177 6 method {} 0 {} 0 178 } 179 180 do_catchsql_test 1.1.0.1 { 181 INSERT INTO zz(name, mode, mtime, sz, rawdata, method) 182 VALUES('f.txt', '-rw-r--r--', 1000000000, 5, 'abcde', 0); 183 } {1 {rawdata must be NULL}} 184 do_catchsql_test 1.1.0.2 { 185 INSERT INTO zz(name, mtime, sz, data, method) 186 VALUES('g.txt', 1000000002, 5, '12345', 0); 187 } {1 {sz must be NULL}} 188 do_catchsql_test 1.1.0.3 { 189 INSERT INTO zz(name, mtime, rawdata, method) 190 VALUES('g.txt', 1000000002, '12345', 0); 191 } {1 {rawdata must be NULL}} 192 do_catchsql_test 1.1.0.4 { 193 INSERT INTO zz(name, data, method) 194 VALUES('g.txt', '12345', 7); 195 } {1 {unknown compression method: 7}} 196 197 do_execsql_test 1.1.1 { 198 INSERT INTO zz(name, mode, mtime, data, method) 199 VALUES('f.txt', '-rw-r--r--', 1000000000, 'abcde', 0); 200 } 201 do_execsql_test 1.1.2 { 202 INSERT INTO zz(name, mode, mtime, data, method) 203 VALUES('g.txt', NULL, 1000000002, '12345', 0); 204 } 205 206 do_execsql_test 1.2 { 207 SELECT name, mtime, data FROM zipfile('test.zip') 208 } { 209 f.txt 1000000000 abcde 210 g.txt 1000000002 12345 211 } 212 do_zip_tests 1.2a test.zip 213 214 do_execsql_test 1.3 { 215 INSERT INTO zz(name, mode, mtime, data) VALUES('h.txt', 216 '-rw-r--r--', 1000000004, 'aaaaaaaaaabbbbbbbbbb' 217 ); 218 } 219 do_zip_tests 1.3a test.zip 220 221 do_execsql_test 1.4 { 222 SELECT name, mtime, data, method FROM zipfile('test.zip'); 223 } { 224 f.txt 1000000000 abcde 0 225 g.txt 1000000002 12345 0 226 h.txt 1000000004 aaaaaaaaaabbbbbbbbbb 8 227 } 228 229 ifcapable json1 { 230 do_execsql_test 1.4.1 { 231 SELECT name, json_extract( zipfile_cds(z) , '$.crc32')!=0 232 FROM zipfile('test.zip'); 233 } { 234 f.txt 1 235 g.txt 1 236 h.txt 1 237 } 238 } 239 do_catchsql_test 1.4.2 { 240 SELECT zipfile_cds(mode) FROM zipfile('test.zip'); 241 } {0 {{} {} {}}} 242 243 do_execsql_test 1.5.1 { 244 BEGIN; 245 INSERT INTO zz(name, mode, mtime, data, method) 246 VALUES('i.txt', '-rw-r--r--', 1000000006, 'zxcvb', 0); 247 SELECT name FROM zz; 248 COMMIT; 249 } {f.txt g.txt h.txt i.txt} 250 do_execsql_test 1.5.2 { 251 SELECT name FROM zz; 252 } {f.txt g.txt h.txt i.txt} 253 do_execsql_test 1.5.3 { 254 SELECT data FROM zz WHERE name='i.txt'; 255 } {zxcvb} 256 257 do_execsql_test 1.6.0 { 258 DELETE FROM zz WHERE name='g.txt'; 259 SELECT name FROM zz; 260 } {f.txt h.txt i.txt} 261 262 do_execsql_test 1.6.1 { 263 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 264 } { 265 f.txt 33188 1000000000 abcde 0 266 h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8 267 i.txt 33188 1000000006 zxcvb 0 268 } 269 do_zip_tests 1.6.1a test.zip 270 271 do_execsql_test 1.6.2 { 272 UPDATE zz SET mtime=4 WHERE name='i.txt'; 273 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 274 } { 275 f.txt 33188 1000000000 abcde 0 276 h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8 277 i.txt 33188 4 zxcvb 0 278 } 279 280 if {$::tcl_platform(platform)=="unix"} { 281 set modes -rw-r--r-x 282 set perms 33189 283 } else { 284 set modes -rw-r--r--; # no execute bits on Win32 285 set perms 33188 286 } 287 288 do_execsql_test 1.6.3 { 289 UPDATE zz SET mode=$modes WHERE name='h.txt'; 290 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 291 } [string map [list %perms% $perms] { 292 f.txt 33188 1000000000 abcde 0 293 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 294 i.txt 33188 4 zxcvb 0 295 }] 296 do_zip_tests 1.6.3a test.zip 297 298 do_execsql_test 1.6.4 { 299 UPDATE zz SET name = 'blue.txt' WHERE name='f.txt'; 300 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 301 } [string map [list %perms% $perms] { 302 blue.txt 33188 1000000000 abcde 0 303 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 304 i.txt 33188 4 zxcvb 0 305 }] 306 do_zip_tests 1.6.4a test.zip 307 308 do_execsql_test 1.6.5 { 309 UPDATE zz SET data = 'edcba' WHERE name='blue.txt'; 310 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 311 } [string map [list %perms% $perms] { 312 blue.txt 33188 1000000000 edcba 0 313 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 314 i.txt 33188 4 zxcvb 0 315 }] 316 317 do_execsql_test 1.6.6 { 318 UPDATE zz SET mode=NULL, data = NULL WHERE name='blue.txt'; 319 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 320 } [string map [list %perms% $perms] { 321 blue.txt/ 16877 1000000000 {} 0 322 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 323 i.txt 33188 4 zxcvb 0 324 }] 325 326 do_catchsql_test 1.6.7 { 327 UPDATE zz SET data=NULL WHERE name='i.txt' 328 } {1 {zipfile: mode does not match data}} 329 do_execsql_test 1.6.8 { 330 SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); 331 } [string map [list %perms% $perms] { 332 blue.txt/ 16877 1000000000 {} 0 333 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 334 i.txt 33188 4 zxcvb 0 335 }] 336 337 do_execsql_test 1.6.9 { 338 UPDATE zz SET data = '' WHERE name='i.txt'; 339 SELECT name,mode,mtime,data,method from zipfile('test.zip'); 340 } [string map [list %perms% $perms] { 341 blue.txt/ 16877 1000000000 {} 0 342 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 343 i.txt 33188 4 {} 0 344 }] 345 346 do_execsql_test 1.6.10 { 347 SELECT a.name, a.data 348 FROM zz AS a, zz AS b 349 WHERE a.name=+b.name AND +a.mode=b.mode 350 } { 351 blue.txt/ {} 352 h.txt aaaaaaaaaabbbbbbbbbb 353 i.txt {} 354 } 355 356 do_execsql_test 1.6.11 { 357 SELECT name, data FROM zz WHERE name LIKE '%txt' 358 } { 359 h.txt aaaaaaaaaabbbbbbbbbb 360 i.txt {} 361 } 362 363 do_execsql_test 1.7 { 364 DELETE FROM zz; 365 SELECT * FROM zz; 366 } {} 367 368 #------------------------------------------------------------------------- 369 db close 370 forcedelete test.zip 371 reset_db 372 load_static_extension db fileio 373 load_static_extension db zipfile 374 do_execsql_test 2.1 { 375 CREATE VIRTUAL TABLE zzz USING zipfile('test.zip'); 376 INSERT INTO zzz(name, mode) VALUES('dirname', 'drwxr-xr-x'); 377 SELECT name, mode, data FROM zzz; 378 } {dirname/ 16877 {}} 379 do_execsql_test 2.2 { 380 INSERT INTO zzz(name, data) VALUES('dirname2', NULL); 381 INSERT INTO zzz(name, data) VALUES('dirname2/file1.txt', 'abcdefghijklmnop'); 382 SELECT name, mode, data FROM zzz; 383 } { 384 dirname/ 16877 {} 385 dirname2/ 16877 {} 386 dirname2/file1.txt 33188 abcdefghijklmnop 387 } 388 389 do_catchsql_test 2.3 { 390 UPDATE zzz SET name = 'dirname3' WHERE name = 'dirname/'; 391 } {0 {}} 392 do_execsql_test 2.4 { 393 SELECT name, mode, data FROM zzz; 394 } { 395 dirname3/ 16877 {} 396 dirname2/ 16877 {} 397 dirname2/file1.txt 33188 abcdefghijklmnop 398 } 399 do_zip_tests 2.4a test.zip 400 401 # Check that the [unzip] utility can unpack our archive. 402 # 403 if {[info exists ::UNZIP]} { 404 do_test 2.5.1 { 405 forcedelete dirname 406 forcedelete dirname2 407 if {$::tcl_platform(platform)=="unix"} { 408 set null /dev/null 409 } else { 410 set null NUL 411 } 412 set rc [catch { exec $::UNZIP test.zip > $null } msg] 413 list $rc $msg 414 } {0 {}} 415 do_test 2.5.2 { file isdir dirname3 } 1 416 do_test 2.5.3 { file isdir dirname2 } 1 417 do_test 2.5.4 { file isdir dirname2/file1.txt } 0 418 do_test 2.5.5 { 419 set fd [open dirname2/file1.txt] 420 set data [read $fd] 421 close $fd 422 set data 423 } {abcdefghijklmnop} 424 } 425 426 #------------------------------------------------------------------------- 427 reset_db 428 forcedelete test.zip 429 load_static_extension db zipfile 430 load_static_extension db fileio 431 432 do_execsql_test 3.0 { 433 CREATE VIRTUAL TABLE temp.x1 USING zipfile('test.zip'); 434 INSERT INTO x1(name, data) VALUES('dir1/', NULL); 435 INSERT INTO x1(name, data) VALUES('file1', '1234'); 436 INSERT INTO x1(name, data) VALUES('dir1/file2', '5678'); 437 } 438 foreach {tn fname} { 439 1 dir1 440 2 file1 441 3 dir1/file2 442 } { 443 do_catchsql_test 3.1.$tn.0 { 444 INSERT INTO x1(name, data) VALUES($fname, NULL); 445 } [list 1 "duplicate name: \"$fname/\""] 446 do_catchsql_test 3.1.$tn.1 { 447 INSERT INTO x1(name, data) VALUES($fname || '/', NULL); 448 } [list 1 "duplicate name: \"$fname/\""] 449 do_catchsql_test 3.1.$tn.2 { 450 INSERT INTO x1(name, data) VALUES($fname, 'abcd'); 451 } [list 1 "duplicate name: \"$fname\""] 452 } 453 454 do_catchsql_test 3.2 { 455 SELECT rowid FROM x1 456 } {1 {no such column: rowid}} 457 458 #------------------------------------------------------------------------- 459 # Test some error conditions. 460 # 461 do_catchsql_test 4.1 { 462 CREATE VIRTUAL TABLE yyy USING zipfile(); 463 } {1 {zipfile constructor requires one argument}} 464 do_catchsql_test 4.2 { 465 CREATE VIRTUAL TABLE yyy USING zipfile('test.zip', 'test.zip'); 466 } {1 {zipfile constructor requires one argument}} 467 468 do_catchsql_test 4.3 { 469 SELECT * FROM zipfile() 470 } {1 {zipfile() function requires an argument}} 471 472 do_catchsql_test 4.4 { 473 SELECT * FROM zipfile('/path/that/does/not/exist') 474 } {1 {cannot open file: /path/that/does/not/exist}} 475 476 foreach {tn mode} { 477 1 abcd 478 2 brwxrwxrwx 479 3 lrwxrrxrwx 480 } { 481 do_catchsql_test 4.5.$tn { 482 WITH m(m) AS ( SELECT $mode) 483 SELECT zipfile('a.txt', m, 1000, 'xyz') FROM m 484 } [list 1 "zipfile: parse error in mode: $mode"] 485 } 486 487 do_catchsql_test 4.6 { 488 WITH c(name,data) AS ( SELECT 'a.txt', 'abc') 489 SELECT zipfile(name) FROM c 490 } {1 {wrong number of arguments to function zipfile()}} 491 492 do_catchsql_test 4.7 { 493 WITH c(name,data) AS ( 494 SELECT 'a.txt', 'abc' UNION ALL 495 SELECT NULL, 'def' 496 ) 497 SELECT zipfile(name,data) FROM c 498 } {1 {first argument to zipfile() must be non-NULL}} 499 500 do_catchsql_test 4.8 { 501 WITH c(name,data,method) AS ( 502 SELECT 'a.txt', 'abc', 0 503 UNION SELECT 'b.txt', 'def', 8 504 UNION SELECT 'c.txt', 'ghi', 16 505 ) 506 SELECT zipfile(name,NULL,NULL,data,method) FROM c 507 } {1 {illegal method value: 16}} 508 509 do_catchsql_test 4.9 { 510 WITH c(name,data) AS ( 511 SELECT 'a.txt', 'abc' 512 UNION SELECT 'b.txt', 'def' 513 UNION SELECT 'c.txt/', 'ghi' 514 ) 515 SELECT zipfile(name,NULL,NULL,data) FROM c 516 } {1 {non-directory name must not end with /}} 517 518 #-------------------------------------------------------------------------- 519 520 db func rt remove_timestamps 521 do_execsql_test 5.0 { 522 WITH c(name,mtime,data) AS ( 523 SELECT 'a.txt', 946684800, 'abc' 524 ) 525 SELECT name,mtime,data FROM zipfile( 526 ( SELECT rt( zipfile(name,NULL,mtime,data,NULL) ) FROM c ) 527 ) 528 } { 529 a.txt 946684800 abc 530 } 531 532 if {[info exists ::UNZIP]} { 533 ifcapable datetime { 534 forcedelete test1.zip test2.zip 535 do_test 6.0 { 536 execsql { 537 WITH c(name,mtime,data) AS ( 538 SELECT 'a.txt', 946684800, 'abc' UNION ALL 539 SELECT 'b.txt', 1000000000, 'abc' UNION ALL 540 SELECT 'c.txt', 1111111000, 'abc' 541 ) 542 SELECT writefile('test1.zip', rt( zipfile(name, NULL, mtime, data) ) ), 543 writefile('test2.zip', ( zipfile(name, NULL, mtime, data) ) ) 544 FROM c; 545 } 546 forcedelete test_unzip 547 file mkdir test_unzip 548 exec $::UNZIP -d test_unzip test1.zip 549 550 db eval { 551 SELECT name, strftime('%s', mtime, 'unixepoch', 'localtime') 552 FROM fsdir('test_unzip') WHERE name!='test_unzip' 553 ORDER BY name 554 } 555 } [list {*}{ 556 test_unzip/a.txt 946684800 557 test_unzip/b.txt 1000000000 558 test_unzip/c.txt 1111111000 559 }] 560 561 # fsdir() issue reported on the mailing list on 2018-03-14 by Jack Thaw. 562 do_test 6.0b { 563 db eval { 564 SELECT sum(name LIKE '%/a.txt') 565 FROM (VALUES(1),(2),(3)) CROSS JOIN fsdir('test_unzip') 566 } 567 } {3} 568 569 do_execsql_test 6.1 { 570 SELECT name, mtime, data FROM zipfile('test1.zip') 571 } { 572 a.txt 946684800 abc 573 b.txt 1000000000 abc 574 c.txt 1111111000 abc 575 } 576 577 do_test 6.2 { 578 forcedelete test_unzip 579 file mkdir test_unzip 580 exec $::UNZIP -d test_unzip test2.zip 581 582 db eval { 583 SELECT name, mtime 584 FROM fsdir('test_unzip') WHERE name!='test_unzip' 585 ORDER BY name 586 } 587 } [list {*}{ 588 test_unzip/a.txt 946684800 589 test_unzip/b.txt 1000000000 590 test_unzip/c.txt 1111111000 591 }] 592 593 do_execsql_test 6.3 { 594 SELECT name, mtime, sz, rawdata, data FROM zipfile('test2.zip') 595 } { 596 a.txt 946684800 3 abc abc 597 b.txt 1000000000 3 abc abc 598 c.txt 1111111000 3 abc abc 599 } 600 } 601 } 602 603 #------------------------------------------------------------------------- 604 # Force an IO error by truncating the zip archive to zero bytes in size 605 # while it is being read. 606 forcedelete test.zip 607 do_test 7.0 { 608 execsql { 609 WITH c(name,data) AS ( 610 SELECT '1', randomblob(1000000) UNION ALL 611 SELECT '2', randomblob(1000000) UNION ALL 612 SELECT '3', randomblob(1000000) 613 ) 614 SELECT writefile('test.zip', zipfile(name, data) ) FROM c; 615 } 616 617 list [catch { 618 db eval { SELECT name, data FROM zipfile('test.zip') } { 619 if {$name==2} { close [open test.zip w+] } 620 } 621 } msg] $msg 622 } {1 {error in fread()}} 623 624 forcedelete test.zip 625 do_execsql_test 8.0.1 { 626 CREATE VIRTUAL TABLE zz USING zipfile('test.zip'); 627 BEGIN; 628 INSERT INTO zz(name, data) VALUES('a.txt', '1'); 629 INSERT INTO zz(name, data) VALUES('b.txt', '2'); 630 INSERT INTO zz(name, data) VALUES('c.txt', '1'); 631 INSERT INTO zz(name, data) VALUES('d.txt', '2'); 632 SELECT name, data FROM zz; 633 } { 634 a.txt 1 b.txt 2 c.txt 1 d.txt 2 635 } 636 do_test 8.0.2 { 637 db eval { SELECT name, data FROM zz } { 638 if { $data=="2" } { db eval { DELETE FROM zz WHERE name=$name } } 639 } 640 execsql { SELECT name, data FROM zz } 641 } {a.txt 1 c.txt 1} 642 do_test 8.0.3 { 643 db eval { SELECT name, data FROM zz } { 644 db eval { DELETE FROM zz WHERE name=$name } 645 } 646 execsql { SELECT name, data FROM zz } 647 } {} 648 execsql COMMIT 649 650 catch { forcedelete test_unzip } 651 catch { file mkdir test_unzip } 652 do_execsql_test 8.1.1 { 653 CREATE VIRTUAL TABLE nogood USING zipfile('test_unzip'); 654 } 655 do_catchsql_test 8.1.2 { 656 INSERT INTO nogood(name, data) VALUES('abc', 'def'); 657 } {1 {zipfile: failed to open file test_unzip for writing}} 658 659 do_execsql_test 8.2.1 { 660 DROP TABLE nogood; 661 BEGIN; 662 CREATE VIRTUAL TABLE nogood USING zipfile('test_unzip'); 663 } 664 do_catchsql_test 8.2.2 { 665 INSERT INTO nogood(name, data) VALUES('abc', 'def'); 666 } {1 {zipfile: failed to open file test_unzip for writing}} 667 do_execsql_test 8.2.3 { 668 COMMIT; 669 } 670 671 forcedelete test.zip 672 do_execsql_test 8.3.1 { 673 BEGIN; 674 CREATE VIRTUAL TABLE ok USING zipfile('test.zip'); 675 INSERT INTO ok(name, data) VALUES ('sqlite3', 'elf'); 676 COMMIT; 677 } 678 679 #------------------------------------------------------------------------- 680 # Test that the zipfile aggregate correctly adds and removes "/" from 681 # the ends of directory file names. 682 do_execsql_test 9.0 { 683 WITH src(nm) AS ( 684 VALUES('dir1') UNION ALL 685 VALUES('dir2/') UNION ALL 686 VALUES('dir3//') UNION ALL 687 VALUES('dir4///') UNION ALL 688 VALUES('/') 689 ) 690 SELECT name FROM zipfile((SELECT zipfile(nm, NULL) FROM src)) 691 } {dir1/ dir2/ dir3/ dir4/ /} 692 693 #------------------------------------------------------------------------- 694 # INSERT OR REPLACE and INSERT OR IGNORE 695 # 696 catch {db close} 697 forcedelete test.zip test.db 698 sqlite3 db :memory: 699 load_static_extension db zipfile 700 load_static_extension db fileio 701 702 do_execsql_test 10.0 { 703 CREATE VIRTUAL TABLE z USING zipfile('test.zip'); 704 } {} 705 do_catchsql_test 10.1 { 706 INSERT INTO z(name,data) VALUES('a0','one'),('a0','two'); 707 } {1 {duplicate name: "a0"}} 708 do_execsql_test 10.2 { 709 SELECT name, data FROM z; 710 } {a0 one} 711 do_execsql_test 10.3 { 712 REPLACE INTO z(name,data) VALUES('a0','three'),('a0','four'); 713 } {} 714 do_execsql_test 10.4 { 715 SELECT name, data FROM z; 716 } {a0 four} 717 do_execsql_test 10.5 { 718 INSERT OR IGNORE INTO z(name,data) VALUES('a0','five'),('a0','six'); 719 } {} 720 do_execsql_test 10.6 { 721 SELECT name, data FROM z; 722 } {a0 four} 723 724 do_execsql_test 11.1 { 725 DELETE FROM z; 726 } {} 727 do_execsql_test 11.2 { 728 SELECT name, data FROM z; 729 } {} 730 do_execsql_test 11.3 { 731 INSERT INTO z (name,data) VALUES ('b0','one'); 732 SELECT name, data FROM z; 733 } {b0 one} 734 do_execsql_test 11.4 { 735 UPDATE z SET name = 'b1' WHERE name = 'b0'; 736 SELECT name, data FROM z; 737 } {b1 one} 738 do_execsql_test 11.5 { 739 INSERT INTO z (name,data) VALUES ('b0','one'); 740 SELECT name, data FROM z ORDER BY name; 741 } {b0 one b1 one} 742 do_catchsql_test 11.6 { 743 UPDATE z SET name = 'b1' WHERE name = 'b0'; 744 } {1 {duplicate name: "b1"}} 745 do_execsql_test 11.7 { 746 UPDATE z SET data = 'two' WHERE name = 'b0'; 747 SELECT name, data FROM z ORDER BY name; 748 } {b0 two b1 one} 749 do_catchsql_test 11.8 { 750 UPDATE z SET name = 'b1'; 751 } {1 {duplicate name: "b1"}} 752 do_catchsql_test 11.9 { 753 UPDATE z SET name = 'b2'; 754 } {1 {duplicate name: "b2"}} 755 do_execsql_test 11.10 { 756 UPDATE z SET name = name; 757 SELECT name, data FROM z ORDER BY name; 758 } {b0 two b2 one} 759 do_execsql_test 11.11 { 760 UPDATE z SET name = name || 'suffix'; 761 SELECT name, data FROM z ORDER BY name; 762 } {b0suffix two b2suffix one} 763 764 765 if {$tcl_platform(platform)!="windows"} { 766 do_test 12.0 { 767 catch { file delete -force subdir } 768 foreach {path sz} { 769 subdir/x1.txt 143 770 subdir/x2.txt 153 771 } { 772 set dir [file dirname $path] 773 catch { file mkdir $dir } 774 set fd [open $path w] 775 puts -nonewline $fd [string repeat 1 $sz] 776 close $fd 777 } 778 } {} 779 780 do_execsql_test 12.1 { 781 SELECT name FROM fsdir('subdir') ORDER BY 1; 782 } {subdir subdir/x1.txt subdir/x2.txt} 783 784 do_execsql_test 12.2 { 785 CREATE TABLE d AS SELECT 'subdir' d; 786 CREATE TABLE x AS SELECT 1 x; 787 } 788 789 do_execsql_test 12.4 { 790 SELECT name FROM d JOIN x JOIN fsdir(d) ORDER BY 1; 791 } {subdir subdir/x1.txt subdir/x2.txt} 792 793 do_execsql_test 12.5 { 794 SELECT name FROM d JOIN x JOIN fsdir('.', d) ORDER BY 1; 795 } {. ./x1.txt ./x2.txt} 796 } 797 798 # 2019-12-18 Yongheng and Rui fuzzer 799 # 800 do_execsql_test 13.10 { 801 DROP TABLE IF EXISTS t0; 802 DROP TABLE IF EXISTS t1; 803 CREATE TABLE t0(a,b,c,d,e,f,g); 804 REPLACE INTO t0(c,b,f) VALUES(10,10,10); 805 CREATE VIRTUAL TABLE t1 USING zipfile('h.zip'); 806 REPLACE INTO t1 SELECT * FROM t0; 807 SELECT quote(name),quote(mode),quote(mtime),quote(sz),quote(rawdata), 808 quote(data),quote(method) FROM t1; 809 } {'' 10 10 2 X'3130' X'3130' 0} 810 811 # 2019-12-23 Yongheng and Rui fuzzer 812 # Run using valgrind to see the problem. 813 # 814 do_execsql_test 14.10 { 815 DROP TABLE t1; 816 CREATE TABLE t1(x char); 817 INSERT INTO t1(x) VALUES('1'); 818 INSERT INTO t1(x) SELECT zipfile(x, 'xyz') FROM t1; 819 INSERT INTO t1(x) SELECT zipfile(x, 'uvw') FROM t1; 820 SELECT count(*) FROM t1; 821 PRAGMA integrity_check; 822 } {3 ok} 823 824 # 2019-12-26 More problems in zipfile from the Yongheng and Rui fuzzer 825 # 826 do_execsql_test 15.10 { 827 DROP TABLE IF EXISTS t1; 828 CREATE VIRTUAL TABLE t1 USING zipfile(null); 829 REPLACE INTO t1 VALUES(null,null,0,null,null,null,null); 830 } {} 831 do_execsql_test 15.20 { 832 DROP TABLE IF EXISTS t2; 833 CREATE VIRTUAL TABLE t2 USING zipfile(null); 834 REPLACE INTO t2 values(null,null,null,null,null,10,null); 835 } {} 836 837 # 2020-01-02 Yongheng fuzzer discovery 838 # 839 do_catchsql_test 16.10 { 840 DELETE FROM zipfile; 841 } {1 {zipfile: missing filename}} 842 do_catchsql_test 16.20 { 843 REPLACE INTO zipfile VALUES(null,null,null,null,null,123,null); 844 } {1 {zipfile: missing filename}} 845 846 # 2021-04-22 forum https://sqlite.org/forum/forumpost/d82289d69f 847 do_execsql_test 17.1 { 848 WITH vlist(x) AS ( 849 VALUES(9223372036854775807), 850 (-9223372036854775808), 851 (9223372036854775806), 852 (-9223372036854775807) 853 ) 854 SELECT DISTINCT typeof(zipfile(0,0,x,0)) FROM vlist; 855 } {blob} 856 857 858 finish_test