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
163db2 close
164
165proc xConflict {ret args} { return $ret }
166
167do_test 2.1 {
168  faultsim_restore_and_reopen
169  set C1 [changeset_from_sql {
170    INSERT INTO t3 VALUES(10, 11, 12);
171    UPDATE t4 SET y='j' WHERE x='g';
172    DELETE FROM t4 WHERE x='a';
173  }]
174
175  faultsim_restore_and_reopen
176  set C2 [changeset_from_sql {
177    INSERT INTO t3 VALUES(1000, 11, 12);
178    DELETE FROM t4 WHERE x='g';
179  }]
180
181  faultsim_restore_and_reopen
182  sqlite3changeset_apply db $C1 [list xConflict OMIT]
183  faultsim_save_and_close
184} {}
185
186do_faultsim_test 2.2 -faults oom* -prep {
187  catch {db2 close}
188  catch {db close}
189  faultsim_restore_and_reopen
190  sqlite3 db2 test.db2
191} -body {
192  set rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
193  set {} {}
194} -test {
195  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
196}
197do_faultsim_test 2.3 -faults oom* -prep {
198  catch {db2 close}
199  catch {db close}
200  faultsim_restore_and_reopen
201  sqlite3 db2 test.db2
202} -body {
203  set rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict REPLACE]]
204  set {} {}
205} -test {
206  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
207}
208do_faultsim_test 2.4 -faults oom* -prep {
209  catch {db2 close}
210  catch {db close}
211  faultsim_restore_and_reopen
212  set ::rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict REPLACE]]
213} -body {
214  sqlite3rebaser_create R
215  R configure $::rebase
216  R rebase $::C1
217  set {} {}
218} -test {
219  catch { R delete }
220  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
221}
222do_faultsim_test 2.5 -faults oom* -prep {
223  catch {db2 close}
224  catch {db close}
225  faultsim_restore_and_reopen
226  set ::rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
227} -body {
228  sqlite3rebaser_create R
229  R configure $::rebase
230  R rebase $::C1
231  set {} {}
232} -test {
233  catch { R delete }
234  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
235}
236
237}
238
239reset_db
240do_execsql_test 3.0 {
241  CREATE TABLE t1(x PRIMARY KEY, y, z);
242  INSERT INTO t1 VALUES(3, 1, 4);
243  INSERT INTO t1 VALUES(1, 5, 9);
244}
245faultsim_save_and_close
246
247proc xConflict {ret args} { return $ret }
248
249do_test 3.1 {
250  faultsim_restore_and_reopen
251
252  execsql { BEGIN; UPDATE t1 SET z=11; }
253  set C1 [changeset_from_sql {
254    UPDATE t1 SET z=10 WHERE x=1;
255  }]
256  execsql { ROLLBACK }
257
258  execsql { BEGIN; UPDATE t1 SET z=11; }
259  set C2 [changeset_from_sql {
260    UPDATE t1 SET z=55 WHERE x=1;
261  }]
262  execsql { ROLLBACK }
263
264  set ::rebase1 [sqlite3changeset_apply_v2 db $::C1 [list xConflict OMIT]]
265  set ::rebase2 [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
266  set {} {}
267  execsql { SELECT * FROM t1 }
268} {3 1 4 1 5 9}
269
270
271do_faultsim_test 3.2 -faults oom* -prep {
272  faultsim_restore_and_reopen
273} -body {
274  sqlite3rebaser_create R
275  R configure $::rebase1
276  R configure $::rebase2
277  set {} {}
278} -test {
279  catch { R delete }
280  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
281}
282
283
284finish_test
285