|
1 # 2007 May 10 |
|
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. The |
|
12 # focus of this file is generating semi-random strings of SQL |
|
13 # (a.k.a. "fuzz") and sending it into the parser to try to |
|
14 # generate errors. |
|
15 # |
|
16 # The tests in this file are really about testing fuzzily generated |
|
17 # SQL parse-trees. The majority of the fuzzily generated SQL is |
|
18 # valid as far as the parser is concerned. |
|
19 # |
|
20 # The most complicated trees are for SELECT statements. |
|
21 # |
|
22 # $Id: fuzz.test,v 1.14 2007/05/30 10:36:47 danielk1977 Exp $ |
|
23 |
|
24 set testdir [file dirname $argv0] |
|
25 source $testdir/tester.tcl |
|
26 |
|
27 set ::REPEATS 5000 |
|
28 |
|
29 # If running quick.test, don't do so many iterations. |
|
30 if {[info exists ::ISQUICK]} { |
|
31 if {$::ISQUICK} { set ::REPEATS 20 } |
|
32 } |
|
33 |
|
34 source $testdir/fuzz_common.tcl |
|
35 |
|
36 #---------------------------------------------------------------- |
|
37 # These tests caused errors that were first caught by the tests |
|
38 # in this file. They are still here. |
|
39 do_test fuzz-1.1 { |
|
40 execsql { |
|
41 SELECT 'abc' LIKE X'ABCD'; |
|
42 } |
|
43 } {0} |
|
44 do_test fuzz-1.2 { |
|
45 execsql { |
|
46 SELECT 'abc' LIKE zeroblob(10); |
|
47 } |
|
48 } {0} |
|
49 do_test fuzz-1.3 { |
|
50 execsql { |
|
51 SELECT zeroblob(10) LIKE 'abc'; |
|
52 } |
|
53 } {0} |
|
54 do_test fuzz-1.4 { |
|
55 execsql { |
|
56 SELECT (- -21) % NOT (456 LIKE zeroblob(10)); |
|
57 } |
|
58 } {0} |
|
59 do_test fuzz-1.5 { |
|
60 execsql { |
|
61 SELECT (SELECT ( |
|
62 SELECT (SELECT -2147483648) FROM (SELECT 1) ORDER BY 1 |
|
63 )) |
|
64 } |
|
65 } {-2147483648} |
|
66 do_test fuzz-1.6 { |
|
67 execsql { |
|
68 SELECT 'abc', zeroblob(1) FROM (SELECT 1) ORDER BY 1 |
|
69 } |
|
70 } [execsql {SELECT 'abc', zeroblob(1)}] |
|
71 |
|
72 do_test fuzz-1.7 { |
|
73 execsql { |
|
74 SELECT ( SELECT zeroblob(1000) FROM ( |
|
75 SELECT * FROM (SELECT 'first') ORDER BY NOT 'in') |
|
76 ) |
|
77 } |
|
78 } [execsql {SELECT zeroblob(1000)}] |
|
79 |
|
80 do_test fuzz-1.8 { |
|
81 # Problems with opcode OP_ToText (did not account for MEM_Zero). |
|
82 # Also MemExpandBlob() was marking expanded blobs as nul-terminated. |
|
83 # They are not. |
|
84 execsql { |
|
85 SELECT CAST(zeroblob(1000) AS text); |
|
86 } |
|
87 } {{}} |
|
88 |
|
89 do_test fuzz-1.9 { |
|
90 # This was causing a NULL pointer dereference of Expr.pList. |
|
91 execsql { |
|
92 SELECT 1 FROM (SELECT * FROM sqlite_master WHERE random()) |
|
93 } |
|
94 } {} |
|
95 |
|
96 do_test fuzz-1.10 { |
|
97 # Bug in calculation of Parse.ckOffset causing an assert() |
|
98 # to fail. Probably harmless. |
|
99 execsql { |
|
100 SELECT coalesce(1, substr( 1, 2, length('in' IN (SELECT 1)))) |
|
101 } |
|
102 } {1} |
|
103 |
|
104 do_test fuzz-1.11 { |
|
105 # The literals (A, B, C, D) are not important, they are just used |
|
106 # to make the EXPLAIN output easier to read. |
|
107 # |
|
108 # The problem here is that the EXISTS(...) expression leaves an |
|
109 # extra value on the VDBE stack. This is confusing the parent and |
|
110 # leads to an assert() failure when OP_Insert encounters an integer |
|
111 # when it expects a record blob. |
|
112 # |
|
113 # Update: Any query with (LIMIT 0) was leaking stack. |
|
114 # |
|
115 execsql { |
|
116 SELECT 'A' FROM (SELECT 'B') ORDER BY EXISTS ( |
|
117 SELECT 'C' FROM (SELECT 'D' LIMIT 0) |
|
118 ) |
|
119 } |
|
120 } {A} |
|
121 |
|
122 do_test fuzz-1.12.1 { |
|
123 # Create a table with a single row. |
|
124 execsql { |
|
125 CREATE TABLE abc(b); |
|
126 INSERT INTO abc VALUES('ABCDE'); |
|
127 } |
|
128 |
|
129 # The following query was crashing. The later subquery (in the FROM) |
|
130 # clause was flattened into the parent, but the code was not repairng |
|
131 # the "b" reference in the other sub-query. When the query was executed, |
|
132 # that "b" refered to a non-existant vdbe table-cursor. |
|
133 # |
|
134 execsql { |
|
135 SELECT 1 IN ( SELECT b UNION SELECT 1 ) FROM (SELECT b FROM abc); |
|
136 } |
|
137 } {1} |
|
138 do_test fuzz-1.12.2 { |
|
139 # Clean up after the previous query. |
|
140 execsql { |
|
141 DROP TABLE abc; |
|
142 } |
|
143 } {} |
|
144 |
|
145 |
|
146 do_test fuzz-1.13 { |
|
147 # The problem here was that when there were more expressions in |
|
148 # the ORDER BY list than the result-set list. The temporary b-tree |
|
149 # used for sorting was being misconfigured in this case. |
|
150 # |
|
151 execsql { |
|
152 SELECT 'abcd' UNION SELECT 'efgh' ORDER BY 1 ASC, 1 ASC; |
|
153 } |
|
154 } {abcd efgh} |
|
155 |
|
156 do_test fuzz-1.14.1 { |
|
157 execsql { |
|
158 CREATE TABLE abc(a, b, c); |
|
159 INSERT INTO abc VALUES(123, 456, 789); |
|
160 } |
|
161 |
|
162 # The [a] reference in the sub-select was causing a problem. Because |
|
163 # the internal walkSelectExpr() function was not considering compound |
|
164 # SELECT operators. |
|
165 execsql { |
|
166 SELECT 1 FROM abc |
|
167 GROUP BY c HAVING EXISTS (SELECT a UNION SELECT 123); |
|
168 } |
|
169 } {1} |
|
170 do_test fuzz-1.14.2 { |
|
171 execsql { |
|
172 DROP TABLE abc; |
|
173 } |
|
174 } {} |
|
175 |
|
176 #---------------------------------------------------------------- |
|
177 # Test some fuzzily generated expressions. |
|
178 # |
|
179 do_fuzzy_test fuzz-2 -template { SELECT [Expr] } |
|
180 |
|
181 do_test fuzz-3.1 { |
|
182 execsql { |
|
183 CREATE TABLE abc(a, b, c); |
|
184 CREATE TABLE def(a, b, c); |
|
185 CREATE TABLE ghi(a, b, c); |
|
186 } |
|
187 } {} |
|
188 set ::TableList [list abc def ghi] |
|
189 |
|
190 #---------------------------------------------------------------- |
|
191 # Test some fuzzily generated SELECT statements. |
|
192 # |
|
193 do_fuzzy_test fuzz-3.2 -template {[Select]} |
|
194 |
|
195 #---------------------------------------------------------------- |
|
196 # Insert a small amount of data into the database and then run |
|
197 # some more generated SELECT statements. |
|
198 # |
|
199 do_test fuzz-4.1 { |
|
200 execsql { |
|
201 INSERT INTO abc VALUES(1, 2, 3); |
|
202 INSERT INTO abc VALUES(4, 5, 6); |
|
203 INSERT INTO abc VALUES(7, 8, 9); |
|
204 INSERT INTO def VALUES(1, 2, 3); |
|
205 INSERT INTO def VALUES(4, 5, 6); |
|
206 INSERT INTO def VALUES(7, 8, 9); |
|
207 INSERT INTO ghi VALUES(1, 2, 3); |
|
208 INSERT INTO ghi VALUES(4, 5, 6); |
|
209 INSERT INTO ghi VALUES(7, 8, 9); |
|
210 CREATE INDEX abc_i ON abc(a, b, c); |
|
211 CREATE INDEX def_i ON def(c, a, b); |
|
212 CREATE INDEX ghi_i ON ghi(b, c, a); |
|
213 } |
|
214 } {} |
|
215 do_fuzzy_test fuzz-4.2 -template {[Select]} |
|
216 |
|
217 #---------------------------------------------------------------- |
|
218 # Test some fuzzy INSERT statements: |
|
219 # |
|
220 do_test fuzz-5.1 {execsql BEGIN} {} |
|
221 do_fuzzy_test fuzz-5.2 -template {[Insert]} -errorlist table |
|
222 integrity_check fuzz-5.2.integrity |
|
223 do_test fuzz-5.3 {execsql COMMIT} {} |
|
224 integrity_check fuzz-5.4.integrity |
|
225 |
|
226 #---------------------------------------------------------------- |
|
227 # Now that there is data in the database, run some more SELECT |
|
228 # statements |
|
229 # |
|
230 set ::ColumnList [list a b c] |
|
231 set E {{no such col} {ambiguous column name}} |
|
232 do_fuzzy_test fuzz-6.1 -template {[Select]} -errorlist $E |
|
233 |
|
234 #---------------------------------------------------------------- |
|
235 # Run some SELECTs, INSERTs, UPDATEs and DELETEs in a transaction. |
|
236 # |
|
237 set E {{no such col} {ambiguous column name} {table}} |
|
238 do_test fuzz-7.1 {execsql BEGIN} {} |
|
239 do_fuzzy_test fuzz-7.2 -template {[Statement]} -errorlist $E |
|
240 integrity_check fuzz-7.3.integrity |
|
241 do_test fuzz-7.4 {execsql COMMIT} {} |
|
242 integrity_check fuzz-7.5.integrity |
|
243 |
|
244 #---------------------------------------------------------------- |
|
245 # Many CREATE and DROP TABLE statements: |
|
246 # |
|
247 set E [list table duplicate {no such col} {ambiguous column name} {use DROP}] |
|
248 do_fuzzy_test fuzz-8.1 -template {[CreateOrDropTableOrView]} -errorlist $E |
|
249 |
|
250 close $::log |
|
251 finish_test |