1# 2021 Februar 20
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 sessionnoop
22
23#-------------------------------------------------------------------------
24# Test plan:
25#
26#   1.*: Test that concatenating changesets cannot produce a noop UPDATE.
27#   2.*: Test that rebasing changesets cannot produce a noop UPDATE.
28#   3.*: Test that sqlite3changeset_apply() ignores noop UPDATE changes.
29#
30
31do_execsql_test 1.0 {
32  CREATE TABLE t1(a PRIMARY KEY, b, c, d);
33  INSERT INTO t1 VALUES(1, 1, 1, 1);
34  INSERT INTO t1 VALUES(2, 2, 2, 2);
35  INSERT INTO t1 VALUES(3, 3, 3, 3);
36}
37
38proc do_concat_test {tn sql1 sql2 res} {
39  uplevel [list do_test $tn [subst -nocommands {
40    set C1 [changeset_from_sql {$sql1}]
41    set C2 [changeset_from_sql {$sql2}]
42    set C3 [sqlite3changeset_concat [set C1] [set C2]]
43    set got [list]
44    sqlite3session_foreach elem [set C3] { lappend got [set elem] }
45    set got
46  }] [list {*}$res]]
47}
48
49do_concat_test 1.1 {
50  UPDATE t1 SET c=c+1;
51} {
52  UPDATE t1 SET c=c-1;
53} {
54}
55
56#-------------------------------------------------------------------------
57reset_db
58do_execsql_test 2.0 {
59  CREATE TABLE t1(a PRIMARY KEY, b, c);
60  INSERT INTO t1 VALUES(1, 1, 1);
61  INSERT INTO t1 VALUES(2, 2, 2);
62  INSERT INTO t1 VALUES(3, 3, 3);
63}
64
65proc do_rebase_test {tn sql_local sql_remote conflict_res expected} {
66  proc xConflict {args} [list return $conflict_res]
67
68  uplevel [list \
69    do_test $tn [subst -nocommands {
70      execsql BEGIN
71        set c_remote [changeset_from_sql {$sql_remote}]
72      execsql ROLLBACK
73
74      execsql BEGIN
75        set c_local [changeset_from_sql {$sql_local}]
76        set base [sqlite3changeset_apply_v2 db [set c_remote] xConflict]
77      execsql ROLLBACK
78
79      sqlite3rebaser_create R
80      R config [set base]
81      set res [list]
82      sqlite3session_foreach elem [R rebase [set c_local]] {
83        lappend res [set elem]
84      }
85      R delete
86      set res
87    }] [list {*}$expected]
88  ]
89}
90
91do_rebase_test 2.1 {
92  UPDATE t1 SET c=2 WHERE a=1;              -- local
93} {
94  UPDATE t1 SET c=3 WHERE a=1;              -- remote
95} OMIT {
96  {UPDATE t1 0 X.. {i 1 {} {} i 3} {{} {} {} {} i 2}}
97}
98
99do_rebase_test 2.2 {
100  UPDATE t1 SET c=2 WHERE a=1;              -- local
101} {
102  UPDATE t1 SET c=3 WHERE a=1;              -- remote
103} REPLACE {
104}
105
106do_rebase_test 2.3.1 {
107  UPDATE t1 SET c=4 WHERE a=1;              -- local
108} {
109  UPDATE t1 SET c=4 WHERE a=1               -- remote
110} OMIT {
111  {UPDATE t1 0 X.. {i 1 {} {} i 4} {{} {} {} {} i 4}}
112}
113
114do_rebase_test 2.3.2 {
115  UPDATE t1 SET c=5 WHERE a=1;              -- local
116} {
117  UPDATE t1 SET c=5 WHERE a=1               -- remote
118} REPLACE {
119}
120
121#-------------------------------------------------------------------------
122#
123reset_db
124do_execsql_test 3.0 {
125  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
126  INSERT INTO t1 VALUES(1, 1, 1);
127  INSERT INTO t1 VALUES(2, 2, 2);
128  INSERT INTO t1 VALUES(3, 3, 3);
129  INSERT INTO t1 VALUES(4, 4, 4);
130}
131
132# Arg $pkstr contains one character for each column in the table. An
133# "X" for PK column, or a "." for a non-PK.
134#
135proc mk_tbl_header {name pkstr} {
136  set ret [binary format H2c 54 [string length $pkstr]]
137  foreach i [split $pkstr {}] {
138    if {$i=="X"} {
139      append ret [binary format H2 01]
140    } else {
141      if {$i!="."} {error "bad pkstr: $pkstr ($i)"}
142      append ret [binary format H2 00]
143    }
144  }
145  append ret $name
146  append ret [binary format H2 00]
147  set ret
148}
149
150proc mk_update_change {args} {
151  set ret [binary format H2H2 17 00]
152  foreach a $args {
153    if {$a==""} {
154      append ret [binary format H2 00]
155    } else {
156      append ret [binary format H2W 01 $a]
157    }
158  }
159  set ret
160}
161
162proc xConflict {args} { return "ABORT" }
163do_test 3.1 {
164  set    C [mk_tbl_header t1 X..]
165  append C [mk_update_change    1 {} 1   {} {}  500]
166  append C [mk_update_change    2 {} {}  {} {}  {}]
167  append C [mk_update_change    3 3  {}  {} 600 {}]
168  append C [mk_update_change    4 {} {}  {} {}  {}]
169
170  sqlite3changeset_apply_v2 db $C xConflict
171} {}
172do_execsql_test 3.2 {
173  SELECT * FROM t1
174} {
175  1 1 500
176  2 2 2
177  3 600 3
178  4 4 4
179}
180
181
182
183
184
185
186finish_test
187
188