1*1e25d20cSdan# 2021 Februar 20
2*1e25d20cSdan#
3*1e25d20cSdan# The author disclaims copyright to this source code.  In place of
4*1e25d20cSdan# a legal notice, here is a blessing:
5*1e25d20cSdan#
6*1e25d20cSdan#    May you do good and not evil.
7*1e25d20cSdan#    May you find forgiveness for yourself and forgive others.
8*1e25d20cSdan#    May you share freely, never taking more than you give.
9*1e25d20cSdan#
10*1e25d20cSdan#***********************************************************************
11*1e25d20cSdan# This file implements regression tests for SQLite library.
12*1e25d20cSdan#
13*1e25d20cSdan
14*1e25d20cSdanif {![info exists testdir]} {
15*1e25d20cSdan  set testdir [file join [file dirname [info script]] .. .. test]
16*1e25d20cSdan}
17*1e25d20cSdansource [file join [file dirname [info script]] session_common.tcl]
18*1e25d20cSdansource $testdir/tester.tcl
19*1e25d20cSdanifcapable !session {finish_test; return}
20*1e25d20cSdan
21*1e25d20cSdanset testprefix sessionnoop
22*1e25d20cSdan
23*1e25d20cSdan#-------------------------------------------------------------------------
24*1e25d20cSdan# Test plan:
25*1e25d20cSdan#
26*1e25d20cSdan#   1.*: Test that concatenating changesets cannot produce a noop UPDATE.
27*1e25d20cSdan#   2.*: Test that rebasing changesets cannot produce a noop UPDATE.
28*1e25d20cSdan#   3.*: Test that sqlite3changeset_apply() ignores noop UPDATE changes.
29*1e25d20cSdan#
30*1e25d20cSdan
31*1e25d20cSdando_execsql_test 1.0 {
32*1e25d20cSdan  CREATE TABLE t1(a PRIMARY KEY, b, c, d);
33*1e25d20cSdan  INSERT INTO t1 VALUES(1, 1, 1, 1);
34*1e25d20cSdan  INSERT INTO t1 VALUES(2, 2, 2, 2);
35*1e25d20cSdan  INSERT INTO t1 VALUES(3, 3, 3, 3);
36*1e25d20cSdan}
37*1e25d20cSdan
38*1e25d20cSdanproc do_concat_test {tn sql1 sql2 res} {
39*1e25d20cSdan  uplevel [list do_test $tn [subst -nocommands {
40*1e25d20cSdan    set C1 [changeset_from_sql {$sql1}]
41*1e25d20cSdan    set C2 [changeset_from_sql {$sql2}]
42*1e25d20cSdan    set C3 [sqlite3changeset_concat [set C1] [set C2]]
43*1e25d20cSdan    set got [list]
44*1e25d20cSdan    sqlite3session_foreach elem [set C3] { lappend got [set elem] }
45*1e25d20cSdan    set got
46*1e25d20cSdan  }] [list {*}$res]]
47*1e25d20cSdan}
48*1e25d20cSdan
49*1e25d20cSdando_concat_test 1.1 {
50*1e25d20cSdan  UPDATE t1 SET c=c+1;
51*1e25d20cSdan} {
52*1e25d20cSdan  UPDATE t1 SET c=c-1;
53*1e25d20cSdan} {
54*1e25d20cSdan}
55*1e25d20cSdan
56*1e25d20cSdan#-------------------------------------------------------------------------
57*1e25d20cSdanreset_db
58*1e25d20cSdando_execsql_test 2.0 {
59*1e25d20cSdan  CREATE TABLE t1(a PRIMARY KEY, b, c);
60*1e25d20cSdan  INSERT INTO t1 VALUES(1, 1, 1);
61*1e25d20cSdan  INSERT INTO t1 VALUES(2, 2, 2);
62*1e25d20cSdan  INSERT INTO t1 VALUES(3, 3, 3);
63*1e25d20cSdan}
64*1e25d20cSdan
65*1e25d20cSdanproc do_rebase_test {tn sql_local sql_remote conflict_res expected} {
66*1e25d20cSdan  proc xConflict {args} [list return $conflict_res]
67*1e25d20cSdan
68*1e25d20cSdan  uplevel [list \
69*1e25d20cSdan    do_test $tn [subst -nocommands {
70*1e25d20cSdan      execsql BEGIN
71*1e25d20cSdan        set c_remote [changeset_from_sql {$sql_remote}]
72*1e25d20cSdan      execsql ROLLBACK
73*1e25d20cSdan
74*1e25d20cSdan      execsql BEGIN
75*1e25d20cSdan        set c_local [changeset_from_sql {$sql_local}]
76*1e25d20cSdan        set base [sqlite3changeset_apply_v2 db [set c_remote] xConflict]
77*1e25d20cSdan      execsql ROLLBACK
78*1e25d20cSdan
79*1e25d20cSdan      sqlite3rebaser_create R
80*1e25d20cSdan      R config [set base]
81*1e25d20cSdan      set res [list]
82*1e25d20cSdan      sqlite3session_foreach elem [R rebase [set c_local]] {
83*1e25d20cSdan        lappend res [set elem]
84*1e25d20cSdan      }
85*1e25d20cSdan      R delete
86*1e25d20cSdan      set res
87*1e25d20cSdan    }] [list {*}$expected]
88*1e25d20cSdan  ]
89*1e25d20cSdan}
90*1e25d20cSdan
91*1e25d20cSdando_rebase_test 2.1 {
92*1e25d20cSdan  UPDATE t1 SET c=2 WHERE a=1;              -- local
93*1e25d20cSdan} {
94*1e25d20cSdan  UPDATE t1 SET c=3 WHERE a=1;              -- remote
95*1e25d20cSdan} OMIT {
96*1e25d20cSdan  {UPDATE t1 0 X.. {i 1 {} {} i 3} {{} {} {} {} i 2}}
97*1e25d20cSdan}
98*1e25d20cSdan
99*1e25d20cSdando_rebase_test 2.2 {
100*1e25d20cSdan  UPDATE t1 SET c=2 WHERE a=1;              -- local
101*1e25d20cSdan} {
102*1e25d20cSdan  UPDATE t1 SET c=3 WHERE a=1;              -- remote
103*1e25d20cSdan} REPLACE {
104*1e25d20cSdan}
105*1e25d20cSdan
106*1e25d20cSdando_rebase_test 2.3.1 {
107*1e25d20cSdan  UPDATE t1 SET c=4 WHERE a=1;              -- local
108*1e25d20cSdan} {
109*1e25d20cSdan  UPDATE t1 SET c=4 WHERE a=1               -- remote
110*1e25d20cSdan} OMIT {
111*1e25d20cSdan  {UPDATE t1 0 X.. {i 1 {} {} i 4} {{} {} {} {} i 4}}
112*1e25d20cSdan}
113*1e25d20cSdan
114*1e25d20cSdando_rebase_test 2.3.2 {
115*1e25d20cSdan  UPDATE t1 SET c=5 WHERE a=1;              -- local
116*1e25d20cSdan} {
117*1e25d20cSdan  UPDATE t1 SET c=5 WHERE a=1               -- remote
118*1e25d20cSdan} REPLACE {
119*1e25d20cSdan}
120*1e25d20cSdan
121*1e25d20cSdan#-------------------------------------------------------------------------
122*1e25d20cSdan#
123*1e25d20cSdanreset_db
124*1e25d20cSdando_execsql_test 3.0 {
125*1e25d20cSdan  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
126*1e25d20cSdan  INSERT INTO t1 VALUES(1, 1, 1);
127*1e25d20cSdan  INSERT INTO t1 VALUES(2, 2, 2);
128*1e25d20cSdan  INSERT INTO t1 VALUES(3, 3, 3);
129*1e25d20cSdan  INSERT INTO t1 VALUES(4, 4, 4);
130*1e25d20cSdan}
131*1e25d20cSdan
132*1e25d20cSdan# Arg $pkstr contains one character for each column in the table. An
133*1e25d20cSdan# "X" for PK column, or a "." for a non-PK.
134*1e25d20cSdan#
135*1e25d20cSdanproc mk_tbl_header {name pkstr} {
136*1e25d20cSdan  set ret [binary format H2c 54 [string length $pkstr]]
137*1e25d20cSdan  foreach i [split $pkstr {}] {
138*1e25d20cSdan    if {$i=="X"} {
139*1e25d20cSdan      append ret [binary format H2 01]
140*1e25d20cSdan    } else {
141*1e25d20cSdan      if {$i!="."} {error "bad pkstr: $pkstr ($i)"}
142*1e25d20cSdan      append ret [binary format H2 00]
143*1e25d20cSdan    }
144*1e25d20cSdan  }
145*1e25d20cSdan  append ret $name
146*1e25d20cSdan  append ret [binary format H2 00]
147*1e25d20cSdan  set ret
148*1e25d20cSdan}
149*1e25d20cSdan
150*1e25d20cSdanproc mk_update_change {args} {
151*1e25d20cSdan  set ret [binary format H2H2 17 00]
152*1e25d20cSdan  foreach a $args {
153*1e25d20cSdan    if {$a==""} {
154*1e25d20cSdan      append ret [binary format H2 00]
155*1e25d20cSdan    } else {
156*1e25d20cSdan      append ret [binary format H2W 01 $a]
157*1e25d20cSdan    }
158*1e25d20cSdan  }
159*1e25d20cSdan  set ret
160*1e25d20cSdan}
161*1e25d20cSdan
162*1e25d20cSdanproc xConflict {args} { return "ABORT" }
163*1e25d20cSdando_test 3.1 {
164*1e25d20cSdan  set    C [mk_tbl_header t1 X..]
165*1e25d20cSdan  append C [mk_update_change    1 {} 1   {} {}  500]
166*1e25d20cSdan  append C [mk_update_change    2 {} {}  {} {}  {}]
167*1e25d20cSdan  append C [mk_update_change    3 3  {}  {} 600 {}]
168*1e25d20cSdan  append C [mk_update_change    4 {} {}  {} {}  {}]
169*1e25d20cSdan
170*1e25d20cSdan  sqlite3changeset_apply_v2 db $C xConflict
171*1e25d20cSdan} {}
172*1e25d20cSdando_execsql_test 3.2 {
173*1e25d20cSdan  SELECT * FROM t1
174*1e25d20cSdan} {
175*1e25d20cSdan  1 1 500
176*1e25d20cSdan  2 2 2
177*1e25d20cSdan  3 600 3
178*1e25d20cSdan  4 4 4
179*1e25d20cSdan}
180*1e25d20cSdan
181*1e25d20cSdan
182*1e25d20cSdan
183*1e25d20cSdan
184*1e25d20cSdan
185*1e25d20cSdan
186*1e25d20cSdanfinish_test
187*1e25d20cSdan
188