1# 2016 March 31
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# The focus of this file is testing the session module.
13#
14
15if {![info exists testdir]} {
16  set testdir [file join [file dirname [info script]] .. .. test]
17}
18source [file join [file dirname [info script]] session_common.tcl]
19source $testdir/tester.tcl
20ifcapable !session {finish_test; return}
21set testprefix sessionfault2
22
23if 1 {
24
25do_execsql_test 1.0.0 {
26  CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
27  INSERT INTO t1 VALUES(1, 1);
28  INSERT INTO t1 VALUES(2, 2);
29  INSERT INTO t1 VALUES(3, 3);
30
31  CREATE TABLE t2(a PRIMARY KEY, b UNIQUE);
32  INSERT INTO t2 VALUES(1, 1);
33  INSERT INTO t2 VALUES(2, 2);
34  INSERT INTO t2 VALUES(3, 3);
35}
36faultsim_save_and_close
37
38faultsim_restore_and_reopen
39do_test 1.0.1 {
40  set ::C [changeset_from_sql {
41    UPDATE t1 SET b=4 WHERE a=3;
42    UPDATE t1 SET b=3 WHERE a=2;
43    UPDATE t1 SET b=2 WHERE a=1;
44    UPDATE t2 SET b=0 WHERE a=1;
45    UPDATE t2 SET b=1 WHERE a=2;
46    UPDATE t2 SET b=2 WHERE a=3;
47  }]
48  set {} {}
49} {}
50
51proc xConflict args { return "OMIT" }
52
53do_faultsim_test 1 -faults oom-p* -prep {
54  faultsim_restore_and_reopen
55} -body {
56  sqlite3changeset_apply db $::C xConflict
57} -test {
58  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
59  faultsim_integrity_check
60
61  catch { db eval ROLLBACK }
62  set res [db eval {
63    SELECT * FROM t1;
64    SELECT * FROM t2;
65  }]
66
67  if {$testrc==0} {
68    if {$res != "1 2 2 3 3 4 1 0 2 1 3 2"} { error "data error" }
69  } else {
70    if {
71         $res != "1 2 2 3 3 4 1 0 2 1 3 2"
72      && $res != "1 1 2 2 3 3 1 1 2 2 3 3"
73    } { error "data error!! $res" }
74  }
75}
76
77#-------------------------------------------------------------------------
78# OOM when applying a changeset for which one of the tables has a name
79# 99 bytes in size. This happens to cause an extra malloc in within the
80# sessions_strm permutation.
81#
82reset_db
83set nm [string repeat t 99]
84do_execsql_test 2.0.0 [string map "%TBL% $nm" {
85  CREATE TABLE %TBL%(a PRIMARY KEY, b UNIQUE);
86}]
87faultsim_save_and_close
88
89faultsim_restore_and_reopen
90do_test 1.0.1 {
91  set ::C [changeset_from_sql [string map "%TBL% $nm" {
92    INSERT INTO %TBL% VALUES(1, 2);
93    INSERT INTO %TBL% VALUES(3, 4);
94  }]]
95  set {} {}
96} {}
97
98proc xConflict args { return "OMIT" }
99do_faultsim_test 2 -faults oom-p* -prep {
100  faultsim_restore_and_reopen
101} -body {
102  sqlite3changeset_apply db $::C xConflict
103} -test {
104  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
105  faultsim_integrity_check
106}
107
108#-------------------------------------------------------------------------
109# OOM when collecting and apply a changeset that uses sqlite_stat1.
110#
111reset_db
112forcedelete test.db2
113sqlite3 db2 test.db2
114do_common_sql {
115  CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c);
116  CREATE INDEX i1 ON t1(c);
117  INSERT INTO t1 VALUES(1, 2, 3);
118  INSERT INTO t1 VALUES(4, 5, 6);
119  INSERT INTO t1 VALUES(7, 8, 9);
120  CREATE TABLE t2(a, b, c);
121  INSERT INTO t2 VALUES(1, 2, 3);
122  INSERT INTO t2 VALUES(4, 5, 6);
123  INSERT INTO t2 VALUES(7, 8, 9);
124  ANALYZE;
125}
126faultsim_save_and_close
127db2 close
128
129do_faultsim_test 1.1 -faults oom-* -prep {
130  catch {db2 close}
131  catch {db close}
132  faultsim_restore_and_reopen
133  sqlite3 db2 test.db2
134} -body {
135  do_then_apply_sql {
136    INSERT INTO sqlite_stat1 VALUES('x', 'y', 45);
137    UPDATE sqlite_stat1 SET stat = 123 WHERE tbl='t1' AND idx='i1';
138    UPDATE sqlite_stat1 SET stat = 456 WHERE tbl='t2';
139  }
140} -test {
141  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
142  faultsim_integrity_check
143  if {$testrc==0} { compare_db db db2 }
144}
145
146#-------------------------------------------------------------------------
147# OOM when collecting and using a rebase changeset.
148#
149reset_db
150do_execsql_test 2.0 {
151  CREATE TABLE t3(a, b, c, PRIMARY KEY(b, c));
152  CREATE TABLE t4(x PRIMARY KEY, y, z);
153
154  INSERT INTO t3 VALUES(1, 2, 3);
155  INSERT INTO t3 VALUES(4, 2, 5);
156  INSERT INTO t3 VALUES(7, 2, 9);
157
158  INSERT INTO t4 VALUES('a', 'b', 'c');
159  INSERT INTO t4 VALUES('d', 'e', 'f');
160  INSERT INTO t4 VALUES('g', 'h', 'i');
161}
162faultsim_save_and_close
163
164proc xConflict {ret args} { return $ret }
165
166do_test 2.1 {
167  faultsim_restore_and_reopen
168  set C1 [changeset_from_sql {
169    INSERT INTO t3 VALUES(10, 11, 12);
170    UPDATE t4 SET y='j' WHERE x='g';
171    DELETE FROM t4 WHERE x='a';
172  }]
173
174  faultsim_restore_and_reopen
175  set C2 [changeset_from_sql {
176    INSERT INTO t3 VALUES(1000, 11, 12);
177    DELETE FROM t4 WHERE x='g';
178  }]
179
180  faultsim_restore_and_reopen
181  sqlite3changeset_apply db $C1 [list xConflict OMIT]
182  faultsim_save_and_close
183} {}
184
185do_faultsim_test 2.2 -faults oom* -prep {
186  catch {db2 close}
187  catch {db close}
188  faultsim_restore_and_reopen
189  sqlite3 db2 test.db2
190} -body {
191  set rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
192  set {} {}
193} -test {
194  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
195}
196do_faultsim_test 2.3 -faults oom* -prep {
197  catch {db2 close}
198  catch {db close}
199  faultsim_restore_and_reopen
200  sqlite3 db2 test.db2
201} -body {
202  set rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict REPLACE]]
203  set {} {}
204} -test {
205  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
206}
207do_faultsim_test 2.4 -faults oom* -prep {
208  catch {db2 close}
209  catch {db close}
210  faultsim_restore_and_reopen
211  set ::rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict REPLACE]]
212} -body {
213  sqlite3rebaser_create R
214  R configure $::rebase
215  R rebase $::C1
216  set {} {}
217} -test {
218  catch { R delete }
219  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
220}
221do_faultsim_test 2.5 -faults oom* -prep {
222  catch {db2 close}
223  catch {db close}
224  faultsim_restore_and_reopen
225  set ::rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
226} -body {
227  sqlite3rebaser_create R
228  R configure $::rebase
229  R rebase $::C1
230  set {} {}
231} -test {
232  catch { R delete }
233  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
234}
235
236}
237
238reset_db
239do_execsql_test 3.0 {
240  CREATE TABLE t1(x PRIMARY KEY, y, z);
241  INSERT INTO t1 VALUES(3, 1, 4);
242  INSERT INTO t1 VALUES(1, 5, 9);
243}
244faultsim_save_and_close
245
246proc xConflict {ret args} { return $ret }
247
248do_test 3.1 {
249  faultsim_restore_and_reopen
250
251  execsql { BEGIN; UPDATE t1 SET z=11; }
252  set C1 [changeset_from_sql {
253    UPDATE t1 SET z=10 WHERE x=1;
254  }]
255  execsql { ROLLBACK }
256
257  execsql { BEGIN; UPDATE t1 SET z=11; }
258  set C2 [changeset_from_sql {
259    UPDATE t1 SET z=55 WHERE x=1;
260  }]
261  execsql { ROLLBACK }
262
263  set ::rebase1 [sqlite3changeset_apply_v2 db $::C1 [list xConflict OMIT]]
264  set ::rebase2 [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
265  set {} {}
266  execsql { SELECT * FROM t1 }
267} {3 1 4 1 5 9}
268
269
270do_faultsim_test 3.2 -faults oom* -prep {
271  faultsim_restore_and_reopen
272} -body {
273  sqlite3rebaser_create R
274  R configure $::rebase1
275  R configure $::rebase2
276  set {} {}
277} -test {
278  catch { R delete }
279  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
280}
281
282
283finish_test
284
285