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
148#-------------------------------------------------------------------------
149# OOM when collecting and using a rebase changeset.
150#
151reset_db
152do_execsql_test 2.0 {
153  CREATE TABLE t3(a, b, c, PRIMARY KEY(b, c));
154  CREATE TABLE t4(x PRIMARY KEY, y, z);
155
156  INSERT INTO t3 VALUES(1, 2, 3);
157  INSERT INTO t3 VALUES(4, 2, 5);
158  INSERT INTO t3 VALUES(7, 2, 9);
159
160  INSERT INTO t4 VALUES('a', 'b', 'c');
161  INSERT INTO t4 VALUES('d', 'e', 'f');
162  INSERT INTO t4 VALUES('g', 'h', 'i');
163}
164faultsim_save_and_close
165
166proc xConflict {ret args} { return $ret }
167
168do_test 2.1 {
169  faultsim_restore_and_reopen
170  set C1 [changeset_from_sql {
171    INSERT INTO t3 VALUES(10, 11, 12);
172    UPDATE t4 SET y='j' WHERE x='g';
173    DELETE FROM t4 WHERE x='a';
174  }]
175
176  faultsim_restore_and_reopen
177  set C2 [changeset_from_sql {
178    INSERT INTO t3 VALUES(1000, 11, 12);
179    DELETE FROM t4 WHERE x='g';
180  }]
181
182  faultsim_restore_and_reopen
183  sqlite3changeset_apply db $C1 [list xConflict OMIT]
184  faultsim_save_and_close
185} {}
186
187do_faultsim_test 2.2 -faults oom* -prep {
188  catch {db2 close}
189  catch {db close}
190  faultsim_restore_and_reopen
191  sqlite3 db2 test.db2
192} -body {
193  set rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
194  set {} {}
195} -test {
196  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
197}
198do_faultsim_test 2.3 -faults oom* -prep {
199  catch {db2 close}
200  catch {db close}
201  faultsim_restore_and_reopen
202  sqlite3 db2 test.db2
203} -body {
204  set rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict REPLACE]]
205  set {} {}
206} -test {
207  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
208}
209do_faultsim_test 2.4 -faults oom* -prep {
210  catch {db2 close}
211  catch {db close}
212  faultsim_restore_and_reopen
213  set ::rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict REPLACE]]
214} -body {
215  sqlite3rebaser_create R
216  R configure $::rebase
217  R rebase $::C1
218  set {} {}
219} -test {
220  catch { R delete }
221  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
222}
223do_faultsim_test 2.5 -faults oom* -prep {
224  catch {db2 close}
225  catch {db close}
226  faultsim_restore_and_reopen
227  set ::rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]]
228} -body {
229  sqlite3rebaser_create R
230  R configure $::rebase
231  R rebase $::C1
232  set {} {}
233} -test {
234  catch { R delete }
235  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
236}
237
238
239finish_test
240
241