OLD | NEW |
(Empty) | |
| 1 # 2011 April 13 |
| 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 the session module. |
| 12 # Specifically, for the sqlite3changeset_concat() command. |
| 13 # |
| 14 |
| 15 if {![info exists testdir]} { |
| 16 set testdir [file join [file dirname [info script]] .. .. test] |
| 17 } |
| 18 source [file join [file dirname [info script]] session_common.tcl] |
| 19 source $testdir/tester.tcl |
| 20 ifcapable !session {finish_test; return} |
| 21 |
| 22 set testprefix session5 |
| 23 |
| 24 # Organization of tests: |
| 25 # |
| 26 # session5-1.*: Simple tests to check the concat() function produces |
| 27 # correct results. |
| 28 # |
| 29 # session5-2.*: More complicated tests. |
| 30 # |
| 31 # session5-3.*: Schema mismatch errors. |
| 32 # |
| 33 # session5-4.*: Test the concat cases that indicate that the database |
| 34 # was modified in between recording of the two changesets |
| 35 # being concatenated (i.e. two changesets that INSERT rows |
| 36 # with the same PK values). |
| 37 # |
| 38 |
| 39 proc do_concat_test {tn args} { |
| 40 |
| 41 set subtest 0 |
| 42 foreach sql $args { |
| 43 incr subtest |
| 44 sqlite3session S db main ; S attach * |
| 45 execsql $sql |
| 46 |
| 47 set c [S changeset] |
| 48 if {[info commands s_prev] != ""} { |
| 49 set c_concat [sqlite3changeset_concat $c_prev $c] |
| 50 set c_two [s_prev changeset] |
| 51 s_prev delete |
| 52 |
| 53 set h_concat [changeset_to_list $c_concat] |
| 54 set h_two [changeset_to_list $c_two] |
| 55 |
| 56 do_test $tn.$subtest [list set {} $h_concat] $h_two |
| 57 } |
| 58 set c_prev $c |
| 59 rename S s_prev |
| 60 } |
| 61 |
| 62 catch { s_prev delete } |
| 63 } |
| 64 |
| 65 #------------------------------------------------------------------------- |
| 66 # Test cases session5-1.* - simple tests. |
| 67 # |
| 68 do_execsql_test 1.0 { |
| 69 CREATE TABLE t1(a PRIMARY KEY, b); |
| 70 } |
| 71 |
| 72 do_concat_test 1.1.1 { |
| 73 INSERT INTO t1 VALUES(1, 'one'); |
| 74 } { |
| 75 INSERT INTO t1 VALUES(2, 'two'); |
| 76 } |
| 77 |
| 78 do_concat_test 1.1.2 { |
| 79 UPDATE t1 SET b = 'five' WHERE a = 1; |
| 80 } { |
| 81 UPDATE t1 SET b = 'six' WHERE a = 2; |
| 82 } |
| 83 |
| 84 do_concat_test 1.1.3 { |
| 85 DELETE FROM t1 WHERE a = 1; |
| 86 } { |
| 87 DELETE FROM t1 WHERE a = 2; |
| 88 } |
| 89 |
| 90 |
| 91 # 1.2.1: INSERT + DELETE -> (none) |
| 92 # 1.2.2: INSERT + UPDATE -> INSERT |
| 93 # |
| 94 # 1.2.3: DELETE + INSERT (matching data) -> (none) |
| 95 # 1.2.4: DELETE + INSERT (non-matching data) -> UPDATE |
| 96 # |
| 97 # 1.2.5: UPDATE + UPDATE (matching data) -> (none) |
| 98 # 1.2.6: UPDATE + UPDATE (non-matching data) -> UPDATE |
| 99 # 1.2.7: UPDATE + DELETE -> DELETE |
| 100 # |
| 101 do_concat_test 1.2.1 { |
| 102 INSERT INTO t1 VALUES('x', 'y'); |
| 103 } { |
| 104 DELETE FROM t1 WHERE a = 'x'; |
| 105 } |
| 106 do_concat_test 1.2.2 { |
| 107 INSERT INTO t1 VALUES(5.0, 'five'); |
| 108 } { |
| 109 UPDATE t1 SET b = 'six' WHERE a = 5.0; |
| 110 } |
| 111 |
| 112 do_execsql_test 1.2.3.1 "INSERT INTO t1 VALUES('I', 'one')" |
| 113 do_concat_test 1.2.3.2 { |
| 114 DELETE FROM t1 WHERE a = 'I'; |
| 115 } { |
| 116 INSERT INTO t1 VALUES('I', 'one'); |
| 117 } |
| 118 do_concat_test 1.2.4 { |
| 119 DELETE FROM t1 WHERE a = 'I'; |
| 120 } { |
| 121 INSERT INTO t1 VALUES('I', 'two'); |
| 122 } |
| 123 do_concat_test 1.2.5 { |
| 124 UPDATE t1 SET b = 'five' WHERE a = 'I'; |
| 125 } { |
| 126 UPDATE t1 SET b = 'two' WHERE a = 'I'; |
| 127 } |
| 128 do_concat_test 1.2.6 { |
| 129 UPDATE t1 SET b = 'six' WHERE a = 'I'; |
| 130 } { |
| 131 UPDATE t1 SET b = 'seven' WHERE a = 'I'; |
| 132 } |
| 133 do_concat_test 1.2.7 { |
| 134 UPDATE t1 SET b = 'eight' WHERE a = 'I'; |
| 135 } { |
| 136 DELETE FROM t1 WHERE a = 'I'; |
| 137 } |
| 138 |
| 139 |
| 140 #------------------------------------------------------------------------- |
| 141 # Test cases session5-2.* - more complex tests. |
| 142 # |
| 143 db function indirect indirect |
| 144 proc indirect {{x -1}} { |
| 145 S indirect $x |
| 146 s_prev indirect $x |
| 147 } |
| 148 do_concat_test 2.1 { |
| 149 CREATE TABLE abc(a, b, c PRIMARY KEY); |
| 150 INSERT INTO abc VALUES(NULL, NULL, 1); |
| 151 INSERT INTO abc VALUES('abcdefghijkl', NULL, 2); |
| 152 } { |
| 153 DELETE FROM abc WHERE c = 1; |
| 154 UPDATE abc SET c = 1 WHERE c = 2; |
| 155 } { |
| 156 INSERT INTO abc VALUES('abcdefghijkl', NULL, 2); |
| 157 INSERT INTO abc VALUES(1.0, 2.0, 3); |
| 158 } { |
| 159 UPDATE abc SET a = a-1; |
| 160 } { |
| 161 CREATE TABLE def(d, e, f, PRIMARY KEY(e, f)); |
| 162 INSERT INTO def VALUES('x', randomblob(11000), 67); |
| 163 INSERT INTO def SELECT d, e, f+1 FROM def; |
| 164 INSERT INTO def SELECT d, e, f+2 FROM def; |
| 165 INSERT INTO def SELECT d, e, f+4 FROM def; |
| 166 } { |
| 167 DELETE FROM def WHERE rowid>4; |
| 168 } { |
| 169 INSERT INTO def SELECT d, e, f+4 FROM def; |
| 170 } { |
| 171 INSERT INTO abc VALUES(22, 44, -1); |
| 172 } { |
| 173 UPDATE abc SET c=-2 WHERE c=-1; |
| 174 UPDATE abc SET c=-3 WHERE c=-2; |
| 175 } { |
| 176 UPDATE abc SET c=-4 WHERE c=-3; |
| 177 } { |
| 178 UPDATE abc SET a=a+1 WHERE c=-3; |
| 179 UPDATE abc SET a=a+1 WHERE c=-3; |
| 180 } { |
| 181 UPDATE abc SET a=a+1 WHERE c=-3; |
| 182 UPDATE abc SET a=a+1 WHERE c=-3; |
| 183 } { |
| 184 INSERT INTO abc VALUES('one', 'two', 'three'); |
| 185 } { |
| 186 SELECT indirect(1); |
| 187 UPDATE abc SET a='one point five' WHERE c = 'three'; |
| 188 } { |
| 189 SELECT indirect(0); |
| 190 UPDATE abc SET a='one point six' WHERE c = 'three'; |
| 191 } { |
| 192 CREATE TABLE x1(a, b, PRIMARY KEY(a)); |
| 193 SELECT indirect(1); |
| 194 INSERT INTO x1 VALUES(1, 2); |
| 195 } { |
| 196 SELECT indirect(1); |
| 197 UPDATE x1 SET b = 3 WHERE a = 1; |
| 198 } |
| 199 |
| 200 catch {db close} |
| 201 forcedelete test.db |
| 202 sqlite3 db test.db |
| 203 do_concat_test 2.2 { |
| 204 CREATE TABLE t1(a, b, PRIMARY KEY(b)); |
| 205 CREATE TABLE t2(a PRIMARY KEY, b); |
| 206 INSERT INTO t1 VALUES('string', 1); |
| 207 INSERT INTO t1 VALUES(4, 2); |
| 208 INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3); |
| 209 } { |
| 210 INSERT INTO t2 VALUES('one', 'two'); |
| 211 INSERT INTO t2 VALUES(1, NULL); |
| 212 UPDATE t1 SET a = 5 WHERE a = 2; |
| 213 } { |
| 214 DELETE FROM t2 WHERE a = 1; |
| 215 UPDATE t1 SET a = 4 WHERE a = 2; |
| 216 INSERT INTO t2 VALUES('x', 'y'); |
| 217 } |
| 218 |
| 219 do_test 2.3.0 { |
| 220 catch {db close} |
| 221 forcedelete test.db |
| 222 sqlite3 db test.db |
| 223 |
| 224 set sql1 "" |
| 225 set sql2 "" |
| 226 for {set i 1} {$i < 120} {incr i} { |
| 227 append sql1 "INSERT INTO x1 VALUES($i*4, $i);" |
| 228 } |
| 229 for {set i 1} {$i < 120} {incr i} { |
| 230 append sql2 "DELETE FROM x1 WHERE a = $i*4;" |
| 231 } |
| 232 set {} {} |
| 233 } {} |
| 234 do_concat_test 2.3 { |
| 235 CREATE TABLE x1(a PRIMARY KEY, b) |
| 236 } $sql1 $sql2 $sql1 $sql2 |
| 237 |
| 238 do_concat_test 2.4 { |
| 239 CREATE TABLE x2(a PRIMARY KEY, b); |
| 240 CREATE TABLE x3(a PRIMARY KEY, b); |
| 241 |
| 242 INSERT INTO x2 VALUES('a', 'b'); |
| 243 INSERT INTO x2 VALUES('x', 'y'); |
| 244 INSERT INTO x3 VALUES('a', 'b'); |
| 245 } { |
| 246 INSERT INTO x2 VALUES('c', 'd'); |
| 247 INSERT INTO x3 VALUES('e', 'f'); |
| 248 INSERT INTO x3 VALUES('x', 'y'); |
| 249 } |
| 250 |
| 251 do_concat_test 2.5 { |
| 252 UPDATE x3 SET b = 'Y' WHERE a = 'x' |
| 253 } { |
| 254 DELETE FROM x3 WHERE a = 'x' |
| 255 } { |
| 256 DELETE FROM x2 WHERE a = 'a' |
| 257 } { |
| 258 INSERT INTO x2 VALUES('a', 'B'); |
| 259 } |
| 260 |
| 261 for {set k 1} {$k <=10} {incr k} { |
| 262 do_test 2.6.$k.1 { |
| 263 drop_all_tables |
| 264 set sql1 "" |
| 265 set sql2 "" |
| 266 for {set i 1} {$i < 120} {incr i} { |
| 267 append sql1 "INSERT INTO x1 VALUES(randomblob(20+(random()%10)), $i);" |
| 268 } |
| 269 for {set i 1} {$i < 120} {incr i} { |
| 270 append sql2 "DELETE FROM x1 WHERE rowid = $i;" |
| 271 } |
| 272 set {} {} |
| 273 } {} |
| 274 do_concat_test 2.6.$k { |
| 275 CREATE TABLE x1(a PRIMARY KEY, b) |
| 276 } $sql1 $sql2 $sql1 $sql2 |
| 277 } |
| 278 |
| 279 for {set k 1} {$k <=10} {incr k} { |
| 280 do_test 2.7.$k.1 { |
| 281 drop_all_tables |
| 282 set sql1 "" |
| 283 set sql2 "" |
| 284 for {set i 1} {$i < 120} {incr i} { |
| 285 append sql1 { |
| 286 INSERT INTO x1 VALUES( |
| 287 CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END, |
| 288 CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END |
| 289 ); |
| 290 } |
| 291 } |
| 292 for {set i 1} {$i < 120} {incr i} { |
| 293 append sql2 "DELETE FROM x1 WHERE rowid = $i;" |
| 294 } |
| 295 set {} {} |
| 296 } {} |
| 297 do_concat_test 2.7.$k { |
| 298 CREATE TABLE x1(a PRIMARY KEY, b) |
| 299 } $sql1 $sql2 $sql1 $sql2 |
| 300 } |
| 301 |
| 302 |
| 303 #------------------------------------------------------------------------- |
| 304 # Test that schema incompatibilities are detected correctly. |
| 305 # |
| 306 # session5-3.1: Incompatible number of columns. |
| 307 # session5-3.2: Incompatible PK definition. |
| 308 # |
| 309 |
| 310 do_test 3.1 { |
| 311 db close |
| 312 forcedelete test.db |
| 313 sqlite3 db test.db |
| 314 |
| 315 execsql { CREATE TABLE t1(a PRIMARY KEY, b) } |
| 316 set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }] |
| 317 execsql { |
| 318 DROP TABLE t1; |
| 319 CREATE TABLE t1(a PRIMARY KEY, b, c); |
| 320 } |
| 321 set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3, 4) }] |
| 322 |
| 323 list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg |
| 324 } {1 SQLITE_SCHEMA} |
| 325 |
| 326 do_test 3.2 { |
| 327 db close |
| 328 forcedelete test.db |
| 329 sqlite3 db test.db |
| 330 |
| 331 execsql { CREATE TABLE t1(a PRIMARY KEY, b) } |
| 332 set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }] |
| 333 execsql { |
| 334 DROP TABLE t1; |
| 335 CREATE TABLE t1(a, b PRIMARY KEY); |
| 336 } |
| 337 set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3) }] |
| 338 |
| 339 list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg |
| 340 } {1 SQLITE_SCHEMA} |
| 341 |
| 342 #------------------------------------------------------------------------- |
| 343 # Test that concat() handles these properly: |
| 344 # |
| 345 # session5-4.1: INSERT + INSERT |
| 346 # session5-4.2: UPDATE + INSERT |
| 347 # session5-4.3: DELETE + UPDATE |
| 348 # session5-4.4: DELETE + DELETE |
| 349 # |
| 350 |
| 351 proc do_concat_test2 {tn sql1 sqlX sql2 expected} { |
| 352 sqlite3session S db main ; S attach * |
| 353 execsql $sql1 |
| 354 set ::c1 [S changeset] |
| 355 S delete |
| 356 |
| 357 execsql $sqlX |
| 358 |
| 359 sqlite3session S db main ; S attach * |
| 360 execsql $sql2 |
| 361 set ::c2 [S changeset] |
| 362 S delete |
| 363 |
| 364 uplevel do_test $tn [list { |
| 365 changeset_to_list [sqlite3changeset_concat $::c1 $::c2] |
| 366 }] [list [normalize_list $expected]] |
| 367 } |
| 368 |
| 369 drop_all_tables db |
| 370 do_concat_test2 4.1 { |
| 371 CREATE TABLE t1(a PRIMARY KEY, b); |
| 372 INSERT INTO t1 VALUES('key', 'value'); |
| 373 } { |
| 374 DELETE FROM t1 WHERE a = 'key'; |
| 375 } { |
| 376 INSERT INTO t1 VALUES('key', 'xxx'); |
| 377 } { |
| 378 {INSERT t1 0 X. {} {t key t value}} |
| 379 } |
| 380 do_concat_test2 4.2 { |
| 381 UPDATE t1 SET b = 'yyy'; |
| 382 } { |
| 383 DELETE FROM t1 WHERE a = 'key'; |
| 384 } { |
| 385 INSERT INTO t1 VALUES('key', 'value'); |
| 386 } { |
| 387 {UPDATE t1 0 X. {t key t xxx} {{} {} t yyy}} |
| 388 } |
| 389 do_concat_test2 4.3 { |
| 390 DELETE FROM t1 WHERE a = 'key'; |
| 391 } { |
| 392 INSERT INTO t1 VALUES('key', 'www'); |
| 393 } { |
| 394 UPDATE t1 SET b = 'valueX' WHERE a = 'key'; |
| 395 } { |
| 396 {DELETE t1 0 X. {t key t value} {}} |
| 397 } |
| 398 do_concat_test2 4.4 { |
| 399 DELETE FROM t1 WHERE a = 'key'; |
| 400 } { |
| 401 INSERT INTO t1 VALUES('key', 'ttt'); |
| 402 } { |
| 403 DELETE FROM t1 WHERE a = 'key'; |
| 404 } { |
| 405 {DELETE t1 0 X. {t key t valueX} {}} |
| 406 } |
| 407 |
| 408 finish_test |
OLD | NEW |