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