wasCSharpSQLite – Blame information for rev 7
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | # 2011 April 22 |
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 | |||
13 | set testdir [file dirname $argv0] |
||
14 | source $testdir/tester.tcl |
||
15 | |||
16 | # Test organization: |
||
17 | # |
||
18 | # 1.*: That file names are correctly extracted from URIs. |
||
19 | # 2.*: That URI options (query parameters) are correctly extracted from URIs. |
||
20 | # 3.*: That specifying an unknown VFS causes an error. |
||
21 | # 4.*: Tests for specifying other options (other than "vfs"). |
||
22 | # 5.*: Test using a different VFS with an attached database. |
||
23 | # 6.*: Test that authorities other than "" and localhost cause errors. |
||
24 | # 7.*: Test that a read-write db can be attached to a read-only connection. |
||
25 | # |
||
26 | |||
27 | set testprefix uri |
||
28 | db close |
||
29 | sqlite3_shutdown |
||
30 | sqlite3_config_uri 1 |
||
31 | |||
32 | #------------------------------------------------------------------------- |
||
33 | # Test that file names are correctly extracted from URIs. |
||
34 | # |
||
35 | foreach {tn uri file} { |
||
36 | 1 test.db test.db |
||
37 | 2 file:test.db test.db |
||
38 | 3 file://PWD/test.db test.db |
||
39 | 4 file:PWD/test.db test.db |
||
40 | 5 file:test.db?mork=1 test.db |
||
41 | 6 file:test.db?mork=1&tonglor=2 test.db |
||
42 | 7 file:test.db?mork=1#boris test.db |
||
43 | 8 file:test.db#boris test.db |
||
44 | 9 test.db#boris test.db#boris |
||
45 | 10 file:test%2Edb test.db |
||
46 | 11 file file |
||
47 | 12 http_test.db http_test.db |
||
48 | 13 file:test.db%00extra test.db |
||
49 | 14 file:testdb%00.db%00extra testdb |
||
50 | |||
51 | 15 test.db?mork=1#boris test.db?mork=1#boris |
||
52 | 16 file://localhostPWD/test.db%3Fhello test.db?hello |
||
53 | } { |
||
54 | |||
55 | if {$tcl_platform(platform)=="windows"} { |
||
56 | if {$tn>14} break |
||
57 | set uri [string map [list PWD /[pwd]] $uri] |
||
58 | } else { |
||
59 | set uri [string map [list PWD [pwd]] $uri] |
||
60 | } |
||
61 | |||
62 | if {[file isdir $file]} {error "$file is a directory"} |
||
63 | forcedelete $file |
||
64 | do_test 1.$tn.1 { file exists $file } 0 |
||
65 | set DB [sqlite3_open $uri] |
||
66 | do_test 1.$tn.2 { file exists $file } 1 |
||
67 | sqlite3_close $DB |
||
68 | forcedelete $file |
||
69 | |||
70 | do_test 1.$tn.3 { file exists $file } 0 |
||
71 | sqlite3 db xxx.db |
||
72 | catchsql { ATTACH $uri AS aux } |
||
73 | do_test 1.$tn.4 { file exists $file } 1 |
||
74 | db close |
||
75 | } |
||
76 | |||
77 | #------------------------------------------------------------------------- |
||
78 | # Test that URI query parameters are passed through to the VFS layer |
||
79 | # correctly. |
||
80 | # |
||
81 | testvfs tvfs2 |
||
82 | testvfs tvfs -default 1 |
||
83 | tvfs filter xOpen |
||
84 | tvfs script open_method |
||
85 | proc open_method {method file arglist} { |
||
86 | set ::arglist $arglist |
||
87 | } |
||
88 | foreach {tn uri kvlist} { |
||
89 | 1 file:test.db?hello=world {hello world} |
||
90 | 2 file:test.db?hello&world {hello {} world {}} |
||
91 | 3 file:test.db?hello=1&world=2&vfs=tvfs {hello 1 world 2 vfs tvfs} |
||
92 | 4 file:test.db?hello=1&world=2&vfs=tvfs2 {} |
||
93 | 5 file:test.db?%68%65%6C%6C%6F=%77%6F%72%6C%64 {hello world} |
||
94 | 6 file:testdb%00.db?hello%00extra=world%00ex {hello world} |
||
95 | 7 file:testdb%00.db?hello%00=world%00 {hello world} |
||
96 | 8 file:testdb%00.db?=world&xyz=abc {xyz abc} |
||
97 | 9 file:test.db?%00hello=world&xyz=abc {xyz abc} |
||
98 | 10 file:test.db?hello=%00world&xyz= {hello {} xyz {}} |
||
99 | 11 file:test.db?=#ravada {} |
||
100 | 12 file:test.db?&&&&&&&&hello=world&&&&&&& {hello world} |
||
101 | |||
102 | 13 test.db?&&&&&&&&hello=world&&&&&&& {} |
||
103 | 14 http:test.db?hello&world {} |
||
104 | } { |
||
105 | |||
106 | if {$tcl_platform(platform) == "windows" && $tn>12} { |
||
107 | continue |
||
108 | } |
||
109 | |||
110 | set ::arglist "" |
||
111 | set DB [sqlite3_open $uri] |
||
112 | do_test 2.$tn.1 { set ::arglist } $kvlist |
||
113 | sqlite3_close $DB |
||
114 | |||
115 | sqlite3 db xxx.db |
||
116 | set ::arglist "" |
||
117 | execsql { ATTACH $uri AS aux } |
||
118 | do_test 2.$tn.2 { set ::arglist } $kvlist |
||
119 | db close |
||
120 | } |
||
121 | tvfs delete |
||
122 | tvfs2 delete |
||
123 | |||
124 | #------------------------------------------------------------------------- |
||
125 | # Test that specifying a non-existent VFS raises an error. |
||
126 | # |
||
127 | do_test 3.1 { |
||
128 | list [catch { sqlite3 db "file:test.db?vfs=nosuchvfs" } msg] $msg |
||
129 | } {1 {no such vfs: nosuchvfs}} |
||
130 | |||
131 | #------------------------------------------------------------------------- |
||
132 | # Test some of the other options (other than "vfs"). |
||
133 | # |
||
134 | foreach {tn mode create_ok write_ok readonly_ok} { |
||
135 | 1 ro 0 0 1 |
||
136 | 2 rw 0 1 0 |
||
137 | 3 rwc 1 1 0 |
||
138 | } { |
||
139 | catch { db close } |
||
140 | forcedelete test.db |
||
141 | |||
142 | set A(1) {0 {}} |
||
143 | set A(0) {1 {unable to open database file}} |
||
144 | do_test 4.1.$tn.1 { |
||
145 | list [catch {sqlite3 db "file:test.db?mode=$mode"} msg] $msg |
||
146 | } $A($create_ok) |
||
147 | |||
148 | catch { db close } |
||
149 | forcedelete test.db |
||
150 | sqlite3 db test.db |
||
151 | db eval { CREATE TABLE t1(a, b) } |
||
152 | db close |
||
153 | |||
154 | set A(1) {0 {}} |
||
155 | set A(0) {1 {attempt to write a readonly database}} |
||
156 | do_test 4.1.$tn.2 { |
||
157 | sqlite3 db "file:test.db?mode=$mode" |
||
158 | catchsql { INSERT INTO t1 VALUES(1, 2) } |
||
159 | } $A($write_ok) |
||
160 | |||
161 | set A(1) {0 {}} |
||
162 | set A(0) [list 1 "access mode not allowed: $mode"] |
||
163 | do_test 4.1.$tn.3 { |
||
164 | list [catch {sqlite3 db "file:test.db?mode=$mode" -readonly 1} msg] $msg |
||
165 | } $A($readonly_ok) |
||
166 | } |
||
167 | |||
168 | set orig [sqlite3_enable_shared_cache] |
||
169 | foreach {tn options sc_default is_shared} { |
||
170 | 1 "" 1 1 |
||
171 | 2 "cache=private" 1 0 |
||
172 | 3 "cache=shared" 1 1 |
||
173 | 4 "" 0 0 |
||
174 | 5 "cache=private" 0 0 |
||
175 | 6 "cache=shared" 0 1 |
||
176 | } { |
||
177 | catch { db close } |
||
178 | forcedelete test.db |
||
179 | |||
180 | sqlite3_enable_shared_cache 1 |
||
181 | sqlite3 db2 test.db |
||
182 | db2 eval {CREATE TABLE t1(a, b)} |
||
183 | |||
184 | sqlite3_enable_shared_cache $sc_default |
||
185 | sqlite3 db "file:test.db?$options" |
||
186 | db eval {SELECT * FROM t1} |
||
187 | |||
188 | set A(1) {1 {database table is locked: t1}} |
||
189 | set A(0) {0 {}} |
||
190 | do_test 4.2.$tn { |
||
191 | db2 eval {BEGIN; INSERT INTO t1 VALUES(1, 2);} |
||
192 | catchsql { SELECT * FROM t1 } |
||
193 | } $A($is_shared) |
||
194 | |||
195 | db2 close |
||
196 | } |
||
197 | |||
198 | do_test 4.3.1 { |
||
199 | list [catch {sqlite3 db "file:test.db?mode=rc"} msg] $msg |
||
200 | } {1 {no such access mode: rc}} |
||
201 | do_test 4.3.2 { |
||
202 | list [catch {sqlite3 db "file:test.db?cache=public"} msg] $msg |
||
203 | } {1 {no such cache mode: public}} |
||
204 | |||
205 | #------------------------------------------------------------------------- |
||
206 | # Test that things work if an ATTACHed database uses a different VFS than |
||
207 | # the main database. The important point is that for all operations |
||
208 | # involving the ATTACHed database, the correct versions of the following |
||
209 | # VFS are used for all operations involving the attached database. |
||
210 | # |
||
211 | # xOpen |
||
212 | # xDelete |
||
213 | # xAccess |
||
214 | # xFullPathname |
||
215 | # |
||
216 | |||
217 | # This block of code creates two VFS - "tvfs1" and "tvfs2". Each time one |
||
218 | # of the above methods is called using "tvfs1", global variable ::T1(X) is |
||
219 | # set, where X is the file-name the method is called on. Calls to the above |
||
220 | # methods using "tvfs2" set entries in the global T2 array. |
||
221 | # |
||
222 | testvfs tvfs1 |
||
223 | tvfs1 filter {xOpen xDelete xAccess xFullPathname} |
||
224 | tvfs1 script tvfs1_callback |
||
225 | proc tvfs1_callback {method filename args} { |
||
226 | set ::T1([file tail $filename]) 1 |
||
227 | } |
||
228 | testvfs tvfs2 |
||
229 | tvfs2 filter {xOpen xDelete xAccess xFullPathname} |
||
230 | tvfs2 script tvfs2_callback |
||
231 | proc tvfs2_callback {method filename args} { |
||
232 | set ::T2([file tail $filename]) 1 |
||
233 | } |
||
234 | |||
235 | catch {db close} |
||
236 | eval forcedelete [glob test.db*] |
||
237 | do_test 5.1.1 { |
||
238 | sqlite3 db file:test.db1?vfs=tvfs1 |
||
239 | execsql { |
||
240 | ATTACH 'file:test.db2?vfs=tvfs2' AS aux; |
||
241 | PRAGMA main.journal_mode = PERSIST; |
||
242 | PRAGMA aux.journal_mode = PERSIST; |
||
243 | CREATE TABLE t1(a, b); |
||
244 | CREATE TABLE aux.t2(a, b); |
||
245 | PRAGMA main.journal_mode = WAL; |
||
246 | PRAGMA aux.journal_mode = WAL; |
||
247 | INSERT INTO t1 VALUES('x', 'y'); |
||
248 | INSERT INTO t2 VALUES('x', 'y'); |
||
249 | } |
||
250 | lsort [array names ::T1] |
||
251 | } {test.db1 test.db1-journal test.db1-wal} |
||
252 | |||
253 | do_test 5.1.2 { |
||
254 | lsort [array names ::T2] |
||
255 | } {test.db2 test.db2-journal test.db2-wal} |
||
256 | |||
257 | db close |
||
258 | tvfs1 delete |
||
259 | tvfs2 delete |
||
260 | |||
261 | #------------------------------------------------------------------------- |
||
262 | # Check that only "" and "localhost" are acceptable as authorities. |
||
263 | # |
||
264 | catch {db close} |
||
265 | foreach {tn uri res} { |
||
266 | 1 "file://localhost/PWD/test.db" {not an error} |
||
267 | 2 "file:///PWD/test.db" {not an error} |
||
268 | 3 "file:/PWD/test.db" {not an error} |
||
269 | 4 "file://l%6Fcalhost/PWD/test.db" {invalid uri authority: l%6Fcalhost} |
||
270 | 5 "file://lbcalhost/PWD/test.db" {invalid uri authority: lbcalhost} |
||
271 | 6 "file://x/PWD/test.db" {invalid uri authority: x} |
||
272 | } { |
||
273 | |||
274 | if {$tcl_platform(platform)=="windows"} { |
||
275 | set uri [string map [list PWD [string range [pwd] 3 end]] $uri] |
||
276 | } else { |
||
277 | set uri [string map [list PWD [string range [pwd] 1 end]] $uri] |
||
278 | } |
||
279 | |||
280 | do_test 6.$tn { |
||
281 | set DB [sqlite3_open $uri] |
||
282 | sqlite3_errmsg $DB |
||
283 | } $res |
||
284 | catch { sqlite3_close $DB } |
||
285 | } |
||
286 | |||
287 | forcedelete test.db test.db2 |
||
288 | do_test 7.1 { |
||
289 | sqlite3 db test.db |
||
290 | execsql { |
||
291 | CREATE TABLE t1(a, b); |
||
292 | INSERT INTO t1 VALUES(1, 2); |
||
293 | ATTACH 'test.db2' AS aux; |
||
294 | CREATE TABLE aux.t2(a, b); |
||
295 | INSERT INTO t1 VALUES('a', 'b'); |
||
296 | } |
||
297 | db close |
||
298 | } {} |
||
299 | do_test 7.2 { |
||
300 | sqlite3 db file:test.db?mode=ro |
||
301 | execsql { ATTACH 'file:test.db2?mode=rw' AS aux } |
||
302 | } {} |
||
303 | do_execsql_test 7.3 { |
||
304 | INSERT INTO t2 VALUES('c', 'd') |
||
305 | } {} |
||
306 | do_catchsql_test 7.4 { |
||
307 | INSERT INTO t1 VALUES(3, 4) |
||
308 | } {1 {attempt to write a readonly database}} |
||
309 | |||
310 | finish_test |