guard against zero block size if provider initialization fails
[sqlcipher.git] / test / sqlcipher-rekey.test
blob2e6534e3da9181293a50eb1da2871b108a20a17b
1 # SQLCipher
2 # codec.test developed by Stephen Lombardo (Zetetic LLC)
3 # sjlombardo at zetetic dot net
4 # http://zetetic.net
6 # Copyright (c) 2018, ZETETIC LLC
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
9 #     * Redistributions of source code must retain the above copyright
10 #       notice, this list of conditions and the following disclaimer.
11 #     * Redistributions in binary form must reproduce the above copyright
12 #       notice, this list of conditions and the following disclaimer in the
13 #       documentation and/or other materials provided with the distribution.
14 #     * Neither the name of the ZETETIC LLC nor the
15 #       names of its contributors may be used to endorse or promote products
16 #       derived from this software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
19 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 # DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
22 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 # This file implements regression tests for SQLite library.  The
30 # focus of this script is testing code cipher features.
32 # NOTE: tester.tcl has overridden the definition of sqlite3 to
33 # automatically pass in a key value. Thus tests in this file
34 # should explicitly close and open db with sqlite_orig in order
35 # to bypass default key assignment.
37 set testdir [file dirname $argv0]
38 source $testdir/tester.tcl
39 source $testdir/sqlcipher.tcl
41 # Test rekey as first operation on an empty database. should be a no-op
42 do_test rekey-as-first-op {
43   sqlite_orig db test.db
45   execsql {
46     PRAGMA rekey = 'testkey';
47     CREATE table t1(a,b);
48     BEGIN;
49   }
51   for {set i 1} {$i<=100} {incr i} {
52     set r [expr {int(rand()*500000)}]
53     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
54   }
56   execsql {
57     COMMIT;
58   } 
60   db close
61   sqlite_orig db test.db
63   execsql {
64     PRAGMA rekey = 'testkey';
65     SELECT count(*) FROM t1;
66   }
68 } {ok 100}
69 db close
70 file delete -force test.db
72 # Test rekey as first operation follwed by key
73 do_test rekey-then-key-as-first-ops {
74   sqlite_orig db test.db
76   execsql {
77     PRAGMA rekey = '1234';
78     PRAGMA key = 'testkey';
79     CREATE table t1(a,b);
80     BEGIN;
81   }
83   for {set i 1} {$i<=100} {incr i} {
84     set r [expr {int(rand()*500000)}]
85     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
86   }
88   execsql {
89     COMMIT;
90   } 
92   db close
93   sqlite_orig db test.db
95   execsql {
96     PRAGMA rekey = '4321';
97     PRAGMA key = 'testkey';
98     SELECT count(*) FROM t1;
99   }
101 } {ok ok 100}
102 db close
103 file delete -force test.db
106 # test a rekey operation as the first op on a database
107 # then test that now the new key opens the database
108 # now close database re-open with new key
109 setup test.db "'testkey'"
110 do_test rekey-as-first-operation {
111   sqlite_orig db test.db
112   execsql {
113     PRAGMA key = 'testkey';
114     PRAGMA rekey = 'testkeynew';
115   }
116   db close
118   sqlite_orig db test.db
119   execsql {
120     PRAGMA key = 'testkeynew';
121     SELECT name FROM sqlite_schema WHERE type='table';
122   }
123 } {ok t1}
124 db close
125 file delete -force test.db
127 # create a new database, insert some data
128 # then rekey it with the same password
129 do_test rekey-same-passkey {
130   sqlite_orig db test.db
132   execsql {
133     PRAGMA key = 'test123';
134     CREATE TABLE t1(a,b);
135     BEGIN;
136   }
138   for {set i 1} {$i<=1000} {incr i} {
139     set r [expr {int(rand()*500000)}]
140     execsql "INSERT INTO t1 VALUES($i,'value $r');"
141   }
143   execsql {
144     COMMIT;
145     SELECT count(*) FROM t1;
146     PRAGMA rekey = 'test123';
147     SELECT count(*) FROM t1;
148   }
149 } {1000 ok 1000}
150 db close
151 file delete -force test.db
153 # create a new database, insert some data
154 # then rekey it. Make sure it is immediately
155 # readable. Then close it and make sure it can be
156 # read back 
157 do_test rekey-and-query-1 {
158   sqlite_orig db test.db
160   execsql {
161     PRAGMA key = 'test123';
162     CREATE TABLE t1(a,b);
163     BEGIN;
164   }
166   for {set i 1} {$i<=1000} {incr i} {
167     set r [expr {int(rand()*500000)}]
168     execsql "INSERT INTO t1 VALUES($i,'value $r');"
169   }
171   execsql {
172     COMMIT;
173     SELECT count(*) FROM t1;
174     PRAGMA rekey = 'test321';
175     SELECT count(*) FROM t1;
176   }
177 } {1000 ok 1000}
179 db close
181 do_test rekey-and-query-2 {
182   sqlite_orig db test.db
183   execsql {
184     PRAGMA key = 'test321';
185     SELECT count(*) FROM t1;
186   }
187 } {ok 1000}
188 db close
189 file delete -force test.db
191 # create a new database, insert some data
192 # delete about 50% of the data
193 # write some new data
194 # delete another 50%
195 # then rekey it. Make sure it is immediately
196 # readable. Then close it and make sure it can be
197 # read back. This test will ensure that Secure Delete
198 # is enabled and all pages are being written and are not
199 # being optimized out by sqlite3PagerDontWrite
200 do_test rekey-delete-and-query-1 {
201   sqlite_orig db test.db
203   execsql {
204     PRAGMA key = 'test123';
205     CREATE TABLE t1(a,b);
206     CREATE INDEX ta_a ON t1(a);
207     BEGIN;
208   }
210   for {set i 1} {$i<1000} {incr i} {
211     set r1 [expr {int(rand()*32767)}]
212     execsql "INSERT INTO t1 VALUES($i,$r1);"
213   }
215   execsql "DELETE FROM t1 WHERE a < 500;"
217   set r1 [expr {int(rand()*32767)}]
218   execsql "UPDATE t1 SET b = $r1 WHERE a < 750;"
220   execsql "DELETE FROM t1 WHERE a > 750;"
222   execsql {
223     COMMIT;
224     SELECT (count(*) > 0) FROM t1;
225   }
226 } {1}
227 db close
229 do_test rekey-delete-and-query-2 {
230   sqlite_orig db test.db
231   execsql {
232     PRAGMA key = 'test123';
233     PRAGMA rekey = 'test321';
234     SELECT count(*) > 1 FROM t1;
235     PRAGMA integrity_check;
236   }
237 } {ok ok 1 ok}
238 db close
240 do_test rekey-delete-and-query-3 {
241   sqlite_orig db test.db
242   execsql {
243     PRAGMA key = 'test321';
244     SELECT count(*) > 1 FROM t1;
245   }
246 } {ok 1}
247 db close
248 file delete -force test.db
251 # same as previous test, but use WAL
252 do_test rekey-delete-and-query-wal-1 {
253   sqlite_orig db test.db
255   execsql {
256     PRAGMA key = 'test123';
257     PRAGMA journal_mode = WAL;
258     CREATE TABLE t1(a,b);
259     CREATE INDEX ta_a ON t1(a);
260     BEGIN;
261   }
263   for {set i 1} {$i<1000} {incr i} {
264     set r1 [expr {int(rand()*32767)}]
265     execsql "INSERT INTO t1 VALUES($i,$r1);"
266   }
268   execsql "DELETE FROM t1 WHERE a < 500;"
270   set r1 [expr {int(rand()*32767)}]
271   execsql "UPDATE t1 SET b = $r1 WHERE a < 750;"
273   execsql "DELETE FROM t1 WHERE a > 750;"
275   execsql {
276     COMMIT;
277     SELECT (count(*) > 0) FROM t1;
278   }
279 } {1}
280 db close
282 do_test rekey-delete-and-query-wal-2 {
283   sqlite_orig db test.db
284   execsql {
285     PRAGMA key = 'test123';
286     PRAGMA journal_mode = WAL;
287     PRAGMA rekey = 'test321';
288     SELECT count(*) > 1 FROM t1;
289     PRAGMA integrity_check;
290   }
291 } {ok wal ok 1 ok}
292 db close
294 do_test rekey-delete-and-query-wal-3 {
295   sqlite_orig db test.db
296   execsql {
297     PRAGMA key = 'test321';
298     PRAGMA journal_mode = WAL;
299     SELECT count(*) > 1 FROM t1;
300   }
301 } {ok wal 1}
302 db close
303 file delete -force test.db
305 do_test rekey-database-by-name {
306     sqlite_orig db test.db
307     execsql {
308         attach database 'new.db' as new;
309         pragma new.key = 'foo';
310         create table new.t1(a,b);
311         insert into new.t1(a,b) values('foo', 'bar');
312         pragma new.rekey = 'bar';
313         detach database new;
314     }
315     db close
317     sqlite_orig db new.db
318     execsql {
319         pragma key = 'bar';
320         select * from t1;
321     }
322 } {ok foo bar}
323 db close
324 file delete -force test.db
325 file delete -force new.db
327 finish_test