- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / sqlite / src / test / exclusive2.test
1 # 2007 March 24
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.
12 #
13 # $Id: exclusive2.test,v 1.10 2008/11/27 02:22:11 drh Exp $
14
15 set testdir [file dirname $argv0]
16 source $testdir/tester.tcl
17
18 # Do not use a codec for tests in this file, as the database file is
19 # manipulated directly using tcl scripts (using the [hexio_write] command).
20 #
21 do_not_use_codec
22
23 ifcapable {!pager_pragmas} {
24   finish_test
25   return
26 }
27
28 # This module does not work right if the cache spills at unexpected
29 # moments.  So disable the soft-heap-limit.
30 #
31 sqlite3_soft_heap_limit 0
32
33 proc pagerChangeCounter {filename new {fd ""}} {
34   if {$fd==""} {
35     set fd [open $filename RDWR]
36     fconfigure $fd -translation binary -encoding binary
37     set needClose 1
38   } else {
39     set needClose 0
40   }
41   if {$new ne ""} {
42     seek $fd 24
43     set a [expr {($new&0xFF000000)>>24}]
44     set b [expr {($new&0x00FF0000)>>16}]
45     set c [expr {($new&0x0000FF00)>>8}]
46     set d [expr {($new&0x000000FF)}]
47     puts -nonewline $fd [binary format cccc $a $b $c $d]
48     flush $fd
49   }
50
51   seek $fd 24
52   foreach {a b c d} [list 0 0 0 0] {}
53   binary scan [read $fd 4] cccc a b c d
54   set  ret [expr ($a&0x000000FF)<<24]
55   incr ret [expr ($b&0x000000FF)<<16]
56   incr ret [expr ($c&0x000000FF)<<8]
57   incr ret [expr ($d&0x000000FF)<<0]
58
59   if {$needClose} {close $fd}
60   return $ret
61 }
62
63 proc readPagerChangeCounter {filename} {
64   set fd [open $filename RDONLY]
65   fconfigure $fd -translation binary -encoding binary
66
67   seek $fd 24
68   foreach {a b c d} [list 0 0 0 0] {}
69   binary scan [read $fd 4] cccc a b c d
70   set  ret [expr ($a&0x000000FF)<<24]
71   incr ret [expr ($b&0x000000FF)<<16]
72   incr ret [expr ($c&0x000000FF)<<8]
73   incr ret [expr ($d&0x000000FF)<<0]
74
75   close $fd
76   return $ret
77 }
78
79
80 proc t1sig {{db db}} {
81   execsql {SELECT count(*), md5sum(a) FROM t1} $db
82 }
83 do_test exclusive2-1.0 {
84   readPagerChangeCounter test.db
85 } {0}
86
87 #-----------------------------------------------------------------------
88 # The following tests - exclusive2-1.X - check that:
89 #
90 # 1-3:   Build a database with connection 1, calculate a signature.
91 # 4-7:   Modify the database using a second connection in a way that
92 #        does not modify the freelist, then reset the pager change-counter
93 #        to the value it had before the modifications.
94 # 8:     Check that using the first connection, the database signature
95 #        is still the same. This is because it uses the in-memory cache.
96 #        It can't tell the db has changed because we reset the change-counter.
97 # 9:     Increment the change-counter.
98 # 10:    Ensure that the first connection now sees the updated database. It
99 #        sees the change-counter has been incremented and discards the 
100 #        invalid in-memory cache.
101 #
102 # This will only work if the database cache is large enough to hold 
103 # the entire database. In the case of 1024 byte pages, this means
104 # the cache size must be at least 17. Otherwise, some pages will be
105 # loaded from the database file in step 8.
106 #
107 # For similar reasons, this test does not work with the memsubsys1 permutation.
108 # Permutation memsubsys1 configures the pcache subsystem to use a static
109 # allocation of 24 pages (shared between all pagers). This is not enough for
110 # this test.
111 #
112 do_test exclusive2-1.1 {
113   execsql {
114     BEGIN;
115     CREATE TABLE t1(a, b);
116     INSERT INTO t1(a) VALUES(randstr(10, 400));
117     INSERT INTO t1(a) VALUES(randstr(10, 400));
118     INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
119     INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
120     INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
121     INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
122     INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
123     COMMIT;
124     SELECT count(*) FROM t1;
125   }
126 } {64}
127 do_test exclusive2-1.2.1 {
128   # Make sure the pager cache is large enough to store the 
129   # entire database.
130   set nPage [expr [file size test.db]/1024]
131   if {$::SQLITE_DEFAULT_CACHE_SIZE < $nPage} {
132     execsql "PRAGMA cache_size = $nPage"
133   }
134   expr {[execsql {PRAGMA cache_size}] >= $nPage}
135 } {1}
136 do_test exclusive2-1.2 {
137   set ::sig [t1sig]
138   readPagerChangeCounter test.db
139 } {1}
140 do_test exclusive2-1.3 {
141   t1sig
142 } $::sig
143 do_test exclusive2-1.4 {
144   sqlite3 db2 test.db
145   t1sig db2
146 } $::sig
147 do_test exclusive2-1.5 {
148   execsql {
149     UPDATE t1 SET b=a, a=NULL;
150   } db2
151   expr {[t1sig db2] eq $::sig}
152 } 0
153 do_test exclusive2-1.6 {
154   readPagerChangeCounter test.db
155 } {2}
156 do_test exclusive2-1.7 {
157   pagerChangeCounter test.db 1
158 } {1}
159 if {[permutation] != "memsubsys1"} {
160   do_test exclusive2-1.9 {
161     t1sig
162     expr {[t1sig] eq $::sig}
163   } {1}
164 }
165 do_test exclusive2-1.10 {
166   pagerChangeCounter test.db 2
167 } {2}
168 do_test exclusive2-1.11 {
169   expr {[t1sig] eq $::sig}
170 } {0}
171 db2 close
172
173 #--------------------------------------------------------------------
174 # These tests - exclusive2-2.X - are similar to exclusive2-1.X, 
175 # except that they are run with locking_mode=EXCLUSIVE.
176 #
177 # 1-3:   Build a database with exclusive-access connection 1, 
178 #        calculate a signature.
179 # 4:     Corrupt the database by writing 10000 bytes of garbage
180 #        starting at the beginning of page 2. Check that connection 1
181 #        still works. It should be accessing the in-memory cache.
182 # 5-6:   Modify the dataase change-counter. Connection 1 still works
183 #        entirely from in-memory cache, because it doesn't check the
184 #        change-counter.
185 # 7-8    Set the locking-mode back to normal. After the db is unlocked,
186 #        SQLite detects the modified change-counter and discards the
187 #        in-memory cache. Then it finds the corruption caused in step 4....
188 #
189 # As above, this test is only applicable if the pager cache is
190 # large enough to hold the entire database. With 1024 byte pages,
191 # this means 19 pages.  We also need to disable the soft-heap-limit
192 # to prevent memory-induced cache spills.
193 #
194 do_test exclusive2-2.1 {
195   execsql {PRAGMA cache_size=1000;}
196   execsql {PRAGMA locking_mode = exclusive;}
197   execsql {
198     BEGIN;
199     DELETE FROM t1;
200     INSERT INTO t1(a) VALUES(randstr(10, 400));
201     INSERT INTO t1(a) VALUES(randstr(10, 400));
202     INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
203     INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
204     INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
205     INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
206     INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
207     COMMIT;
208     SELECT count(*) FROM t1;
209   }
210 } {64}
211 do_test exclusive2-2.2.1 {
212   # Make sure the pager cache is large enough to store the 
213   # entire database.
214   set nPage [expr [file size test.db]/1024]
215   if {$::SQLITE_DEFAULT_CACHE_SIZE < $nPage} {
216     execsql "PRAGMA cache_size = $nPage"
217   }
218   expr {[execsql {PRAGMA cache_size}] >= $nPage}
219 } {1}
220 do_test exclusive2-2.2 {
221   set ::sig [t1sig]
222   readPagerChangeCounter test.db
223 } {3}
224 do_test exclusive2-2.3 {
225   t1sig
226 } $::sig
227
228 do_test exclusive2-2.4 {
229   set ::fd [open test.db RDWR]
230   fconfigure $::fd -translation binary
231   seek $::fd 1024
232   puts -nonewline $::fd [string repeat [binary format c 0] 10000]
233   flush $::fd
234   t1sig
235 } $::sig
236
237 do_test exclusive2-2.5 {
238   pagerChangeCounter test.db 5 $::fd
239 } {5}
240 do_test exclusive2-2.6 {
241   t1sig
242 } $::sig
243 do_test exclusive2-2.7 {
244   execsql {PRAGMA locking_mode = normal}
245   t1sig
246 } $::sig
247
248 do_test exclusive2-2.8 {
249   set rc [catch {t1sig} msg]
250   list $rc $msg
251 } {1 {database disk image is malformed}}
252
253 #--------------------------------------------------------------------
254 # These tests - exclusive2-3.X - verify that the pager change-counter
255 # is only incremented by the first change when in exclusive access
256 # mode. In normal mode, the change-counter is incremented once
257 # per write-transaction.
258 #
259
260 db close
261 catch {close $::fd}
262 file delete -force test.db
263 file delete -force test.db-journal
264
265 do_test exclusive2-3.0 {
266   sqlite3 db test.db
267   execsql {
268     BEGIN;
269     CREATE TABLE t1(a UNIQUE);
270     INSERT INTO t1 VALUES(randstr(200, 200));
271     INSERT INTO t1 VALUES(randstr(200, 200));
272     COMMIT;
273   }
274   readPagerChangeCounter test.db
275 } {1}
276 do_test exclusive2-3.1 {
277   execsql {
278     INSERT INTO t1 VALUES(randstr(200, 200));
279   }
280   readPagerChangeCounter test.db
281 } {2}
282 do_test exclusive2-3.2 {
283   execsql {
284     INSERT INTO t1 VALUES(randstr(200, 200));
285   }
286   readPagerChangeCounter test.db
287 } {3}
288 do_test exclusive2-3.3 {
289   execsql {
290     PRAGMA locking_mode = exclusive;
291     INSERT INTO t1 VALUES(randstr(200, 200));
292   }
293   readPagerChangeCounter test.db
294 } {4}
295 do_test exclusive2-3.4 {
296 breakpoint
297   execsql {
298     INSERT INTO t1 VALUES(randstr(200, 200));
299   }
300   readPagerChangeCounter test.db
301 } {4}
302 do_test exclusive2-3.5 {
303   execsql {
304     PRAGMA locking_mode = normal;
305     INSERT INTO t1 VALUES(randstr(200, 200));
306   }
307   readPagerChangeCounter test.db
308 } {4}
309 do_test exclusive2-3.6 {
310   execsql {
311     INSERT INTO t1 VALUES(randstr(200, 200));
312   }
313   readPagerChangeCounter test.db
314 } {5}
315 sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
316
317 finish_test