1# 2018 March 14 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# This file implements regression tests for SQLite library. 12# 13 14if {![info exists testdir]} { 15 set testdir [file join [file dirname [info script]] .. .. test] 16} 17source [file join [file dirname [info script]] session_common.tcl] 18source $testdir/tester.tcl 19ifcapable !session {finish_test; return} 20 21set testprefix sessionrebase 22 23set ::lConflict [list] 24proc xConflict {args} { 25 set res [lindex $::lConflict 0] 26 set ::lConflict [lrange $::lConflict 1 end] 27 return $res 28} 29 30#------------------------------------------------------------------------- 31# The following test cases - 1.* - test that the rebase blobs output by 32# sqlite3_changeset_apply_v2 look correct in some simple cases. The blob 33# is itself a changeset, containing records determined as follows: 34# 35# * For each conflict resolved with REPLACE, the rebase blob contains 36# a DELETE record. All fields other than the PK fields are undefined. 37# 38# * For each conflict resolved with OMIT, the rebase blob contains an 39# INSERT record. For an INSERT or UPDATE operation, the indirect flag 40# is clear and all updated fields are defined. For a DELETE operation, 41# the indirect flag is set and all non-PK fields left undefined. 42# 43proc do_apply_v2_test {tn sql modsql conflict_handler res} { 44 45 execsql BEGIN 46 sqlite3session S db main 47 S attach * 48 execsql $sql 49 set changeset [S changeset] 50 S delete 51 execsql ROLLBACK 52 53 execsql BEGIN 54 execsql $modsql 55 set ::lConflict $conflict_handler 56 set blob [sqlite3changeset_apply_v2 db $changeset xConflict] 57 execsql ROLLBACK 58 59 uplevel [list do_test $tn [list changeset_to_list $blob] [list {*}$res]] 60} 61 62do_execsql_test 1.0 { 63 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 64 INSERT INTO t1 VALUES(1, 'value A'); 65} 66 67do_apply_v2_test 1.1.1 { 68 UPDATE t1 SET b = 'value B' WHERE a=1; 69} { 70 UPDATE t1 SET b = 'value C' WHERE a=1; 71} { 72 OMIT 73} { 74 {INSERT t1 0 X. {} {i 1 t {value B}}} 75} 76do_apply_v2_test 1.1.2 { 77 UPDATE t1 SET b = 'value B' WHERE a=1; 78} { 79 UPDATE t1 SET b = 'value C' WHERE a=1; 80} { 81 REPLACE 82} { 83 {DELETE t1 0 X. {i 1 {} {}} {}} 84} 85 86do_apply_v2_test 1.2.1 { 87 INSERT INTO t1 VALUES(2, 'first'); 88} { 89 INSERT INTO t1 VALUES(2, 'second'); 90} { 91 OMIT 92} { 93 {INSERT t1 0 X. {} {i 2 t first}} 94} 95do_apply_v2_test 1.2.2 { 96 INSERT INTO t1 VALUES(2, 'first'); 97} { 98 INSERT INTO t1 VALUES(2, 'second'); 99} { 100 REPLACE 101} { 102 {DELETE t1 0 X. {i 2 {} {}} {}} 103} 104 105do_apply_v2_test 1.3.1 { 106 DELETE FROM t1 WHERE a=1; 107} { 108 UPDATE t1 SET b='value D' WHERE a=1; 109} { 110 OMIT 111} { 112 {INSERT t1 1 X. {} {i 1 {} {}}} 113} 114do_apply_v2_test 1.3.2 { 115 DELETE FROM t1 WHERE a=1; 116} { 117 UPDATE t1 SET b='value D' WHERE a=1; 118} { 119 REPLACE 120} { 121 {DELETE t1 0 X. {i 1 {} {}} {}} 122} 123 124#------------------------------------------------------------------------- 125# Test cases 2.* - simple tests of rebasing actual changesets. 126# 127# 2.1.1 - 1u2u1r 128# 2.1.2 - 1u2u2r 129# 2.1.3 - 1d2d 130# 2.1.4 - 1d2u1r 131# 2.1.5 - 1d2u2r !! 132# 2.1.6 - 1u2d1r 133 134proc xConflictAbort {args} { 135 return "ABORT" 136} 137 138# Take a copy of database test.db in file test.db2. Execute $sql1 139# against test.db and $sql2 against test.db2. Capture a changeset 140# for each. Then send the test.db2 changeset to test.db and apply 141# it with the conflict handlers in $conflict_handler. Patch the 142# test.db changeset and then execute it against test.db2. Test that 143# the two databases come out the same. 144# 145proc do_rebase_test {tn sql1 sql2 conflict_handler {testsql ""} {testres ""}} { 146 147 forcedelete test.db2 test.db2-journal test.db2-wal 148 forcecopy test.db test.db2 149 sqlite3 db2 test.db2 150 151 db eval BEGIN 152 153 sqlite3session S1 db main 154 S1 attach * 155 execsql $sql1 db 156 set c1 [S1 changeset] 157 S1 delete 158 159 sqlite3session S2 db2 main 160 S2 attach * 161 execsql $sql2 db2 162 set c2 [S2 changeset] 163 S2 delete 164 165 set ::lConflict $conflict_handler 166 set rebase [sqlite3changeset_apply_v2 db $c2 xConflict] 167 #puts [changeset_to_list $rebase] 168 169 sqlite3rebaser_create R 170 R configure $rebase 171 set c1r [R rebase $c1] 172 R delete 173 #puts [changeset_to_list $c1r] 174 175 sqlite3changeset_apply_v2 db2 $c1r xConflictAbort 176 177 uplevel [list do_test $tn.1 [list compare_db db db2] {}] 178 db2 close 179 180 if {$testsql!=""} { 181 uplevel [list do_execsql_test $tn.2 $testsql $testres] 182 } 183 184 db eval ROLLBACK 185} 186 187reset_db 188do_execsql_test 2.1.0 { 189 CREATE TABLE t1 (a INTEGER PRIMARY KEY, b TEXT); 190 INSERT INTO t1 VALUES(1, 'one'); 191 INSERT INTO t1 VALUES(2, 'two'); 192 INSERT INTO t1 VALUES(3, 'three'); 193} 194do_rebase_test 2.1.1 { 195 UPDATE t1 SET b = 'two.1' WHERE a=2; 196} { 197 UPDATE t1 SET b = 'two.2' WHERE a=2; 198} { 199 OMIT 200} { SELECT * FROM t1 } {1 one 2 two.1 3 three} 201 202do_rebase_test 2.1.2 { 203 UPDATE t1 SET b = 'two.1' WHERE a=2; 204} { 205 UPDATE t1 SET b = 'two.2' WHERE a=2; 206} { 207 REPLACE 208} { SELECT * FROM t1 } {1 one 2 two.2 3 three} 209 210do_rebase_test 2.1.3 { 211 DELETE FROM t1 WHERE a=3; 212} { 213 DELETE FROM t1 WHERE a=3; 214} { 215 OMIT 216} { SELECT * FROM t1 } {1 one 2 two} 217 218do_rebase_test 2.1.4 { 219 DELETE FROM t1 WHERE a=1; 220} { 221 UPDATE t1 SET b='one.2' WHERE a=1 222} { 223 OMIT 224} { SELECT * FROM t1 } {2 two 3 three} 225 226#do_rebase_test 2.1.5 { 227 #DELETE FROM t1 WHERE a=1; 228#} { 229 #UPDATE t1 SET b='one.2' WHERE a=1 230#} { 231 #REPLACE 232#} { SELECT * FROM t1 } {2 two 3 three} 233 234do_rebase_test 2.1.6 { 235 UPDATE t1 SET b='three.1' WHERE a=3; 236} { 237 DELETE FROM t1 WHERE a=3; 238} { 239 OMIT 240} { SELECT * FROM t1 } {1 one 2 two 3 three.1} 241 242do_rebase_test 2.1.7 { 243 UPDATE t1 SET b='three.1' WHERE a=3; 244} { 245 DELETE FROM t1 WHERE a=3; 246} { 247 REPLACE 248} { SELECT * FROM t1 } {1 one 2 two} 249 250finish_test 251 252