Roll src/third_party/WebKit a3b4a2e:7441784 (svn 202551:202552)
[chromium-blink-merge.git] / third_party / sqlite / src / test / mmap1.test
blobece3e0201ed2aceb86cfc48e0adf7d9266a8c4bc
1 # 2013 March 20
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
13 set testdir [file dirname $argv0]
14 source $testdir/tester.tcl
15 ifcapable !mmap {
16   finish_test
17   return
19 source $testdir/lock_common.tcl
20 set testprefix mmap1
22 proc nRead {db} {
23   set bt [btree_from_db $db]
24   db_enter $db
25   array set stats [btree_pager_stats $bt]
26   db_leave $db
27   # puts [array get stats]
28   return $stats(read)
31 proc register_rblob_code {dbname seed} {
32   return [subst -nocommands {
33     set ::rcnt $seed
34     proc rblob {n} {
35       set ::rcnt [expr (([set ::rcnt] << 3) + [set ::rcnt] + 456) & 0xFFFFFFFF]
36       set str [format %.8x [expr [set ::rcnt] ^ 0xbdf20da3]] 
37       string range [string repeat [set str] [expr [set n]/4]] 1 [set n]
38     }
39     $dbname func rblob rblob
40   }]
43 # For cases 1.1 and 1.4, the number of pages read using xRead() is 4 on
44 # unix and 9 on windows. The difference is that windows only ever maps
45 # an integer number of OS pages (i.e. creates mappings that are a multiple 
46 # of 4KB in size). Whereas on unix any sized mapping may be created.
48 foreach {t mmap_size nRead c2init} {
49   1.1 { PRAGMA mmap_size = 67108864 } /[49]/ {PRAGMA mmap_size = 0}
50   1.2 { PRAGMA mmap_size =    53248 } 150    {PRAGMA mmap_size = 0}
51   1.3 { PRAGMA mmap_size =        0 } 344    {PRAGMA mmap_size = 0}
52   1.4 { PRAGMA mmap_size = 67108864 } /[49]/ {PRAGMA mmap_size = 67108864 }
53   1.5 { PRAGMA mmap_size =    53248 } 150    {PRAGMA mmap_size = 67108864 }
54   1.6 { PRAGMA mmap_size =        0 } 344    {PRAGMA mmap_size = 67108864 }
55 } {
57   do_multiclient_test tn {
58     sql1 {PRAGMA cache_size=2000}
59     sql2 {PRAGMA cache_size=2000}
61     sql1 {PRAGMA page_size=1024}
62     sql1 $mmap_size
63     sql2 $c2init
65     code2 [register_rblob_code db2 0]
67     sql2 {
68       PRAGMA page_size=1024;
69       PRAGMA auto_vacuum = 1;
70       CREATE TABLE t1(a, b, UNIQUE(a, b));
71       INSERT INTO t1 VALUES(rblob(500), rblob(500));
72       INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    2
73       INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    4
74       INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    8
75       INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --   16
76       INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --   32
77     }
78     do_test $t.$tn.1 {
79       sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
80     } {32 ok 77}
82     # Have connection 2 shrink the file. Check connection 1 can still read it.
83     sql2 { DELETE FROM t1 WHERE rowid%2; }
84     do_test $t.$tn.2 {
85       sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
86     } {16 ok 42}
88     # Have connection 2 grow the file. Check connection 1 can still read it.
89     sql2 { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1 }
90     do_test $t.$tn.3 {
91       sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
92     } {32 ok 79}
94     # Have connection 2 grow the file again. Check connection 1 is still ok.
95     sql2 { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1 }
96     do_test $t.$tn.4 {
97       sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
98     } {64 ok 149}
100     # Check that the number of pages read by connection 1 indicates that the
101     # "PRAGMA mmap_size" command worked.
102     do_test $t.$tn.5 { nRead db } $nRead
103   }
106 set ::rcnt 0
107 proc rblob {n} {
108   set ::rcnt [expr (($::rcnt << 3) + $::rcnt + 456) & 0xFFFFFFFF]
109   set str [format %.8x [expr $::rcnt ^ 0xbdf20da3]] 
110   string range [string repeat $str [expr $n/4]] 1 $n
113 reset_db
114 db func rblob rblob
116 do_execsql_test 2.1 {
117   PRAGMA auto_vacuum = 1;
118   PRAGMA mmap_size = 67108864;
119   PRAGMA journal_mode = wal;
120   CREATE TABLE t1(a, b, UNIQUE(a, b));
121   INSERT INTO t1 VALUES(rblob(500), rblob(500));
122   INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    2
123   INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    4
124   INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    8
125   INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --   16
126   INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --   32
127   PRAGMA wal_checkpoint;
128 } {67108864 wal 0 103 103}
130 do_execsql_test 2.2 {
131   PRAGMA auto_vacuum;
132   SELECT count(*) FROM t1;
133 } {1 32}
135 if {[permutation] != "inmemory_journal"} {
136   do_test 2.3 {
137     sqlite3 db2 test.db
138     db2 func rblob rblob
139     db2 eval { 
140       DELETE FROM t1 WHERE (rowid%4);
141         PRAGMA wal_checkpoint;
142     }
143     db2 eval { 
144       INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    16
145       SELECT count(*) FROM t1;
146     }
147   } {16}
149   do_execsql_test 2.4 {
150     PRAGMA wal_checkpoint;
151   } {0 24 24}
152   db2 close
155 reset_db
156 execsql { PRAGMA mmap_size = 67108864; }
157 db func rblob rblob
158 do_execsql_test 3.1 {
159   PRAGMA auto_vacuum = 1;
161   CREATE TABLE t1(a, b, UNIQUE(a, b));
162   INSERT INTO t1 VALUES(rblob(500), rblob(500));
163   INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    2
164   INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    4
165   INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    8
167   CREATE TABLE t2(a, b, UNIQUE(a, b));
168   INSERT INTO t2 SELECT * FROM t1;
169 } {}
171 do_test 3.2 {
172   set nRow 0
173   db eval {SELECT * FROM t2 ORDER BY a, b} {
174     if {$nRow==4} { db eval { DELETE FROM t1 } }
175     incr nRow
176   }
177   set nRow
178 } {8}
180 #-------------------------------------------------------------------------
181 # Ensure that existing cursors using xFetch() pages see changes made
182 # to rows using the incrblob API.
184 reset_db
185 execsql { PRAGMA mmap_size = 67108864; }
186 set aaa [string repeat a 400]
187 set bbb [string repeat b 400]
188 set ccc [string repeat c 400]
189 set ddd [string repeat d 400]
190 set eee [string repeat e 400]
192 do_execsql_test 4.1 {
193   PRAGMA page_size = 1024;
194   CREATE TABLE t1(x);
195   INSERT INTO t1 VALUES($aaa);
196   INSERT INTO t1 VALUES($bbb);
197   INSERT INTO t1 VALUES($ccc);
198   INSERT INTO t1 VALUES($ddd);
199   SELECT * FROM t1;
200   BEGIN;
201 } [list $aaa $bbb $ccc $ddd]
203 do_test 4.2 {
204   set ::STMT [sqlite3_prepare db "SELECT * FROM t1 ORDER BY rowid" -1 dummy]
205   sqlite3_step $::STMT
206   sqlite3_column_text $::STMT 0
207 } $aaa
209 do_test 4.3 {
210   foreach r {2 3 4} {
211     set fd [db incrblob t1 x $r]
212     puts -nonewline $fd $eee
213     close $fd
214   }
216   set res [list]
217   while {"SQLITE_ROW" == [sqlite3_step $::STMT]} {
218     lappend res [sqlite3_column_text $::STMT 0]
219   }
220   set res
221 } [list $eee $eee $eee]
223 do_test 4.4 {
224   sqlite3_finalize $::STMT
225 } SQLITE_OK
227 do_execsql_test 4.5 { COMMIT }
229 #-------------------------------------------------------------------------
230 # Ensure that existing cursors holding xFetch() references are not 
231 # confused if those pages are moved to make way for the root page of a
232 # new table or index.
234 reset_db
235 execsql { PRAGMA mmap_size = 67108864; }
236 do_execsql_test 5.1 {
237   PRAGMA auto_vacuum = 2;
238   PRAGMA page_size = 1024;
239   CREATE TABLE t1(x);
240   INSERT INTO t1 VALUES($aaa);
241   INSERT INTO t1 VALUES($bbb);
242   INSERT INTO t1 VALUES($ccc);
243   INSERT INTO t1 VALUES($ddd);
245   PRAGMA auto_vacuum;
246   SELECT * FROM t1;
247 } [list 2 $aaa $bbb $ccc $ddd]
249 do_test 5.2 {
250   set ::STMT [sqlite3_prepare db "SELECT * FROM t1 ORDER BY rowid" -1 dummy]
251   sqlite3_step $::STMT
252   sqlite3_column_text $::STMT 0
253 } $aaa
255 do_execsql_test 5.3 {
256   CREATE TABLE t2(x);
257   INSERT INTO t2 VALUES('tricked you!');
258   INSERT INTO t2 VALUES('tricked you!');
261 do_test 5.4 {
262   sqlite3_step $::STMT
263   sqlite3_column_text $::STMT 0
264 } $bbb
266 do_test 5.5 {
267   sqlite3_finalize $::STMT
268 } SQLITE_OK
270 #-------------------------------------------------------------------------
271 # Test various mmap_size settings.
273 foreach {tn1 mmap1 mmap2} {
274      1 6144       167773
275      2 18432      140399
276      3 43008      401302
277      4 92160      253899
278      5 190464          2
279      6 387072     752431
280      7 780288     291143
281      8 1566720    594306
282      9 3139584    829137
283      10 6285312   793963
284      11 12576768 1015590
285 } {
286   do_multiclient_test tn {
287     sql1 {
288       CREATE TABLE t1(a PRIMARY KEY);
289       CREATE TABLE t2(x);
290       INSERT INTO t2 VALUES('');
291     }
293     code1 [register_rblob_code db  0]
294     code2 [register_rblob_code db2 444]
296     sql1 "PRAGMA mmap_size = $mmap1"
297     sql2 "PRAGMA mmap_size = $mmap2"
299     do_test $tn1.$tn { 
300       for {set i 1} {$i <= 100} {incr i} {
301         if {$i % 2} {
302           set c1 sql1
303             set c2 sql2
304         } else {
305           set c1 sql2
306             set c2 sql1
307         }
309         $c1 {
310           INSERT INTO t1 VALUES( rblob(5000) );
311           UPDATE t2 SET x = (SELECT md5sum(a) FROM t1);
312         }
314         set res [$c2 { 
315             SELECT count(*) FROM t1;
316             SELECT x == (SELECT md5sum(a) FROM t1) FROM t2;
317             PRAGMA integrity_check;
318         }]
319         if {$res != [list $i 1 ok]} {
320           do_test $tn1.$tn.$i {
321             set ::res
322           } [list $i 1 ok]
323         }
324       }
325       set res 1
326     } {1}
327   }
331 finish_test