1# 2015 February 16
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#
12
13if {![info exists testdir]} {
14  set testdir [file join [file dirname [info script]] .. .. test]
15}
16source $testdir/tester.tcl
17set ::testprefix rbu11
18
19
20#--------------------------------------------------------------------
21# Test that the xAccess() method of an rbu vfs handles queries other
22# than SQLITE_ACCESS_EXISTS correctly. The test code below causes
23# SQLite to call xAccess(SQLITE_ACCESS_READWRITE) on the directory
24# path argument passed to "PRAGMA temp_store_directory".
25#
26do_test 1.1 {
27  sqlite3rbu_create_vfs -default rbu ""
28  reset_db
29  catchsql { PRAGMA temp_store_directory = '/no/such/directory' }
30} {1 {not a writable directory}}
31
32do_test 1.2 {
33  catchsql " PRAGMA temp_store_directory = '[pwd]' "
34} {0 {}}
35
36do_test 1.3 {
37  catchsql " PRAGMA temp_store_directory = '' "
38} {0 {}}
39
40do_test 1.4 {
41  db close
42  sqlite3rbu_destroy_vfs rbu
43} {}
44
45#--------------------------------------------------------------------
46# Try to trick rbu into operating on a database opened in wal mode.
47#
48reset_db
49do_execsql_test 2.1 {
50  CREATE TABLE t1(a PRIMARY KEY, b, c);
51  INSERT INTO t1 VALUES(1, 2, 3);
52  PRAGMA journal_mode = 'wal';
53  CREATE TABLE t2(d PRIMARY KEY, e, f);
54} {wal}
55
56do_test 2.2 {
57  db_save
58  db close
59
60  forcedelete rbu.db
61  sqlite3 dbo rbu.db
62  dbo eval {
63    CREATE TABLE data_t1(a, b, c, rbu_control);
64    INSERT INTO data_t1 VALUES(4, 5, 6, 0);
65    INSERT INTO data_t1 VALUES(7, 8, 9, 0);
66  }
67  dbo close
68
69  db_restore
70  hexio_write test.db 18 0101
71  file exists test.db-wal
72} {1}
73
74do_test 2.3 {
75  sqlite3rbu rbu test.db rbu.db
76  rbu step
77} {SQLITE_ERROR}
78
79do_test 2.4 {
80  list [catch {rbu close} msg] $msg
81} {1 {SQLITE_ERROR - cannot update wal mode database}}
82
83#--------------------------------------------------------------------
84# Test a constraint violation message with an unusual table name.
85# Specifically, one for which the first character is a codepoint
86# smaller than 30 (character '0').
87#
88reset_db
89do_execsql_test 3.1 {
90  CREATE TABLE "(t1)"(a PRIMARY KEY, b, c);
91  INSERT INTO "(t1)" VALUES(1, 2, 3);
92  INSERT INTO "(t1)" VALUES(4, 5, 6);
93}
94db close
95
96do_test 3.2 {
97  forcedelete rbu.db
98  sqlite3 dbo rbu.db
99  dbo eval {
100    CREATE TABLE "data_(t1)"(a, b, c, rbu_control);
101    INSERT INTO "data_(t1)" VALUES(4, 8, 9, 0);
102  }
103  dbo close
104
105  sqlite3rbu rbu test.db rbu.db
106  rbu step
107  rbu step
108} {SQLITE_CONSTRAINT}
109
110do_test 3.3 {
111  list [catch {rbu close} msg] $msg
112} {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: (t1).a}}
113
114#--------------------------------------------------------------------
115# Check that once an RBU update has been applied, attempting to apply
116# it a second time is a no-op (as the state stored in the RBU database is
117# "all steps completed").
118#
119reset_db
120do_execsql_test 4.1 {
121  CREATE TABLE "(t1)"(a, b, c, PRIMARY KEY(c, b, a));
122  INSERT INTO "(t1)" VALUES(1, 2, 3);
123  INSERT INTO "(t1)" VALUES(4, 5, 6);
124}
125db close
126
127do_test 4.2 {
128  forcedelete rbu.db
129  sqlite3 dbo rbu.db
130  dbo eval {
131    CREATE TABLE "data_(t1)"(a, b, c, rbu_control);
132    INSERT INTO "data_(t1)" VALUES(7, 8, 9, 0);
133    INSERT INTO "data_(t1)" VALUES(1, 2, 3, 1);
134  }
135  dbo close
136
137  sqlite3rbu rbu test.db rbu.db
138  while {[rbu step]=="SQLITE_OK"} { }
139  rbu close
140} {SQLITE_DONE}
141
142do_test 4.3 {
143  sqlite3rbu rbu test.db rbu.db
144  rbu step
145} {SQLITE_DONE}
146
147do_test 4.4 {
148  rbu close
149} {SQLITE_DONE}
150
151do_test 4.5.1 {
152  sqlite3 dbo rbu.db
153  dbo eval { INSERT INTO rbu_state VALUES(100, 100) }
154  dbo close
155  sqlite3rbu rbu test.db rbu.db
156  rbu step
157} {SQLITE_CORRUPT}
158do_test 4.5.2 {
159  list [catch {rbu close} msg] $msg
160} {1 SQLITE_CORRUPT}
161do_test 4.5.3 {
162  sqlite3 dbo rbu.db
163  dbo eval { DELETE FROM rbu_state WHERE k = 100 }
164  dbo close
165} {}
166
167# Also, check that an invalid state value in the rbu_state table is
168# detected and reported as corruption.
169do_test 4.6.1 {
170  sqlite3 dbo rbu.db
171  dbo eval { UPDATE rbu_state SET v = v*-1 WHERE k = 1 }
172  dbo close
173  sqlite3rbu rbu test.db rbu.db
174  rbu step
175} {SQLITE_CORRUPT}
176do_test 4.6.2 {
177  list [catch {rbu close} msg] $msg
178} {1 SQLITE_CORRUPT}
179do_test 4.6.3 {
180  sqlite3 dbo rbu.db
181  dbo eval { UPDATE rbu_state SET v = v*-1 WHERE k = 1 }
182  dbo close
183} {}
184
185do_test 4.7.1 {
186  sqlite3 dbo rbu.db
187  dbo eval { UPDATE rbu_state SET v = 1 WHERE k = 1 }
188  dbo eval { UPDATE rbu_state SET v = 'nosuchtable' WHERE k = 2 }
189  dbo close
190  sqlite3rbu rbu test.db rbu.db
191  rbu step
192} {SQLITE_ERROR}
193do_test 4.7.2 {
194  list [catch {rbu close} msg] $msg
195} {1 {SQLITE_ERROR - rbu_state mismatch error}}
196
197finish_test
198