1# 2011 Mar 21 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 20 21set testprefix sessionfault 22 23forcedelete test.db2 24sqlite3 db2 test.db2 25do_common_sql { 26 CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)); 27 INSERT INTO t1 VALUES(1, 2, 3); 28 INSERT INTO t1 VALUES(4, 5, 6); 29} 30faultsim_save_and_close 31db2 close 32 33 34#------------------------------------------------------------------------- 35# Test OOM error handling when collecting and applying a simple changeset. 36# 37do_faultsim_test pagerfault-1 -faults oom-* -prep { 38 catch {db2 close} 39 catch {db close} 40 faultsim_restore_and_reopen 41 sqlite3 db2 test.db2 42} -body { 43 do_then_apply_sql { 44 INSERT INTO t1 VALUES(7, 8, 9); 45 UPDATE t1 SET c = 10 WHERE a = 1; 46 DELETE FROM t1 WHERE a = 4; 47 } 48} -test { 49 faultsim_test_result {0 {}} {1 SQLITE_NOMEM} 50 faultsim_integrity_check 51 if {$testrc==0} { compare_db db db2 } 52} 53 54#------------------------------------------------------------------------- 55# The following block of tests - pagerfault-2.* - are designed to check 56# the handling of faults in the sqlite3changeset_apply() function. 57# 58catch {db close} 59catch {db2 close} 60forcedelete test.db2 test.db 61sqlite3 db2 test.db2 62sqlite3 db test.db 63do_common_sql { 64 CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)); 65 INSERT INTO t1 VALUES('apple', 'orange', 'pear'); 66 67 CREATE TABLE t2(x PRIMARY KEY, y); 68} 69db2 close 70faultsim_save_and_close 71 72 73foreach {tn conflict_policy sql sql2} { 74 1 OMIT { INSERT INTO t1 VALUES('one text', 'two text', X'00ff00') } {} 75 2 OMIT { DELETE FROM t1 WHERE a = 'apple' } {} 76 3 OMIT { UPDATE t1 SET c = 'banana' WHERE b = 'orange' } {} 77 4 REPLACE { INSERT INTO t2 VALUES('keyvalue', 'value 1') } { 78 INSERT INTO t2 VALUES('keyvalue', 'value 2'); 79 } 80} { 81 proc xConflict args [list return $conflict_policy] 82 83 do_faultsim_test pagerfault-2.$tn -faults oom-transient -prep { 84 catch {db2 close} 85 catch {db close} 86 faultsim_restore_and_reopen 87 set ::changeset [changeset_from_sql $::sql] 88 sqlite3 db2 test.db2 89 sqlite3_db_config_lookaside db2 0 0 0 90 execsql $::sql2 db2 91 } -body { 92 sqlite3changeset_apply db2 $::changeset xConflict 93 } -test { 94 faultsim_test_result {0 {}} {1 SQLITE_NOMEM} 95 faultsim_integrity_check 96 if {$testrc==0} { compare_db db db2 } 97 } 98} 99 100#------------------------------------------------------------------------- 101# This test case is designed so that a malloc() failure occurs while 102# resizing the session object hash-table from 256 to 512 buckets. This 103# is not an error, just a sub-optimal condition. 104# 105do_faultsim_test pagerfault-3 -faults oom-* -prep { 106 catch {db2 close} 107 catch {db close} 108 faultsim_restore_and_reopen 109 sqlite3 db2 test.db2 110 111 sqlite3session S db main 112 S attach t1 113 execsql { BEGIN } 114 for {set i 0} {$i < 125} {incr i} { 115 execsql {INSERT INTO t1 VALUES(10+$i, 10+$i, 10+$i)} 116 } 117} -body { 118 for {set i 125} {$i < 133} {incr i} { 119 execsql {INSERT INTO t1 VALUES(10+$i, 10+$i, 1-+$i)} 120 } 121 S changeset 122 set {} {} 123} -test { 124 faultsim_test_result {0 {}} {1 SQLITE_NOMEM} 125 if {$testrc==0} { 126 sqlite3changeset_apply db2 [S changeset] xConflict 127 compare_db db db2 128 } 129 catch { S delete } 130 faultsim_integrity_check 131} 132 133catch { db close } 134catch { db2 close } 135forcedelete test.db2 test.db 136sqlite3 db2 test.db2 137sqlite3 db test.db 138 139proc xConflict {op tbl type args} { 140 if { $type=="CONFLICT" || $type=="DATA" } { 141 return "REPLACE" 142 } 143 return "OMIT" 144} 145 146do_test 4.0 { 147 execsql { 148 PRAGMA encoding = 'utf16'; 149 CREATE TABLE t1(a PRIMARY KEY, b); 150 INSERT INTO t1 VALUES(5, 32); 151 } 152 execsql { 153 PRAGMA encoding = 'utf16'; 154 CREATE TABLE t1(a PRIMARY KEY, b NOT NULL); 155 INSERT INTO t1 VALUES(1, 2); 156 INSERT INTO t1 VALUES(2, 4); 157 INSERT INTO t1 VALUES(4, 16); 158 } db2 159} {} 160 161faultsim_save_and_close 162db2 close 163 164do_faultsim_test pagerfault-4 -faults oom-* -prep { 165 catch {db2 close} 166 catch {db close} 167 faultsim_restore_and_reopen 168 sqlite3 db2 test.db2 169 sqlite3session S db main 170 S attach t1 171 execsql { 172 INSERT INTO t1 VALUES(1, 45); 173 INSERT INTO t1 VALUES(2, 55); 174 INSERT INTO t1 VALUES(3, 55); 175 UPDATE t1 SET a = 4 WHERE a = 5; 176 } 177} -body { 178 sqlite3changeset_apply db2 [S changeset] xConflict 179} -test { 180 catch { S delete } 181 faultsim_test_result {0 {}} {1 SQLITE_NOMEM} 182 if {$testrc==0} { compare_db db db2 } 183} 184 185#------------------------------------------------------------------------- 186# This block of tests verifies that OOM faults in the 187# sqlite3changeset_invert() function are handled correctly. 188# 189catch {db close} 190catch {db2 close} 191forcedelete test.db 192sqlite3 db test.db 193execsql { 194 CREATE TABLE t1(a, b, PRIMARY KEY(b)); 195 CREATE TABLE t2(a PRIMARY KEY, b); 196 INSERT INTO t1 VALUES('string', 1); 197 INSERT INTO t1 VALUES(4, 2); 198 INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3); 199} 200set changeset [changeset_from_sql { 201 INSERT INTO t1 VALUES('xxx', 'yyy'); 202 DELETE FROM t1 WHERE a = 'string'; 203 UPDATE t1 SET a = 20 WHERE b = 2; 204}] 205db close 206 207do_faultsim_test pagerfault-5 -faults oom* -body { 208 set ::inverse [sqlite3changeset_invert $::changeset] 209 set {} {} 210} -test { 211 faultsim_test_result {0 {}} {1 SQLITE_NOMEM} 212 if {$testrc==0} { 213 set x [list] 214 sqlite3session_foreach c $::inverse { lappend x $c } 215 foreach c { 216 {DELETE t1 {t xxx t yyy} {}} 217 {INSERT t1 {} {t string i 1}} 218 {UPDATE t1 {i 20 {} {}} {i 4 i 2}} 219 } { lappend y $c } 220 if {$x != $y} { error "changeset no good" } 221 } 222} 223 224finish_test 225