xref: /sqlite-3.40.0/test/zipfile.test (revision b5a4a705)
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
13package require Tcl 8.6
14
15set testdir [file dirname $argv0]
16source $testdir/tester.tcl
17set testprefix zipfile
18
19ifcapable !vtab {
20  finish_test; return
21}
22if {[catch {load_static_extension db zipfile} error]} {
23  puts "Skipping zipfile tests, hit load error: $error"
24  finish_test; return
25}
26if {[catch {load_static_extension db fileio} error]} {
27  puts "Skipping zipfile tests, hit load error: $error"
28  finish_test; return
29}
30
31proc 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
39unset -nocomplain ::UNZIP
40
41if {[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#
85proc 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#
102proc 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#
139proc 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}
157proc strip_slash {in} { regsub {/$} $in {} }
158
159proc do_zip_tests {tn file} {
160  uplevel do_zipfile_blob_test $tn.1 $file
161  uplevel do_unzip_test $tn.2 $file
162}
163
164forcedelete test.zip
165do_execsql_test 1.0 {
166  CREATE VIRTUAL TABLE temp.zz USING zipfile('test.zip');
167  PRAGMA table_info(zz);
168} {
169  0 name {} 1 {} 1
170  1 mode {} 0 {} 0
171  2 mtime {} 0 {} 0
172  3 sz {} 0 {} 0
173  4 rawdata {} 0 {} 0
174  5 data {} 0 {} 0
175  6 method {} 0 {} 0
176}
177
178do_catchsql_test 1.1.0.1 {
179  INSERT INTO zz(name, mode, mtime, sz, rawdata, method)
180  VALUES('f.txt', '-rw-r--r--', 1000000000, 5, 'abcde', 0);
181} {1 {rawdata must be NULL}}
182do_catchsql_test 1.1.0.2 {
183  INSERT INTO zz(name, mtime, sz, data, method)
184  VALUES('g.txt', 1000000002, 5, '12345', 0);
185} {1 {sz must be NULL}}
186do_catchsql_test 1.1.0.3 {
187  INSERT INTO zz(name, mtime, rawdata, method)
188  VALUES('g.txt', 1000000002, '12345', 0);
189} {1 {rawdata must be NULL}}
190do_catchsql_test 1.1.0.4 {
191  INSERT INTO zz(name, data, method)
192  VALUES('g.txt', '12345', 7);
193} {1 {unknown compression method: 7}}
194
195do_execsql_test 1.1.1 {
196  INSERT INTO zz(name, mode, mtime, data, method)
197  VALUES('f.txt', '-rw-r--r--', 1000000000, 'abcde', 0);
198}
199do_execsql_test 1.1.2 {
200  INSERT INTO zz(name, mode, mtime, data, method)
201  VALUES('g.txt', NULL, 1000000002, '12345', 0);
202}
203
204do_execsql_test 1.2 {
205  SELECT name, mtime, data FROM zipfile('test.zip')
206} {
207  f.txt 1000000000 abcde
208  g.txt 1000000002 12345
209}
210do_zip_tests 1.2a test.zip
211
212do_execsql_test 1.3 {
213  INSERT INTO zz(name, mode, mtime, data) VALUES('h.txt',
214    '-rw-r--r--', 1000000004, 'aaaaaaaaaabbbbbbbbbb'
215  );
216}
217do_zip_tests 1.3a test.zip
218
219do_execsql_test 1.4 {
220  SELECT name, mtime, data, method FROM zipfile('test.zip');
221} {
222  f.txt 1000000000 abcde 0
223  g.txt 1000000002 12345 0
224  h.txt 1000000004 aaaaaaaaaabbbbbbbbbb 8
225}
226
227ifcapable json1 {
228  do_execsql_test 1.4.1 {
229    SELECT name, json_extract( zipfile_cds(z) , '$.crc32')!=0
230    FROM zipfile('test.zip');
231  } {
232    f.txt 1
233    g.txt 1
234    h.txt 1
235  }
236}
237do_catchsql_test 1.4.2 {
238  SELECT zipfile_cds(mode) FROM zipfile('test.zip');
239} {0 {{} {} {}}}
240
241do_execsql_test 1.5.1 {
242  BEGIN;
243    INSERT INTO zz(name, mode, mtime, data, method)
244    VALUES('i.txt', '-rw-r--r--', 1000000006, 'zxcvb', 0);
245    SELECT name FROM zz;
246  COMMIT;
247} {f.txt g.txt h.txt i.txt}
248do_execsql_test 1.5.2 {
249  SELECT name FROM zz;
250} {f.txt g.txt h.txt i.txt}
251do_execsql_test 1.5.3 {
252  SELECT data FROM zz WHERE name='i.txt';
253} {zxcvb}
254
255do_execsql_test 1.6.0 {
256  DELETE FROM zz WHERE name='g.txt';
257  SELECT name FROM zz;
258} {f.txt h.txt i.txt}
259
260do_execsql_test 1.6.1 {
261  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
262} {
263  f.txt 33188 1000000000 abcde 0
264  h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8
265  i.txt 33188 1000000006 zxcvb 0
266}
267do_zip_tests 1.6.1a test.zip
268
269do_execsql_test 1.6.2 {
270  UPDATE zz SET mtime=4 WHERE name='i.txt';
271  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
272} {
273  f.txt 33188 1000000000 abcde 0
274  h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8
275  i.txt 33188 4 zxcvb 0
276}
277
278if {$::tcl_platform(platform)=="unix"} {
279  set modes -rw-r--r-x
280  set perms 33189
281} else {
282  set modes -rw-r--r--; # no execute bits on Win32
283  set perms 33188
284}
285
286do_execsql_test 1.6.3 {
287  UPDATE zz SET mode=$modes WHERE name='h.txt';
288  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
289} [string map [list %perms% $perms] {
290  f.txt 33188 1000000000 abcde 0
291  h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8
292  i.txt 33188 4 zxcvb 0
293}]
294do_zip_tests 1.6.3a test.zip
295
296do_execsql_test 1.6.4 {
297  UPDATE zz SET name = 'blue.txt' WHERE name='f.txt';
298  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
299} [string map [list %perms% $perms] {
300  blue.txt 33188 1000000000 abcde 0
301  h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8
302  i.txt 33188 4 zxcvb 0
303}]
304do_zip_tests 1.6.4a test.zip
305
306do_execsql_test 1.6.5 {
307  UPDATE zz SET data = 'edcba' WHERE name='blue.txt';
308  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
309} [string map [list %perms% $perms] {
310  blue.txt 33188 1000000000 edcba 0
311  h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8
312  i.txt 33188 4 zxcvb 0
313}]
314
315do_execsql_test 1.6.6 {
316  UPDATE zz SET mode=NULL, data = NULL WHERE name='blue.txt';
317  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
318} [string map [list %perms% $perms] {
319  blue.txt/ 16877 1000000000 {} 0
320  h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8
321  i.txt 33188 4 zxcvb 0
322}]
323
324do_catchsql_test 1.6.7 {
325  UPDATE zz SET data=NULL WHERE name='i.txt'
326} {1 {zipfile: mode does not match data}}
327do_execsql_test 1.6.8 {
328  SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
329} [string map [list %perms% $perms] {
330  blue.txt/ 16877 1000000000 {} 0
331  h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8
332  i.txt 33188 4 zxcvb 0
333}]
334
335do_execsql_test 1.6.9 {
336  UPDATE zz SET data = '' WHERE name='i.txt';
337  SELECT name,mode,mtime,data,method from zipfile('test.zip');
338} [string map [list %perms% $perms] {
339  blue.txt/ 16877 1000000000 {} 0
340  h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8
341  i.txt 33188 4 {} 0
342}]
343
344do_execsql_test 1.6.10 {
345  SELECT a.name, a.data
346  FROM zz AS a, zz AS b
347  WHERE a.name=+b.name AND +a.mode=b.mode
348} {
349  blue.txt/ {}
350  h.txt aaaaaaaaaabbbbbbbbbb
351  i.txt {}
352}
353
354do_execsql_test 1.6.11 {
355  SELECT name, data FROM zz WHERE name LIKE '%txt'
356} {
357  h.txt aaaaaaaaaabbbbbbbbbb
358  i.txt {}
359}
360
361do_execsql_test 1.7 {
362  DELETE FROM zz;
363  SELECT * FROM zz;
364} {}
365
366#-------------------------------------------------------------------------
367db close
368forcedelete test.zip
369reset_db
370load_static_extension db fileio
371load_static_extension db zipfile
372do_execsql_test 2.1 {
373  CREATE VIRTUAL TABLE zzz USING zipfile('test.zip');
374  INSERT INTO zzz(name, mode) VALUES('dirname', 'drwxr-xr-x');
375  SELECT name, mode, data FROM zzz;
376} {dirname/ 16877 {}}
377do_execsql_test 2.2 {
378  INSERT INTO zzz(name, data) VALUES('dirname2', NULL);
379  INSERT INTO zzz(name, data) VALUES('dirname2/file1.txt', 'abcdefghijklmnop');
380  SELECT name, mode, data FROM zzz;
381} {
382  dirname/ 16877 {}
383  dirname2/ 16877 {}
384  dirname2/file1.txt 33188 abcdefghijklmnop
385}
386
387do_catchsql_test 2.3 {
388  UPDATE zzz SET name = 'dirname3' WHERE name = 'dirname/';
389} {0 {}}
390do_execsql_test 2.4 {
391  SELECT name, mode, data FROM zzz;
392} {
393  dirname3/ 16877 {}
394  dirname2/ 16877 {}
395  dirname2/file1.txt 33188 abcdefghijklmnop
396}
397do_zip_tests 2.4a test.zip
398
399# Check that the [unzip] utility can unpack our archive.
400#
401if {[info exists ::UNZIP]} {
402  do_test 2.5.1 {
403    forcedelete dirname
404    forcedelete dirname2
405    if {$::tcl_platform(platform)=="unix"} {
406      set null /dev/null
407    } else {
408      set null NUL
409    }
410    set rc [catch { exec $::UNZIP test.zip > $null } msg]
411    list $rc $msg
412  } {0 {}}
413  do_test 2.5.2 { file isdir dirname3 } 1
414  do_test 2.5.3 { file isdir dirname2 } 1
415  do_test 2.5.4 { file isdir dirname2/file1.txt } 0
416  do_test 2.5.5 {
417    set fd [open dirname2/file1.txt]
418    set data [read $fd]
419    close $fd
420    set data
421  } {abcdefghijklmnop}
422}
423
424#-------------------------------------------------------------------------
425reset_db
426forcedelete test.zip
427load_static_extension db zipfile
428load_static_extension db fileio
429
430do_execsql_test 3.0 {
431  CREATE VIRTUAL TABLE temp.x1 USING zipfile('test.zip');
432  INSERT INTO x1(name, data) VALUES('dir1/', NULL);
433  INSERT INTO x1(name, data) VALUES('file1', '1234');
434  INSERT INTO x1(name, data) VALUES('dir1/file2', '5678');
435}
436foreach {tn fname} {
437  1 dir1
438  2 file1
439  3 dir1/file2
440} {
441  do_catchsql_test 3.1.$tn.0 {
442    INSERT INTO x1(name, data) VALUES($fname, NULL);
443  } [list 1 "duplicate name: \"$fname/\""]
444  do_catchsql_test 3.1.$tn.1 {
445    INSERT INTO x1(name, data) VALUES($fname || '/', NULL);
446  } [list 1 "duplicate name: \"$fname/\""]
447  do_catchsql_test 3.1.$tn.2 {
448    INSERT INTO x1(name, data) VALUES($fname, 'abcd');
449  } [list 1 "duplicate name: \"$fname\""]
450}
451
452do_catchsql_test 3.2 {
453  SELECT rowid FROM x1
454} {1 {no such column: rowid}}
455
456#-------------------------------------------------------------------------
457# Test some error conditions.
458#
459do_catchsql_test 4.1 {
460  CREATE VIRTUAL TABLE yyy USING zipfile();
461} {1 {zipfile constructor requires one argument}}
462do_catchsql_test 4.2 {
463  CREATE VIRTUAL TABLE yyy USING zipfile('test.zip', 'test.zip');
464} {1 {zipfile constructor requires one argument}}
465
466do_catchsql_test 4.3 {
467  SELECT * FROM zipfile()
468} {1 {zipfile() function requires an argument}}
469
470do_catchsql_test 4.4 {
471  SELECT * FROM zipfile('/path/that/does/not/exist')
472} {1 {cannot open file: /path/that/does/not/exist}}
473
474foreach {tn mode} {
475  1 abcd
476  2 brwxrwxrwx
477  3 lrwxrrxrwx
478} {
479  do_catchsql_test 4.5.$tn {
480    WITH m(m) AS ( SELECT $mode)
481    SELECT zipfile('a.txt', m, 1000, 'xyz') FROM m
482  } [list 1 "zipfile: parse error in mode: $mode"]
483}
484
485do_catchsql_test 4.6 {
486  WITH c(name,data) AS ( SELECT 'a.txt', 'abc')
487  SELECT zipfile(name) FROM c
488} {1 {wrong number of arguments to function zipfile()}}
489
490do_catchsql_test 4.7 {
491  WITH c(name,data) AS (
492    SELECT 'a.txt', 'abc' UNION ALL
493    SELECT NULL, 'def'
494  )
495  SELECT zipfile(name,data) FROM c
496} {1 {first argument to zipfile() must be non-NULL}}
497
498do_catchsql_test 4.8 {
499  WITH c(name,data,method) AS (
500    SELECT 'a.txt', 'abc', 0
501    UNION SELECT 'b.txt', 'def', 8
502    UNION SELECT 'c.txt', 'ghi', 16
503  )
504  SELECT zipfile(name,NULL,NULL,data,method) FROM c
505} {1 {illegal method value: 16}}
506
507do_catchsql_test 4.9 {
508  WITH c(name,data) AS (
509    SELECT 'a.txt', 'abc'
510    UNION SELECT 'b.txt', 'def'
511    UNION SELECT 'c.txt/', 'ghi'
512  )
513  SELECT zipfile(name,NULL,NULL,data) FROM c
514} {1 {non-directory name must not end with /}}
515
516#--------------------------------------------------------------------------
517
518db func rt remove_timestamps
519do_execsql_test 5.0 {
520  WITH c(name,mtime,data) AS (
521    SELECT 'a.txt', 946684800, 'abc'
522  )
523  SELECT name,mtime,data FROM zipfile(
524    ( SELECT rt( zipfile(name,NULL,mtime,data,NULL) ) FROM c )
525  )
526} {
527  a.txt 946684800 abc
528}
529
530if {[info exists ::UNZIP]} {
531ifcapable datetime {
532  forcedelete test1.zip test2.zip
533  do_test 6.0 {
534    execsql {
535      WITH c(name,mtime,data) AS (
536        SELECT 'a.txt', 946684800, 'abc' UNION ALL
537        SELECT 'b.txt', 1000000000, 'abc' UNION ALL
538        SELECT 'c.txt', 1111111000, 'abc'
539      )
540      SELECT writefile('test1.zip', rt( zipfile(name, NULL, mtime, data) ) ),
541             writefile('test2.zip',   ( zipfile(name, NULL, mtime, data) ) )
542      FROM c;
543    }
544    forcedelete test_unzip
545    file mkdir test_unzip
546    exec $::UNZIP -d test_unzip test1.zip
547
548    db eval {
549      SELECT name, strftime('%s', mtime, 'unixepoch', 'localtime')
550      FROM fsdir('test_unzip') WHERE name!='test_unzip'
551      ORDER BY name
552    }
553  } [list {*}{
554    test_unzip/a.txt 946684800
555    test_unzip/b.txt 1000000000
556    test_unzip/c.txt 1111111000
557  }]
558
559  # fsdir() issue reported on the mailing list on 2018-03-14 by Jack Thaw.
560  do_test 6.0b {
561    db eval {
562      SELECT sum(name LIKE '%/a.txt')
563      FROM (VALUES(1),(2),(3)) CROSS JOIN fsdir('test_unzip')
564    }
565  } {3}
566
567  do_execsql_test 6.1 {
568    SELECT name, mtime, data FROM zipfile('test1.zip')
569  } {
570    a.txt 946684800   abc
571    b.txt 1000000000  abc
572    c.txt 1111111000  abc
573  }
574
575  do_test 6.2 {
576    forcedelete test_unzip
577    file mkdir test_unzip
578    exec $::UNZIP -d test_unzip test2.zip
579
580    db eval {
581      SELECT name, mtime
582      FROM fsdir('test_unzip') WHERE name!='test_unzip'
583      ORDER BY name
584    }
585  } [list {*}{
586    test_unzip/a.txt 946684800
587    test_unzip/b.txt 1000000000
588    test_unzip/c.txt 1111111000
589  }]
590
591  do_execsql_test 6.3 {
592    SELECT name, mtime, sz, rawdata, data FROM zipfile('test2.zip')
593  } {
594    a.txt 946684800   3 abc abc
595    b.txt 1000000000  3 abc abc
596    c.txt 1111111000  3 abc abc
597  }
598}
599}
600
601#-------------------------------------------------------------------------
602# Force an IO error by truncating the zip archive to zero bytes in size
603# while it is being read.
604forcedelete test.zip
605do_test 7.0 {
606  execsql {
607    WITH c(name,data) AS (
608        SELECT '1', randomblob(1000000) UNION ALL
609        SELECT '2', randomblob(1000000) UNION ALL
610        SELECT '3', randomblob(1000000)
611    )
612    SELECT writefile('test.zip', zipfile(name, data) ) FROM c;
613  }
614
615  list [catch {
616    db eval { SELECT name, data FROM zipfile('test.zip') } {
617      if {$name==2} { close [open test.zip w+] }
618    }
619  } msg] $msg
620} {1 {error in fread()}}
621
622forcedelete test.zip
623do_execsql_test 8.0.1 {
624  CREATE VIRTUAL TABLE zz USING zipfile('test.zip');
625  BEGIN;
626    INSERT INTO zz(name, data) VALUES('a.txt', '1');
627    INSERT INTO zz(name, data) VALUES('b.txt', '2');
628    INSERT INTO zz(name, data) VALUES('c.txt', '1');
629    INSERT INTO zz(name, data) VALUES('d.txt', '2');
630    SELECT name, data FROM zz;
631} {
632  a.txt 1 b.txt 2 c.txt 1 d.txt 2
633}
634do_test 8.0.2 {
635  db eval { SELECT name, data FROM zz } {
636    if { $data=="2" } { db eval { DELETE FROM zz WHERE name=$name } }
637  }
638  execsql { SELECT name, data FROM zz }
639} {a.txt 1 c.txt 1}
640do_test 8.0.3 {
641  db eval { SELECT name, data FROM zz } {
642    db eval { DELETE FROM zz WHERE name=$name }
643  }
644  execsql { SELECT name, data FROM zz }
645} {}
646execsql COMMIT
647
648do_execsql_test 8.1.1 {
649  CREATE VIRTUAL TABLE nogood USING zipfile('test_unzip');
650}
651do_catchsql_test 8.1.2 {
652  INSERT INTO nogood(name, data) VALUES('abc', 'def');
653} {1 {zipfile: failed to open file test_unzip for writing}}
654
655do_execsql_test 8.2.1 {
656  DROP TABLE nogood;
657  BEGIN;
658    CREATE VIRTUAL TABLE nogood USING zipfile('test_unzip');
659}
660do_catchsql_test 8.2.2 {
661    INSERT INTO nogood(name, data) VALUES('abc', 'def');
662} {1 {zipfile: failed to open file test_unzip for writing}}
663do_execsql_test 8.2.3 {
664  COMMIT;
665}
666
667forcedelete test.zip
668do_execsql_test 8.3.1 {
669  BEGIN;
670    CREATE VIRTUAL TABLE ok USING zipfile('test.zip');
671    INSERT INTO ok(name, data) VALUES ('sqlite3', 'elf');
672  COMMIT;
673}
674
675#-------------------------------------------------------------------------
676# Test that the zipfile aggregate correctly adds and removes "/" from
677# the ends of directory file names.
678do_execsql_test 9.0 {
679  WITH src(nm) AS (
680    VALUES('dir1') UNION ALL
681    VALUES('dir2/') UNION ALL
682    VALUES('dir3//') UNION ALL
683    VALUES('dir4///') UNION ALL
684    VALUES('/')
685  )
686  SELECT name FROM zipfile((SELECT zipfile(nm, NULL) FROM src))
687} {dir1/ dir2/ dir3/ dir4/ /}
688
689#-------------------------------------------------------------------------
690# INSERT OR REPLACE and INSERT OR IGNORE
691#
692catch {db close}
693forcedelete test.zip test.db
694sqlite3 db :memory:
695load_static_extension db zipfile
696load_static_extension db fileio
697
698do_execsql_test 10.0 {
699  CREATE VIRTUAL TABLE z USING zipfile('test.zip');
700} {}
701do_catchsql_test 10.1 {
702  INSERT INTO z(name,data) VALUES('a0','one'),('a0','two');
703} {1 {duplicate name: "a0"}}
704do_execsql_test 10.2 {
705  SELECT name, data FROM z;
706} {a0 one}
707do_execsql_test 10.3 {
708  REPLACE INTO z(name,data) VALUES('a0','three'),('a0','four');
709} {}
710do_execsql_test 10.4 {
711  SELECT name, data FROM z;
712} {a0 four}
713do_execsql_test 10.5 {
714  INSERT OR IGNORE INTO z(name,data) VALUES('a0','five'),('a0','six');
715} {}
716do_execsql_test 10.6 {
717  SELECT name, data FROM z;
718} {a0 four}
719
720
721finish_test
722