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