blob: 509dfe530c0cd6bbc22b309f921dcf279b0a5d3e [file] [log] [blame]
dan8311c472010-08-19 11:05:53 +00001# 2010 August 19
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# This file implements regression tests for SQLite library. The
12# focus of this file is testing that the current version of SQLite
13# is capable of reading and writing databases created by previous
14# versions, and vice-versa.
15#
16# To use this test, old versions of the testfixture process should be
17# copied into the working directory alongside the new version. The old
18# versions should be named "testfixtureXXX" (or testfixtureXXX.exe on
19# windows), where XXX can be any string.
20#
21# This test file uses the tcl code for controlling a second testfixture
22# process located in lock_common.tcl. See the commments in lock_common.tcl
23# for documentation of the available commands.
24#
25
26set testdir [file dirname $argv0]
27source $testdir/tester.tcl
28source $testdir/lock_common.tcl
29source $testdir/malloc_common.tcl
dan74f47e12012-03-21 14:34:23 +000030source $testdir/bc_common.tcl
dana35dafc2010-08-19 15:11:34 +000031db close
dan8311c472010-08-19 11:05:53 +000032
dan74f47e12012-03-21 14:34:23 +000033if {"" == [bc_find_binaries backcompat.test]} {
dan8311c472010-08-19 11:05:53 +000034 finish_test
35 return
36}
dan8311c472010-08-19 11:05:53 +000037
dana35dafc2010-08-19 15:11:34 +000038proc do_backcompat_test {rv bin1 bin2 script} {
dan8311c472010-08-19 11:05:53 +000039
mistachkinfda06be2011-08-02 00:57:34 +000040 forcedelete test.db
dana35dafc2010-08-19 15:11:34 +000041
42 if {$bin1 != ""} { set ::bc_chan1 [launch_testfixture $bin1] }
43 set ::bc_chan2 [launch_testfixture $bin2]
dan8311c472010-08-19 11:05:53 +000044
45 if { $rv } {
dan8311c472010-08-19 11:05:53 +000046 proc code2 {tcl} { uplevel #0 $tcl }
dana35dafc2010-08-19 15:11:34 +000047 if {$bin1 != ""} { proc code2 {tcl} { testfixture $::bc_chan1 $tcl } }
48 proc code1 {tcl} { testfixture $::bc_chan2 $tcl }
dan8311c472010-08-19 11:05:53 +000049 } else {
50 proc code1 {tcl} { uplevel #0 $tcl }
dana35dafc2010-08-19 15:11:34 +000051 if {$bin1 != ""} { proc code1 {tcl} { testfixture $::bc_chan1 $tcl } }
52 proc code2 {tcl} { testfixture $::bc_chan2 $tcl }
dan8311c472010-08-19 11:05:53 +000053 }
54
55 proc sql1 sql { code1 [list db eval $sql] }
56 proc sql2 sql { code2 [list db eval $sql] }
57
dan8311c472010-08-19 11:05:53 +000058 code1 { sqlite3 db test.db }
59 code2 { sqlite3 db test.db }
60
61 uplevel $script
62
63 catch { code1 { db close } }
64 catch { code2 { db close } }
dana35dafc2010-08-19 15:11:34 +000065 catch { close $::bc_chan2 }
66 catch { close $::bc_chan1 }
dan8311c472010-08-19 11:05:53 +000067}
68
69array set ::incompatible [list]
70proc do_allbackcompat_test {script} {
71
dan74f47e12012-03-21 14:34:23 +000072 foreach bin $::BC(binaries) {
dan8311c472010-08-19 11:05:53 +000073 set nErr [set_test_counter errors]
74 foreach dir {0 1} {
75
danfc5026d2010-08-19 15:48:47 +000076 set bintag [string map {testfixture {}} $bin]
shaneh5ad723f2010-08-19 18:05:46 +000077 set bintag [string map {\.exe {}} $bintag]
danfc5026d2010-08-19 15:48:47 +000078 if {$bintag == ""} {set bintag self}
79 set ::bcname ".$bintag.$dir."
dan8311c472010-08-19 11:05:53 +000080
81 rename do_test _do_test
82 proc do_test {nm sql res} {
83 set nm [regsub {\.} $nm $::bcname]
84 uplevel [list _do_test $nm $sql $res]
85 }
86
dana35dafc2010-08-19 15:11:34 +000087 do_backcompat_test $dir {} $bin $script
dan8311c472010-08-19 11:05:53 +000088
89 rename do_test {}
90 rename _do_test do_test
91 }
92 if { $nErr < [set_test_counter errors] } {
93 set ::incompatible([get_version $bin]) 1
94 }
95 }
96}
97
98proc read_file {zFile} {
99 set zData {}
dan9ab7fe82010-08-19 17:16:11 +0000100 if {[file exists $zFile]} {
dan8311c472010-08-19 11:05:53 +0000101 set fd [open $zFile]
102 fconfigure $fd -translation binary -encoding binary
dan9ab7fe82010-08-19 17:16:11 +0000103
104 if {[file size $zFile]<=$::sqlite_pending_byte || $zFile != "test.db"} {
105 set zData [read $fd]
106 } else {
107 set zData [read $fd $::sqlite_pending_byte]
108 append zData [string repeat x 512]
109 seek $fd [expr $::sqlite_pending_byte+512] start
110 append zData [read $fd]
111 }
112
dan8311c472010-08-19 11:05:53 +0000113 close $fd
114 }
115 return $zData
116}
117proc write_file {zFile zData} {
118 set fd [open $zFile w]
119 fconfigure $fd -translation binary -encoding binary
120 puts -nonewline $fd $zData
121 close $fd
122}
123proc read_file_system {} {
124 set ret [list]
125 foreach f {test.db test.db-journal test.db-wal} { lappend ret [read_file $f] }
126 set ret
127}
128proc write_file_system {data} {
129 foreach f {test.db test.db-journal test.db-wal} d $data {
130 if {[string length $d] == 0} {
mistachkinfda06be2011-08-02 00:57:34 +0000131 forcedelete $f
dan8311c472010-08-19 11:05:53 +0000132 } else {
133 write_file $f $d
134 }
135 }
136}
137
138#-------------------------------------------------------------------------
139# Actual tests begin here.
140#
danfc5026d2010-08-19 15:48:47 +0000141# This first block of tests checks to see that the same database and
142# journal files can be used by old and new versions. WAL and wal-index
143# files are tested separately below.
144#
dan8311c472010-08-19 11:05:53 +0000145do_allbackcompat_test {
146
147 # Test that database files are backwards compatible.
148 #
149 do_test backcompat-1.1.1 { sql1 {
150 CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
151 INSERT INTO t1 VALUES('abc', 'def');
152 } } {}
153 do_test backcompat-1.1.2 { sql2 { SELECT * FROM t1; } } {abc def}
154 do_test backcompat-1.1.3 { sql2 { INSERT INTO t1 VALUES('ghi', 'jkl'); } } {}
155 do_test backcompat-1.1.4 { sql1 { SELECT * FROM t1; } } {abc def ghi jkl}
156 do_test backcompat-1.1.5 { sql1 { PRAGMA integrity_check } } {ok}
157 do_test backcompat-1.1.6 { sql2 { PRAGMA integrity_check } } {ok}
158
159 # Test that one version can roll back a hot-journal file left in the
160 # file-system by the other version.
161 #
dana35dafc2010-08-19 15:11:34 +0000162 # Each test case is named "backcompat-1.X...", where X is either 0 or
163 # 1. If it is 0, then the current version creates a journal file that
164 # the old versions try to read. Otherwise, if X is 1, then the old version
165 # creates the journal file and we try to read it with the current version.
166 #
dan8311c472010-08-19 11:05:53 +0000167 do_test backcompat-1.2.1 { sql1 {
168 PRAGMA cache_size = 10;
169 BEGIN;
170 INSERT INTO t1 VALUES(randomblob(400), randomblob(400));
171 INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
172 INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
173 INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
174 INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
175 COMMIT;
176 } } {}
177 set cksum1 [sql1 {SELECT md5sum(a), md5sum(b) FROM t1}]
178 set cksum2 [sql2 {SELECT md5sum(a), md5sum(b) FROM t1}]
179 do_test backcompat-1.2.2 [list string compare $cksum1 $cksum2] 0
180
181 do_test backcompat-1.2.3 { sql1 {
182 BEGIN;
183 UPDATE t1 SET a = randomblob(500);
184 } } {}
185 set data [read_file_system]
dana35dafc2010-08-19 15:11:34 +0000186
dan8311c472010-08-19 11:05:53 +0000187 do_test backcompat-1.2.4 { sql1 { COMMIT } } {}
188
189 set same [expr {[sql2 {SELECT md5sum(a), md5sum(b) FROM t1}] == $cksum2}]
190 do_test backcompat-1.2.5 [list set {} $same] 0
191
dana35dafc2010-08-19 15:11:34 +0000192 code1 { db close }
193 code2 { db close }
dan8311c472010-08-19 11:05:53 +0000194 write_file_system $data
dana35dafc2010-08-19 15:11:34 +0000195 code1 { sqlite3 db test.db }
196 code2 { sqlite3 db test.db }
197
dan8311c472010-08-19 11:05:53 +0000198 set same [expr {[sql2 {SELECT md5sum(a), md5sum(b) FROM t1}] == $cksum2}]
199 do_test backcompat-1.2.6 [list set {} $same] 1
200
dana35dafc2010-08-19 15:11:34 +0000201 do_test backcompat-1.2.7 { sql1 { PRAGMA integrity_check } } {ok}
dan8311c472010-08-19 11:05:53 +0000202 do_test backcompat-1.2.8 { sql2 { PRAGMA integrity_check } } {ok}
203}
dan8311c472010-08-19 11:05:53 +0000204foreach k [lsort [array names ::incompatible]] {
danfc5026d2010-08-19 15:48:47 +0000205 puts "ERROR: Detected journal incompatibility with version $k"
206}
207unset ::incompatible
208
209
210#-------------------------------------------------------------------------
211# Test that WAL and wal-index files may be shared between different
212# SQLite versions.
213#
214do_allbackcompat_test {
215 if {[code1 {sqlite3 -version}] >= "3.7.0"
216 && [code2 {sqlite3 -version}] >= "3.7.0"
217 } {
218
219 do_test backcompat-2.1.1 { sql1 {
220 PRAGMA journal_mode = WAL;
221 CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
222 INSERT INTO t1 VALUES('I', 1);
223 INSERT INTO t1 VALUES('II', 2);
224 INSERT INTO t1 VALUES('III', 3);
225 SELECT * FROM t1;
226 } } {wal I 1 II 2 III 3}
227 do_test backcompat-2.1.2 { sql2 {
228 SELECT * FROM t1;
229 } } {I 1 II 2 III 3}
230
231 set data [read_file_system]
232 code1 {db close}
233 code2 {db close}
234 write_file_system $data
235 code1 {sqlite3 db test.db}
236 code2 {sqlite3 db test.db}
237
238 # The WAL file now in the file-system was created by the [code1]
239 # process. Check that the [code2] process can recover the log.
240 #
241 do_test backcompat-2.1.3 { sql2 {
242 SELECT * FROM t1;
243 } } {I 1 II 2 III 3}
244 do_test backcompat-2.1.4 { sql1 {
245 SELECT * FROM t1;
246 } } {I 1 II 2 III 3}
247 }
dan8311c472010-08-19 11:05:53 +0000248}
249
danc99415d2010-12-03 15:04:26 +0000250#-------------------------------------------------------------------------
251# Test that FTS3 tables may be read/written by different versions of
252# SQLite.
253#
dan5cfed522012-05-10 17:43:14 +0000254ifcapable fts3 {
255 set contents {
256 CREATE VIRTUAL TABLE t1 USING fts3(a, b);
257 }
258 foreach {num doc} {
259 one "jk zm jk eczkjblu urvysbnykk sk gnl jk ttvgf hmjf"
260 two "jk bnhc jjrxpjkb mjpavjuhw fibokdry igju jk zm zm xh"
261 three "wxe ogttbykvt uhzq xr iaf zf urvysbnykk aayxpmve oacaxgjoo mjpavjuhw"
262 four "gazrt jk ephknonq myjp uenvbm wuvajhwqz jk zm xnxhf nvfasfh"
263 five "zm aayxpmve csjqxhgj xnxhf xr jk aayxpmve xnxhf zm zm"
264 six "sokcyf zm ogyavjvv jk zm fibokdry zm jk igju igju"
265 seven "vgsld bvgimjik xuprtlyle jk akmikrqyt jk aayxpmve hkfoudzftq ddjj"
266 eight "zm uhzq ovkyevlgv zk uenvbm csjqxhgj jk vgsld pgybs jk"
267 nine "zm agmckuiu zexh fibokdry jk uhzq bu tugflixoex xnxhf sk"
danc99415d2010-12-03 15:04:26 +0000268 } {
dan5cfed522012-05-10 17:43:14 +0000269 append contents "INSERT INTO t1 VALUES('$num', '$doc');"
270 }
271 do_allbackcompat_test {
272 if {[code1 {set ::sqlite_options(fts3)}]
273 && [code2 {set ::sqlite_options(fts3)}]
danc99415d2010-12-03 15:04:26 +0000274 } {
dan5cfed522012-05-10 17:43:14 +0000275
276 do_test backcompat-3.1 { sql1 $contents } {}
277
278 foreach {n q} {
279 1 "SELECT * FROM t1 ORDER BY a, b"
280 2 "SELECT rowid FROM t1 WHERE a MATCH 'five'"
281 3 "SELECT * FROM t1 WHERE a MATCH 'five'"
282 4 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'jk'"
283 5 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'tug* OR eight'"
284 } {
285 do_test backcompat-3.2 [list sql1 $q] [sql2 $q]
286 }
287
288 do_test backcompat-3.3 { sql1 {
289 INSERT INTO t1 SELECT * FROM t1;
290 INSERT INTO t1 SELECT * FROM t1;
291 INSERT INTO t1 SELECT * FROM t1;
292 INSERT INTO t1 SELECT * FROM t1;
293 INSERT INTO t1 SELECT * FROM t1;
294 INSERT INTO t1 SELECT * FROM t1;
295 INSERT INTO t1 SELECT * FROM t1;
296 INSERT INTO t1 SELECT * FROM t1;
297 } } {}
298
299 foreach {n q} {
300 1 "SELECT * FROM t1 ORDER BY a, b"
301 2 "SELECT rowid FROM t1 WHERE a MATCH 'five'"
302 3 "SELECT * FROM t1 WHERE a MATCH 'five'"
303 4 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'jk'"
304 5 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'tug* OR eight'"
305 } {
306 do_test backcompat-3.4 [list sql1 $q] [sql2 $q]
307 }
308
309 set alphabet "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4"
310 for {set i 0} {$i < 900} {incr i} {
311 set term "[lindex $alphabet [expr $i/30]][lindex $alphabet [expr $i%30]] "
312 sql1 "INSERT INTO t1 VALUES($i, '[string repeat $term 14]')"
313 }
314
315 foreach {n q} {
316 1 "SELECT * FROM t1 ORDER BY a, b"
317 2 "SELECT rowid FROM t1 WHERE a MATCH 'five'"
318 3 "SELECT * FROM t1 WHERE a MATCH 'five'"
319 4 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'jk'"
320 5 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'tug* OR eight'"
321
322 6 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'aa'"
323 7 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH '44'"
324 8 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'a*'"
325 } {
326 do_test backcompat-3.5 [list sql1 $q] [sql2 $q]
327 }
328
329 do_test backcompat-3.6 {
330 sql1 "SELECT optimize(t1) FROM t1 LIMIT 1"
331 } {{Index optimized}}
332
333 foreach {n q} {
334 1 "SELECT * FROM t1 ORDER BY a, b"
335 2 "SELECT rowid FROM t1 WHERE a MATCH 'five'"
336 3 "SELECT * FROM t1 WHERE a MATCH 'five'"
337 4 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'jk'"
338 5 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'tug* OR eight'"
339
340 6 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'aa'"
341 7 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH '44'"
342 8 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'a*'"
343 } {
344 do_test backcompat-3.7 [list sql1 $q] [sql2 $q]
345 }
danc99415d2010-12-03 15:04:26 +0000346 }
347 }
348}
349
dan1c152102011-04-08 18:47:24 +0000350#-------------------------------------------------------------------------
351# Test that Rtree tables may be read/written by different versions of
352# SQLite.
353#
dan5cfed522012-05-10 17:43:14 +0000354ifcapable rtree {
355 set contents {
356 CREATE VIRTUAL TABLE t1 USING rtree(id, x1, x2, y1, y2);
357 }
358 foreach {id x1 x2 y1 y2} {
359 1 -47.64 43.87 33.86 34.42 2 -21.51 17.32 2.05 31.04
360 3 -43.67 -38.33 -19.79 3.43 4 32.41 35.16 9.12 19.82
361 5 33.28 34.87 14.78 28.26 6 49.31 116.59 -9.87 75.09
362 7 -14.93 34.51 -17.64 64.09 8 -43.05 23.43 -1.19 69.44
363 9 44.79 133.56 28.09 80.30 10 -2.66 81.47 -41.38 -10.46
364 11 -42.89 -3.54 15.76 71.63 12 -3.50 84.96 -11.64 64.95
365 13 -45.69 26.25 11.14 55.06 14 -44.09 11.23 17.52 44.45
366 15 36.23 133.49 -19.38 53.67 16 -17.89 81.54 14.64 50.61
367 17 -41.97 -24.04 -39.43 28.95 18 -5.85 7.76 -6.38 47.02
368 19 18.82 27.10 42.82 100.09 20 39.17 113.45 26.14 73.47
369 21 22.31 103.17 49.92 106.05 22 -43.06 40.38 -1.75 76.08
370 23 2.43 57.27 -14.19 -3.83 24 -47.57 -4.35 8.93 100.06
371 25 -37.47 49.14 -29.11 8.81 26 -7.86 75.72 49.34 107.42
372 27 1.53 45.49 20.36 49.74 28 -48.48 32.54 28.81 54.45
373 29 2.67 39.77 -4.05 13.67 30 4.11 62.88 -47.44 -5.72
374 31 -21.47 51.75 37.25 116.09 32 45.59 111.37 -6.43 43.64
375 33 35.23 48.29 23.54 113.33 34 16.61 68.35 -14.69 65.97
376 35 13.98 16.60 48.66 102.87 36 19.74 23.84 31.15 77.27
377 37 -27.61 24.43 7.96 94.91 38 -34.77 12.05 -22.60 -6.29
378 39 -25.83 8.71 -13.48 -12.53 40 -17.11 -1.01 18.06 67.89
379 41 14.13 71.72 -3.78 39.25 42 23.75 76.00 -16.30 8.23
380 43 -39.15 28.63 38.12 125.88 44 48.62 86.09 36.49 102.95
381 45 -31.39 -21.98 2.52 89.78 46 5.65 56.04 15.94 89.10
382 47 18.28 95.81 46.46 143.08 48 30.93 102.82 -20.08 37.36
383 49 -20.78 -3.48 -5.58 35.46 50 49.85 90.58 -24.48 46.29
dan1c152102011-04-08 18:47:24 +0000384 } {
dan5cfed522012-05-10 17:43:14 +0000385 if {$x1 >= $x2 || $y1 >= $y2} { error "$x1 $x2 $y1 $y2" }
386 append contents "INSERT INTO t1 VALUES($id, $x1, $x2, $y1, $y2);"
387 }
388 set queries {
389 1 "SELECT id FROM t1 WHERE x1>10 AND x2<44"
390 2 "SELECT id FROM t1 WHERE y1<100"
391 3 "SELECT id FROM t1 WHERE y1<100 AND x1>0"
392 4 "SELECT id FROM t1 WHERE y1>10 AND x1>0 AND x2<50 AND y2<550"
393 }
394 do_allbackcompat_test {
395 if {[code1 {set ::sqlite_options(fts3)}]
396 && [code2 {set ::sqlite_options(fts3)}]
397 } {
398
399 do_test backcompat-4.1 { sql1 $contents } {}
400
401 foreach {n q} $::queries {
402 do_test backcompat-4.2.$n [list sql1 $q] [sql2 $q]
403 }
404
405 do_test backcompat-4.3 { sql1 {
406 INSERT INTO t1 SELECT id+100, x1+10.0, x2+10.0, y1-10.0, y2-10.0 FROM t1;
407 } } {}
408
409 foreach {n q} $::queries {
410 do_test backcompat-4.4.$n [list sql1 $q] [sql2 $q]
411 }
412
413 do_test backcompat-4.5 { sql2 {
414 INSERT INTO t1 SELECT id+200, x1+20.0, x2+20.0, y1-20.0, y2-20.0 FROM t1;
415 } } {}
416
417 foreach {n q} $::queries {
418 do_test backcompat-4.6.$n [list sql1 $q] [sql2 $q]
419 }
420
dan1c152102011-04-08 18:47:24 +0000421 }
dan1c152102011-04-08 18:47:24 +0000422 }
423}
424
dan8311c472010-08-19 11:05:53 +0000425finish_test