xref: /sqlite-3.40.0/test/zipfile.test (revision fdcd9d4e)
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