Index: third_party/sqlite/src/ext/session/session5.test |
diff --git a/third_party/sqlite/src/ext/session/session5.test b/third_party/sqlite/src/ext/session/session5.test |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9b8f9ffe12f955bccdc0095d2fc0537ab87cf2c7 |
--- /dev/null |
+++ b/third_party/sqlite/src/ext/session/session5.test |
@@ -0,0 +1,408 @@ |
+# 2011 April 13 |
+# |
+# The author disclaims copyright to this source code. In place of |
+# a legal notice, here is a blessing: |
+# |
+# May you do good and not evil. |
+# May you find forgiveness for yourself and forgive others. |
+# May you share freely, never taking more than you give. |
+# |
+#*********************************************************************** |
+# This file implements regression tests for the session module. |
+# Specifically, for the sqlite3changeset_concat() command. |
+# |
+ |
+if {![info exists testdir]} { |
+ set testdir [file join [file dirname [info script]] .. .. test] |
+} |
+source [file join [file dirname [info script]] session_common.tcl] |
+source $testdir/tester.tcl |
+ifcapable !session {finish_test; return} |
+ |
+set testprefix session5 |
+ |
+# Organization of tests: |
+# |
+# session5-1.*: Simple tests to check the concat() function produces |
+# correct results. |
+# |
+# session5-2.*: More complicated tests. |
+# |
+# session5-3.*: Schema mismatch errors. |
+# |
+# session5-4.*: Test the concat cases that indicate that the database |
+# was modified in between recording of the two changesets |
+# being concatenated (i.e. two changesets that INSERT rows |
+# with the same PK values). |
+# |
+ |
+proc do_concat_test {tn args} { |
+ |
+ set subtest 0 |
+ foreach sql $args { |
+ incr subtest |
+ sqlite3session S db main ; S attach * |
+ execsql $sql |
+ |
+ set c [S changeset] |
+ if {[info commands s_prev] != ""} { |
+ set c_concat [sqlite3changeset_concat $c_prev $c] |
+ set c_two [s_prev changeset] |
+ s_prev delete |
+ |
+ set h_concat [changeset_to_list $c_concat] |
+ set h_two [changeset_to_list $c_two] |
+ |
+ do_test $tn.$subtest [list set {} $h_concat] $h_two |
+ } |
+ set c_prev $c |
+ rename S s_prev |
+ } |
+ |
+ catch { s_prev delete } |
+} |
+ |
+#------------------------------------------------------------------------- |
+# Test cases session5-1.* - simple tests. |
+# |
+do_execsql_test 1.0 { |
+ CREATE TABLE t1(a PRIMARY KEY, b); |
+} |
+ |
+do_concat_test 1.1.1 { |
+ INSERT INTO t1 VALUES(1, 'one'); |
+} { |
+ INSERT INTO t1 VALUES(2, 'two'); |
+} |
+ |
+do_concat_test 1.1.2 { |
+ UPDATE t1 SET b = 'five' WHERE a = 1; |
+} { |
+ UPDATE t1 SET b = 'six' WHERE a = 2; |
+} |
+ |
+do_concat_test 1.1.3 { |
+ DELETE FROM t1 WHERE a = 1; |
+} { |
+ DELETE FROM t1 WHERE a = 2; |
+} |
+ |
+ |
+# 1.2.1: INSERT + DELETE -> (none) |
+# 1.2.2: INSERT + UPDATE -> INSERT |
+# |
+# 1.2.3: DELETE + INSERT (matching data) -> (none) |
+# 1.2.4: DELETE + INSERT (non-matching data) -> UPDATE |
+# |
+# 1.2.5: UPDATE + UPDATE (matching data) -> (none) |
+# 1.2.6: UPDATE + UPDATE (non-matching data) -> UPDATE |
+# 1.2.7: UPDATE + DELETE -> DELETE |
+# |
+do_concat_test 1.2.1 { |
+ INSERT INTO t1 VALUES('x', 'y'); |
+} { |
+ DELETE FROM t1 WHERE a = 'x'; |
+} |
+do_concat_test 1.2.2 { |
+ INSERT INTO t1 VALUES(5.0, 'five'); |
+} { |
+ UPDATE t1 SET b = 'six' WHERE a = 5.0; |
+} |
+ |
+do_execsql_test 1.2.3.1 "INSERT INTO t1 VALUES('I', 'one')" |
+do_concat_test 1.2.3.2 { |
+ DELETE FROM t1 WHERE a = 'I'; |
+} { |
+ INSERT INTO t1 VALUES('I', 'one'); |
+} |
+do_concat_test 1.2.4 { |
+ DELETE FROM t1 WHERE a = 'I'; |
+} { |
+ INSERT INTO t1 VALUES('I', 'two'); |
+} |
+do_concat_test 1.2.5 { |
+ UPDATE t1 SET b = 'five' WHERE a = 'I'; |
+} { |
+ UPDATE t1 SET b = 'two' WHERE a = 'I'; |
+} |
+do_concat_test 1.2.6 { |
+ UPDATE t1 SET b = 'six' WHERE a = 'I'; |
+} { |
+ UPDATE t1 SET b = 'seven' WHERE a = 'I'; |
+} |
+do_concat_test 1.2.7 { |
+ UPDATE t1 SET b = 'eight' WHERE a = 'I'; |
+} { |
+ DELETE FROM t1 WHERE a = 'I'; |
+} |
+ |
+ |
+#------------------------------------------------------------------------- |
+# Test cases session5-2.* - more complex tests. |
+# |
+db function indirect indirect |
+proc indirect {{x -1}} { |
+ S indirect $x |
+ s_prev indirect $x |
+} |
+do_concat_test 2.1 { |
+ CREATE TABLE abc(a, b, c PRIMARY KEY); |
+ INSERT INTO abc VALUES(NULL, NULL, 1); |
+ INSERT INTO abc VALUES('abcdefghijkl', NULL, 2); |
+} { |
+ DELETE FROM abc WHERE c = 1; |
+ UPDATE abc SET c = 1 WHERE c = 2; |
+} { |
+ INSERT INTO abc VALUES('abcdefghijkl', NULL, 2); |
+ INSERT INTO abc VALUES(1.0, 2.0, 3); |
+} { |
+ UPDATE abc SET a = a-1; |
+} { |
+ CREATE TABLE def(d, e, f, PRIMARY KEY(e, f)); |
+ INSERT INTO def VALUES('x', randomblob(11000), 67); |
+ INSERT INTO def SELECT d, e, f+1 FROM def; |
+ INSERT INTO def SELECT d, e, f+2 FROM def; |
+ INSERT INTO def SELECT d, e, f+4 FROM def; |
+} { |
+ DELETE FROM def WHERE rowid>4; |
+} { |
+ INSERT INTO def SELECT d, e, f+4 FROM def; |
+} { |
+ INSERT INTO abc VALUES(22, 44, -1); |
+} { |
+ UPDATE abc SET c=-2 WHERE c=-1; |
+ UPDATE abc SET c=-3 WHERE c=-2; |
+} { |
+ UPDATE abc SET c=-4 WHERE c=-3; |
+} { |
+ UPDATE abc SET a=a+1 WHERE c=-3; |
+ UPDATE abc SET a=a+1 WHERE c=-3; |
+} { |
+ UPDATE abc SET a=a+1 WHERE c=-3; |
+ UPDATE abc SET a=a+1 WHERE c=-3; |
+} { |
+ INSERT INTO abc VALUES('one', 'two', 'three'); |
+} { |
+ SELECT indirect(1); |
+ UPDATE abc SET a='one point five' WHERE c = 'three'; |
+} { |
+ SELECT indirect(0); |
+ UPDATE abc SET a='one point six' WHERE c = 'three'; |
+} { |
+ CREATE TABLE x1(a, b, PRIMARY KEY(a)); |
+ SELECT indirect(1); |
+ INSERT INTO x1 VALUES(1, 2); |
+} { |
+ SELECT indirect(1); |
+ UPDATE x1 SET b = 3 WHERE a = 1; |
+} |
+ |
+catch {db close} |
+forcedelete test.db |
+sqlite3 db test.db |
+do_concat_test 2.2 { |
+ CREATE TABLE t1(a, b, PRIMARY KEY(b)); |
+ CREATE TABLE t2(a PRIMARY KEY, b); |
+ INSERT INTO t1 VALUES('string', 1); |
+ INSERT INTO t1 VALUES(4, 2); |
+ INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3); |
+} { |
+ INSERT INTO t2 VALUES('one', 'two'); |
+ INSERT INTO t2 VALUES(1, NULL); |
+ UPDATE t1 SET a = 5 WHERE a = 2; |
+} { |
+ DELETE FROM t2 WHERE a = 1; |
+ UPDATE t1 SET a = 4 WHERE a = 2; |
+ INSERT INTO t2 VALUES('x', 'y'); |
+} |
+ |
+do_test 2.3.0 { |
+ catch {db close} |
+ forcedelete test.db |
+ sqlite3 db test.db |
+ |
+ set sql1 "" |
+ set sql2 "" |
+ for {set i 1} {$i < 120} {incr i} { |
+ append sql1 "INSERT INTO x1 VALUES($i*4, $i);" |
+ } |
+ for {set i 1} {$i < 120} {incr i} { |
+ append sql2 "DELETE FROM x1 WHERE a = $i*4;" |
+ } |
+ set {} {} |
+} {} |
+do_concat_test 2.3 { |
+ CREATE TABLE x1(a PRIMARY KEY, b) |
+} $sql1 $sql2 $sql1 $sql2 |
+ |
+do_concat_test 2.4 { |
+ CREATE TABLE x2(a PRIMARY KEY, b); |
+ CREATE TABLE x3(a PRIMARY KEY, b); |
+ |
+ INSERT INTO x2 VALUES('a', 'b'); |
+ INSERT INTO x2 VALUES('x', 'y'); |
+ INSERT INTO x3 VALUES('a', 'b'); |
+} { |
+ INSERT INTO x2 VALUES('c', 'd'); |
+ INSERT INTO x3 VALUES('e', 'f'); |
+ INSERT INTO x3 VALUES('x', 'y'); |
+} |
+ |
+do_concat_test 2.5 { |
+ UPDATE x3 SET b = 'Y' WHERE a = 'x' |
+} { |
+ DELETE FROM x3 WHERE a = 'x' |
+} { |
+ DELETE FROM x2 WHERE a = 'a' |
+} { |
+ INSERT INTO x2 VALUES('a', 'B'); |
+} |
+ |
+for {set k 1} {$k <=10} {incr k} { |
+ do_test 2.6.$k.1 { |
+ drop_all_tables |
+ set sql1 "" |
+ set sql2 "" |
+ for {set i 1} {$i < 120} {incr i} { |
+ append sql1 "INSERT INTO x1 VALUES(randomblob(20+(random()%10)), $i);" |
+ } |
+ for {set i 1} {$i < 120} {incr i} { |
+ append sql2 "DELETE FROM x1 WHERE rowid = $i;" |
+ } |
+ set {} {} |
+ } {} |
+ do_concat_test 2.6.$k { |
+ CREATE TABLE x1(a PRIMARY KEY, b) |
+ } $sql1 $sql2 $sql1 $sql2 |
+} |
+ |
+for {set k 1} {$k <=10} {incr k} { |
+ do_test 2.7.$k.1 { |
+ drop_all_tables |
+ set sql1 "" |
+ set sql2 "" |
+ for {set i 1} {$i < 120} {incr i} { |
+ append sql1 { |
+ INSERT INTO x1 VALUES( |
+ CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END, |
+ CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END |
+ ); |
+ } |
+ } |
+ for {set i 1} {$i < 120} {incr i} { |
+ append sql2 "DELETE FROM x1 WHERE rowid = $i;" |
+ } |
+ set {} {} |
+ } {} |
+ do_concat_test 2.7.$k { |
+ CREATE TABLE x1(a PRIMARY KEY, b) |
+ } $sql1 $sql2 $sql1 $sql2 |
+} |
+ |
+ |
+#------------------------------------------------------------------------- |
+# Test that schema incompatibilities are detected correctly. |
+# |
+# session5-3.1: Incompatible number of columns. |
+# session5-3.2: Incompatible PK definition. |
+# |
+ |
+do_test 3.1 { |
+ db close |
+ forcedelete test.db |
+ sqlite3 db test.db |
+ |
+ execsql { CREATE TABLE t1(a PRIMARY KEY, b) } |
+ set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }] |
+ execsql { |
+ DROP TABLE t1; |
+ CREATE TABLE t1(a PRIMARY KEY, b, c); |
+ } |
+ set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3, 4) }] |
+ |
+ list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg |
+} {1 SQLITE_SCHEMA} |
+ |
+do_test 3.2 { |
+ db close |
+ forcedelete test.db |
+ sqlite3 db test.db |
+ |
+ execsql { CREATE TABLE t1(a PRIMARY KEY, b) } |
+ set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }] |
+ execsql { |
+ DROP TABLE t1; |
+ CREATE TABLE t1(a, b PRIMARY KEY); |
+ } |
+ set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3) }] |
+ |
+ list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg |
+} {1 SQLITE_SCHEMA} |
+ |
+#------------------------------------------------------------------------- |
+# Test that concat() handles these properly: |
+# |
+# session5-4.1: INSERT + INSERT |
+# session5-4.2: UPDATE + INSERT |
+# session5-4.3: DELETE + UPDATE |
+# session5-4.4: DELETE + DELETE |
+# |
+ |
+proc do_concat_test2 {tn sql1 sqlX sql2 expected} { |
+ sqlite3session S db main ; S attach * |
+ execsql $sql1 |
+ set ::c1 [S changeset] |
+ S delete |
+ |
+ execsql $sqlX |
+ |
+ sqlite3session S db main ; S attach * |
+ execsql $sql2 |
+ set ::c2 [S changeset] |
+ S delete |
+ |
+ uplevel do_test $tn [list { |
+ changeset_to_list [sqlite3changeset_concat $::c1 $::c2] |
+ }] [list [normalize_list $expected]] |
+} |
+ |
+drop_all_tables db |
+do_concat_test2 4.1 { |
+ CREATE TABLE t1(a PRIMARY KEY, b); |
+ INSERT INTO t1 VALUES('key', 'value'); |
+} { |
+ DELETE FROM t1 WHERE a = 'key'; |
+} { |
+ INSERT INTO t1 VALUES('key', 'xxx'); |
+} { |
+ {INSERT t1 0 X. {} {t key t value}} |
+} |
+do_concat_test2 4.2 { |
+ UPDATE t1 SET b = 'yyy'; |
+} { |
+ DELETE FROM t1 WHERE a = 'key'; |
+} { |
+ INSERT INTO t1 VALUES('key', 'value'); |
+} { |
+ {UPDATE t1 0 X. {t key t xxx} {{} {} t yyy}} |
+} |
+do_concat_test2 4.3 { |
+ DELETE FROM t1 WHERE a = 'key'; |
+} { |
+ INSERT INTO t1 VALUES('key', 'www'); |
+} { |
+ UPDATE t1 SET b = 'valueX' WHERE a = 'key'; |
+} { |
+ {DELETE t1 0 X. {t key t value} {}} |
+} |
+do_concat_test2 4.4 { |
+ DELETE FROM t1 WHERE a = 'key'; |
+} { |
+ INSERT INTO t1 VALUES('key', 'ttt'); |
+} { |
+ DELETE FROM t1 WHERE a = 'key'; |
+} { |
+ {DELETE t1 0 X. {t key t valueX} {}} |
+} |
+ |
+finish_test |