OLD | NEW |
| (Empty) |
1 # 2010 September 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 # This file contains tests for the r-tree module. Specifically, it tests | |
12 # that corrupt or inconsistent databases do not cause crashes in the r-tree | |
13 # module. | |
14 # | |
15 | |
16 if {![info exists testdir]} { | |
17 set testdir [file join [file dirname [info script]] .. .. test] | |
18 } | |
19 source $testdir/tester.tcl | |
20 ifcapable !rtree { finish_test ; return } | |
21 | |
22 proc create_t1 {} { | |
23 db close | |
24 forcedelete test.db | |
25 sqlite3 db test.db | |
26 execsql { | |
27 PRAGMA page_size = 1024; | |
28 CREATE VIRTUAL TABLE t1 USING rtree(id, x1, x2, y1, y2); | |
29 } | |
30 } | |
31 proc populate_t1 {} { | |
32 execsql BEGIN | |
33 for {set i 0} {$i < 500} {incr i} { | |
34 set x2 [expr $i+5] | |
35 set y2 [expr $i+5] | |
36 execsql { INSERT INTO t1 VALUES($i, $i, $x2, $i, $y2) } | |
37 } | |
38 execsql COMMIT | |
39 } | |
40 | |
41 proc truncate_node {nodeno nTrunc} { | |
42 set blob [db one {SELECT data FROM t1_node WHERE nodeno=$nodeno}] | |
43 if {$nTrunc<0} {set nTrunc "end-$nTrunc"} | |
44 set blob [string range $blob 0 $nTrunc] | |
45 db eval { UPDATE t1_node SET data = $blob WHERE nodeno=$nodeno } | |
46 } | |
47 | |
48 proc set_tree_depth {tbl {newvalue ""}} { | |
49 set blob [db one "SELECT data FROM ${tbl}_node WHERE nodeno=1"] | |
50 | |
51 if {$newvalue == ""} { | |
52 binary scan $blob Su oldvalue | |
53 return $oldvalue | |
54 } | |
55 | |
56 set blob [binary format Sua* $newvalue [string range $blob 2 end]] | |
57 db eval "UPDATE ${tbl}_node SET data = \$blob WHERE nodeno=1" | |
58 return [set_tree_depth $tbl] | |
59 } | |
60 | |
61 proc set_entry_count {tbl nodeno {newvalue ""}} { | |
62 set blob [db one "SELECT data FROM ${tbl}_node WHERE nodeno=$nodeno"] | |
63 | |
64 if {$newvalue == ""} { | |
65 binary scan [string range $blob 2 end] Su oldvalue | |
66 return $oldvalue | |
67 } | |
68 | |
69 set blob [binary format a*Sua* \ | |
70 [string range $blob 0 1] $newvalue [string range $blob 4 end] | |
71 ] | |
72 db eval "UPDATE ${tbl}_node SET data = \$blob WHERE nodeno=$nodeno" | |
73 return [set_entry_count $tbl $nodeno] | |
74 } | |
75 | |
76 | |
77 proc do_corruption_tests {prefix args} { | |
78 set testarray [lindex $args end] | |
79 set errormsg {database disk image is malformed} | |
80 | |
81 foreach {z value} [lrange $args 0 end-1] { | |
82 set n [string length $z] | |
83 if {$n>=2 && [string equal -length $n $z "-error"]} { | |
84 set errormsg $value | |
85 } | |
86 } | |
87 | |
88 foreach {tn sql} $testarray { | |
89 do_catchsql_test $prefix.$tn $sql [list 1 $errormsg] | |
90 } | |
91 } | |
92 | |
93 #------------------------------------------------------------------------- | |
94 # Test the libraries response if the %_node table is completely empty | |
95 # (i.e. the root node is missing), or has been removed from the database | |
96 # entirely. | |
97 # | |
98 create_t1 | |
99 populate_t1 | |
100 do_execsql_test rtreeA-1.0 { | |
101 DELETE FROM t1_node; | |
102 } {} | |
103 | |
104 do_corruption_tests rtreeA-1.1 { | |
105 1 "SELECT * FROM t1" | |
106 2 "SELECT * FROM t1 WHERE rowid=5" | |
107 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)" | |
108 4 "SELECT * FROM t1 WHERE x1<10 AND x2>12" | |
109 } | |
110 | |
111 do_execsql_test rtreeA-1.2.0 { DROP TABLE t1_node } {} | |
112 do_corruption_tests rtreeA-1.2 -error "SQL logic error or missing database" { | |
113 1 "SELECT * FROM t1" | |
114 2 "SELECT * FROM t1 WHERE rowid=5" | |
115 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)" | |
116 4 "SELECT * FROM t1 WHERE x1<10 AND x2>12" | |
117 } | |
118 | |
119 #------------------------------------------------------------------------- | |
120 # Test the libraries response if some of the entries in the %_node table | |
121 # are the wrong size. | |
122 # | |
123 create_t1 | |
124 populate_t1 | |
125 do_test rtreeA-2.1.0 { | |
126 set nodes [db eval {select nodeno FROM t1_node}] | |
127 foreach {a b c} $nodes { truncate_node $c 200 } | |
128 } {} | |
129 do_corruption_tests rtreeA-2.1 { | |
130 1 "SELECT * FROM t1" | |
131 2 "SELECT * FROM t1 WHERE rowid=5" | |
132 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)" | |
133 4 "SELECT * FROM t1 WHERE x1<10 AND x2>12" | |
134 } | |
135 | |
136 create_t1 | |
137 populate_t1 | |
138 do_test rtreeA-2.2.0 { truncate_node 1 200 } {} | |
139 do_corruption_tests rtreeA-2.2 { | |
140 1 "SELECT * FROM t1" | |
141 2 "SELECT * FROM t1 WHERE rowid=5" | |
142 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)" | |
143 4 "SELECT * FROM t1 WHERE x1<10 AND x2>12" | |
144 } | |
145 | |
146 #------------------------------------------------------------------------- | |
147 # Set the "depth" of the tree stored on the root node incorrectly. Test | |
148 # that this does not cause any problems. | |
149 # | |
150 create_t1 | |
151 populate_t1 | |
152 do_test rtreeA-3.1.0.1 { set_tree_depth t1 } {1} | |
153 do_test rtreeA-3.1.0.2 { set_tree_depth t1 3 } {3} | |
154 do_corruption_tests rtreeA-3.1 { | |
155 1 "SELECT * FROM t1" | |
156 2 "SELECT * FROM t1 WHERE rowid=5" | |
157 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)" | |
158 } | |
159 | |
160 do_test rtreeA-3.2.0 { set_tree_depth t1 1000 } {1000} | |
161 do_corruption_tests rtreeA-3.2 { | |
162 1 "SELECT * FROM t1" | |
163 2 "SELECT * FROM t1 WHERE rowid=5" | |
164 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)" | |
165 } | |
166 | |
167 create_t1 | |
168 populate_t1 | |
169 do_test rtreeA-3.3.0 { | |
170 execsql { DELETE FROM t1 WHERE rowid = 0 } | |
171 set_tree_depth t1 65535 | |
172 } {65535} | |
173 do_corruption_tests rtreeA-3.3 { | |
174 1 "SELECT * FROM t1" | |
175 2 "SELECT * FROM t1 WHERE rowid=5" | |
176 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)" | |
177 } | |
178 | |
179 #------------------------------------------------------------------------- | |
180 # Set the "number of entries" field on some nodes incorrectly. | |
181 # | |
182 create_t1 | |
183 populate_t1 | |
184 do_test rtreeA-4.1.0 { | |
185 set_entry_count t1 1 4000 | |
186 } {4000} | |
187 do_corruption_tests rtreeA-4.1 { | |
188 1 "SELECT * FROM t1" | |
189 2 "SELECT * FROM t1 WHERE rowid=5" | |
190 3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)" | |
191 4 "SELECT * FROM t1 WHERE x1<10 AND x2>12" | |
192 } | |
193 | |
194 #------------------------------------------------------------------------- | |
195 # Remove entries from the %_parent table and check that this does not | |
196 # cause a crash. | |
197 # | |
198 create_t1 | |
199 populate_t1 | |
200 do_execsql_test rtreeA-5.1.0 { DELETE FROM t1_parent } {} | |
201 do_corruption_tests rtreeA-5.1 { | |
202 1 "DELETE FROM t1 WHERE rowid = 5" | |
203 2 "DELETE FROM t1" | |
204 } | |
205 | |
206 #------------------------------------------------------------------------- | |
207 # Add some bad entries to the %_parent table. | |
208 # | |
209 create_t1 | |
210 populate_t1 | |
211 do_execsql_test rtreeA-6.1.0 { | |
212 UPDATE t1_parent set parentnode = parentnode+1 | |
213 } {} | |
214 do_corruption_tests rtreeA-6.1 { | |
215 1 "DELETE FROM t1 WHERE rowid = 5" | |
216 2 "UPDATE t1 SET x1=x1+1, x2=x2+1" | |
217 } | |
218 | |
219 | |
220 finish_test | |
OLD | NEW |