diff options
author | dan miller | 2007-10-20 02:49:29 +0000 |
---|---|---|
committer | dan miller | 2007-10-20 02:49:29 +0000 |
commit | e36d23a85ebff914d74bb541558c2b6082b78edb (patch) | |
tree | 54b58fdf162e78af64055282a6035c8d2443389d /libraries/sqlite/unix/sqlite-3.5.1/test/btree2.test | |
parent | * Fixed an issue whereby avatar chat distances were being calculated against ... (diff) | |
download | opensim-SC-e36d23a85ebff914d74bb541558c2b6082b78edb.zip opensim-SC-e36d23a85ebff914d74bb541558c2b6082b78edb.tar.gz opensim-SC-e36d23a85ebff914d74bb541558c2b6082b78edb.tar.bz2 opensim-SC-e36d23a85ebff914d74bb541558c2b6082b78edb.tar.xz |
sqlite source (unix build) added to libraries
Diffstat (limited to 'libraries/sqlite/unix/sqlite-3.5.1/test/btree2.test')
-rw-r--r-- | libraries/sqlite/unix/sqlite-3.5.1/test/btree2.test | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/libraries/sqlite/unix/sqlite-3.5.1/test/btree2.test b/libraries/sqlite/unix/sqlite-3.5.1/test/btree2.test new file mode 100644 index 0000000..35263c1 --- /dev/null +++ b/libraries/sqlite/unix/sqlite-3.5.1/test/btree2.test | |||
@@ -0,0 +1,502 @@ | |||
1 | # 2001 September 15 | ||
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 script is btree database backend | ||
13 | # | ||
14 | # $Id: btree2.test,v 1.15 2006/03/19 13:00:25 drh Exp $ | ||
15 | |||
16 | |||
17 | set testdir [file dirname $argv0] | ||
18 | source $testdir/tester.tcl | ||
19 | |||
20 | if {[info commands btree_open]!=""} { | ||
21 | |||
22 | # Create a new database file containing no entries. The database should | ||
23 | # contain 5 tables: | ||
24 | # | ||
25 | # 2 The descriptor table | ||
26 | # 3 The foreground table | ||
27 | # 4 The background table | ||
28 | # 5 The long key table | ||
29 | # 6 The long data table | ||
30 | # | ||
31 | # An explanation for what all these tables are used for is provided below. | ||
32 | # | ||
33 | do_test btree2-1.1 { | ||
34 | expr srand(1) | ||
35 | file delete -force test2.bt | ||
36 | file delete -force test2.bt-journal | ||
37 | set ::b [btree_open test2.bt 2000 0] | ||
38 | btree_begin_transaction $::b | ||
39 | btree_create_table $::b 0 | ||
40 | } {2} | ||
41 | do_test btree2-1.2 { | ||
42 | btree_create_table $::b 0 | ||
43 | } {3} | ||
44 | do_test btree2-1.3 { | ||
45 | btree_create_table $::b 0 | ||
46 | } {4} | ||
47 | do_test btree2-1.4 { | ||
48 | btree_create_table $::b 0 | ||
49 | } {5} | ||
50 | do_test btree2-1.5 { | ||
51 | btree_create_table $::b 0 | ||
52 | } {6} | ||
53 | do_test btree2-1.6 { | ||
54 | set ::c2 [btree_cursor $::b 2 1] | ||
55 | btree_insert $::c2 {one} {1} | ||
56 | btree_move_to $::c2 {one} | ||
57 | btree_delete $::c2 | ||
58 | btree_close_cursor $::c2 | ||
59 | btree_commit $::b | ||
60 | btree_integrity_check $::b 1 2 3 4 5 6 | ||
61 | } {} | ||
62 | |||
63 | # This test module works by making lots of pseudo-random changes to a | ||
64 | # database while simultaneously maintaining an invariant on that database. | ||
65 | # Periodically, the script does a sanity check on the database and verifies | ||
66 | # that the invariant is satisfied. | ||
67 | # | ||
68 | # The invariant is as follows: | ||
69 | # | ||
70 | # 1. The descriptor table always contains 2 enters. An entry keyed by | ||
71 | # "N" is the number of elements in the foreground and background tables | ||
72 | # combined. The entry keyed by "L" is the number of digits in the keys | ||
73 | # for foreground and background tables. | ||
74 | # | ||
75 | # 2. The union of the foreground an background tables consists of N entries | ||
76 | # where each entry has an L-digit key. (Actually, some keys can be longer | ||
77 | # than L characters, but they always start with L digits.) The keys | ||
78 | # cover all integers between 1 and N. Whenever an entry is added to | ||
79 | # the foreground it is removed form the background and vice versa. | ||
80 | # | ||
81 | # 3. Some entries in the foreground and background tables have keys that | ||
82 | # begin with an L-digit number but are followed by additional characters. | ||
83 | # For each such entry there is a corresponding entry in the long key | ||
84 | # table. The long key table entry has a key which is just the L-digit | ||
85 | # number and data which is the length of the key in the foreground and | ||
86 | # background tables. | ||
87 | # | ||
88 | # 4. The data for both foreground and background entries is usually a | ||
89 | # short string. But some entries have long data strings. For each | ||
90 | # such entries there is an entry in the long data type. The key to | ||
91 | # long data table is an L-digit number. (The extension on long keys | ||
92 | # is omitted.) The data is the number of charaters in the data of the | ||
93 | # foreground or background entry. | ||
94 | # | ||
95 | # The following function builds a database that satisfies all of the above | ||
96 | # invariants. | ||
97 | # | ||
98 | proc build_db {N L} { | ||
99 | for {set i 2} {$i<=6} {incr i} { | ||
100 | catch {btree_close_cursor [set ::c$i]} | ||
101 | btree_clear_table $::b $i | ||
102 | set ::c$i [btree_cursor $::b $i 1] | ||
103 | } | ||
104 | btree_insert $::c2 N $N | ||
105 | btree_insert $::c2 L $L | ||
106 | set format %0${L}d | ||
107 | for {set i 1} {$i<=$N} {incr i} { | ||
108 | set key [format $format $i] | ||
109 | set data $key | ||
110 | btree_insert $::c3 $key $data | ||
111 | } | ||
112 | } | ||
113 | |||
114 | # Given a base key number and a length, construct the full text of the key | ||
115 | # or data. | ||
116 | # | ||
117 | proc make_payload {keynum L len} { | ||
118 | set key [format %0${L}d $keynum] | ||
119 | set r $key | ||
120 | set i 1 | ||
121 | while {[string length $r]<$len} { | ||
122 | append r " ($i) $key" | ||
123 | incr i | ||
124 | } | ||
125 | return [string range $r 0 [expr {$len-1}]] | ||
126 | } | ||
127 | |||
128 | # Verify the invariants on the database. Return an empty string on | ||
129 | # success or an error message if something is amiss. | ||
130 | # | ||
131 | proc check_invariants {} { | ||
132 | set ck [btree_integrity_check $::b 1 2 3 4 5 6] | ||
133 | if {$ck!=""} { | ||
134 | puts "\n*** SANITY:\n$ck" | ||
135 | exit | ||
136 | return $ck | ||
137 | } | ||
138 | btree_move_to $::c3 {} | ||
139 | btree_move_to $::c4 {} | ||
140 | btree_move_to $::c2 N | ||
141 | set N [btree_data $::c2] | ||
142 | btree_move_to $::c2 L | ||
143 | set L [btree_data $::c2] | ||
144 | set LM1 [expr {$L-1}] | ||
145 | for {set i 1} {$i<=$N} {incr i} { | ||
146 | set key {} | ||
147 | if {![btree_eof $::c3]} { | ||
148 | set key [btree_key $::c3] | ||
149 | } | ||
150 | if {[scan $key %d k]<1} {set k 0} | ||
151 | if {$k!=$i} { | ||
152 | set key {} | ||
153 | if {![btree_eof $::c4]} { | ||
154 | set key [btree_key $::c4] | ||
155 | } | ||
156 | if {[scan $key %d k]<1} {set k 0} | ||
157 | if {$k!=$i} { | ||
158 | return "Key $i is missing from both foreground and background" | ||
159 | } | ||
160 | set data [btree_data $::c4] | ||
161 | btree_next $::c4 | ||
162 | } else { | ||
163 | set data [btree_data $::c3] | ||
164 | btree_next $::c3 | ||
165 | } | ||
166 | set skey [string range $key 0 $LM1] | ||
167 | if {[btree_move_to $::c5 $skey]==0} { | ||
168 | set keylen [btree_data $::c5] | ||
169 | } else { | ||
170 | set keylen $L | ||
171 | } | ||
172 | if {[string length $key]!=$keylen} { | ||
173 | return "Key $i is the wrong size.\ | ||
174 | Is \"$key\" but should be \"[make_payload $k $L $keylen]\"" | ||
175 | } | ||
176 | if {[make_payload $k $L $keylen]!=$key} { | ||
177 | return "Key $i has an invalid extension" | ||
178 | } | ||
179 | if {[btree_move_to $::c6 $skey]==0} { | ||
180 | set datalen [btree_data $::c6] | ||
181 | } else { | ||
182 | set datalen $L | ||
183 | } | ||
184 | if {[string length $data]!=$datalen} { | ||
185 | return "Data for $i is the wrong size.\ | ||
186 | Is [string length $data] but should be $datalen" | ||
187 | } | ||
188 | if {[make_payload $k $L $datalen]!=$data} { | ||
189 | return "Entry $i has an incorrect data" | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | |||
194 | # Look at all elements in both the foreground and background tables. | ||
195 | # Make sure the key is always the same as the prefix of the data. | ||
196 | # | ||
197 | # This routine was used for hunting bugs. It is not a part of standard | ||
198 | # tests. | ||
199 | # | ||
200 | proc check_data {n key} { | ||
201 | global c3 c4 | ||
202 | incr n -1 | ||
203 | foreach c [list $c3 $c4] { | ||
204 | btree_first $c ;# move_to $c $key | ||
205 | set cnt 0 | ||
206 | while {![btree_eof $c]} { | ||
207 | set key [btree_key $c] | ||
208 | set data [btree_data $c] | ||
209 | if {[string range $key 0 $n] ne [string range $data 0 $n]} { | ||
210 | puts "key=[list $key] data=[list $data] n=$n" | ||
211 | puts "cursor info = [btree_cursor_info $c]" | ||
212 | btree_page_dump $::b [lindex [btree_cursor_info $c] 0] | ||
213 | exit | ||
214 | } | ||
215 | btree_next $c | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | |||
220 | # Make random changes to the database such that each change preserves | ||
221 | # the invariants. The number of changes is $n*N where N is the parameter | ||
222 | # from the descriptor table. Each changes begins with a random key. | ||
223 | # the entry with that key is put in the foreground table with probability | ||
224 | # $I and it is put in background with probability (1.0-$I). It gets | ||
225 | # a long key with probability $K and long data with probability $D. | ||
226 | # | ||
227 | set chngcnt 0 | ||
228 | proc random_changes {n I K D} { | ||
229 | global chngcnt | ||
230 | btree_move_to $::c2 N | ||
231 | set N [btree_data $::c2] | ||
232 | btree_move_to $::c2 L | ||
233 | set L [btree_data $::c2] | ||
234 | set LM1 [expr {$L-1}] | ||
235 | set total [expr {int($N*$n)}] | ||
236 | set format %0${L}d | ||
237 | for {set i 0} {$i<$total} {incr i} { | ||
238 | set k [expr {int(rand()*$N)+1}] | ||
239 | set insert [expr {rand()<=$I}] | ||
240 | set longkey [expr {rand()<=$K}] | ||
241 | set longdata [expr {rand()<=$D}] | ||
242 | if {$longkey} { | ||
243 | set x [expr {rand()}] | ||
244 | set keylen [expr {int($x*$x*$x*$x*3000)+10}] | ||
245 | } else { | ||
246 | set keylen $L | ||
247 | } | ||
248 | set key [make_payload $k $L $keylen] | ||
249 | if {$longdata} { | ||
250 | set x [expr {rand()}] | ||
251 | set datalen [expr {int($x*$x*$x*$x*3000)+10}] | ||
252 | } else { | ||
253 | set datalen $L | ||
254 | } | ||
255 | set data [make_payload $k $L $datalen] | ||
256 | set basekey [format $format $k] | ||
257 | if {[set c [btree_move_to $::c3 $basekey]]==0} { | ||
258 | btree_delete $::c3 | ||
259 | } else { | ||
260 | if {$c<0} {btree_next $::c3} | ||
261 | if {![btree_eof $::c3]} { | ||
262 | if {[string match $basekey* [btree_key $::c3]]} { | ||
263 | btree_delete $::c3 | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | if {[set c [btree_move_to $::c4 $basekey]]==0} { | ||
268 | btree_delete $::c4 | ||
269 | } else { | ||
270 | if {$c<0} {btree_next $::c4} | ||
271 | if {![btree_eof $::c4]} { | ||
272 | if {[string match $basekey* [btree_key $::c4]]} { | ||
273 | btree_delete $::c4 | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | set kx -1 | ||
278 | if {![btree_eof $::c4]} { | ||
279 | if {[scan [btree_key $::c4] %d kx]<1} {set kx -1} | ||
280 | } | ||
281 | if {$kx==$k} { | ||
282 | btree_delete $::c4 | ||
283 | } | ||
284 | # For debugging - change the "0" to "1" to integrity check after | ||
285 | # every change. | ||
286 | if 0 { | ||
287 | incr chngcnt | ||
288 | puts check----$chngcnt | ||
289 | set ck [btree_integrity_check $::b 1 2 3 4 5 6] | ||
290 | if {$ck!=""} { | ||
291 | puts "\nSANITY CHECK FAILED!\n$ck" | ||
292 | exit | ||
293 | } | ||
294 | } | ||
295 | if {$insert} { | ||
296 | btree_insert $::c3 $key $data | ||
297 | } else { | ||
298 | btree_insert $::c4 $key $data | ||
299 | } | ||
300 | if {$longkey} { | ||
301 | btree_insert $::c5 $basekey $keylen | ||
302 | } elseif {[btree_move_to $::c5 $basekey]==0} { | ||
303 | btree_delete $::c5 | ||
304 | } | ||
305 | if {$longdata} { | ||
306 | btree_insert $::c6 $basekey $datalen | ||
307 | } elseif {[btree_move_to $::c6 $basekey]==0} { | ||
308 | btree_delete $::c6 | ||
309 | } | ||
310 | # For debugging - change the "0" to "1" to integrity check after | ||
311 | # every change. | ||
312 | if 0 { | ||
313 | incr chngcnt | ||
314 | puts check----$chngcnt | ||
315 | set ck [btree_integrity_check $::b 1 2 3 4 5 6] | ||
316 | if {$ck!=""} { | ||
317 | puts "\nSANITY CHECK FAILED!\n$ck" | ||
318 | exit | ||
319 | } | ||
320 | } | ||
321 | } | ||
322 | } | ||
323 | set btree_trace 0 | ||
324 | |||
325 | # Repeat this test sequence on database of various sizes | ||
326 | # | ||
327 | set testno 2 | ||
328 | foreach {N L} { | ||
329 | 10 2 | ||
330 | 50 2 | ||
331 | 200 3 | ||
332 | 2000 5 | ||
333 | } { | ||
334 | puts "**** N=$N L=$L ****" | ||
335 | set hash [md5file test2.bt] | ||
336 | do_test btree2-$testno.1 [subst -nocommands { | ||
337 | set ::c2 [btree_cursor $::b 2 1] | ||
338 | set ::c3 [btree_cursor $::b 3 1] | ||
339 | set ::c4 [btree_cursor $::b 4 1] | ||
340 | set ::c5 [btree_cursor $::b 5 1] | ||
341 | set ::c6 [btree_cursor $::b 6 1] | ||
342 | btree_begin_transaction $::b | ||
343 | build_db $N $L | ||
344 | check_invariants | ||
345 | }] {} | ||
346 | do_test btree2-$testno.2 { | ||
347 | btree_close_cursor $::c2 | ||
348 | btree_close_cursor $::c3 | ||
349 | btree_close_cursor $::c4 | ||
350 | btree_close_cursor $::c5 | ||
351 | btree_close_cursor $::c6 | ||
352 | btree_rollback $::b | ||
353 | md5file test2.bt | ||
354 | } $hash | ||
355 | do_test btree2-$testno.3 [subst -nocommands { | ||
356 | btree_begin_transaction $::b | ||
357 | set ::c2 [btree_cursor $::b 2 1] | ||
358 | set ::c3 [btree_cursor $::b 3 1] | ||
359 | set ::c4 [btree_cursor $::b 4 1] | ||
360 | set ::c5 [btree_cursor $::b 5 1] | ||
361 | set ::c6 [btree_cursor $::b 6 1] | ||
362 | build_db $N $L | ||
363 | check_invariants | ||
364 | }] {} | ||
365 | do_test btree2-$testno.4 { | ||
366 | btree_commit $::b | ||
367 | check_invariants | ||
368 | } {} | ||
369 | do_test btree2-$testno.5 { | ||
370 | lindex [btree_pager_stats $::b] 1 | ||
371 | } {6} | ||
372 | do_test btree2-$testno.6 { | ||
373 | btree_cursor_info $::c2 | ||
374 | btree_cursor_info $::c3 | ||
375 | btree_cursor_info $::c4 | ||
376 | btree_cursor_info $::c5 | ||
377 | btree_cursor_info $::c6 | ||
378 | btree_close_cursor $::c2 | ||
379 | btree_close_cursor $::c3 | ||
380 | btree_close_cursor $::c4 | ||
381 | btree_close_cursor $::c5 | ||
382 | btree_close_cursor $::c6 | ||
383 | lindex [btree_pager_stats $::b] 1 | ||
384 | } {0} | ||
385 | do_test btree2-$testno.7 { | ||
386 | btree_close $::b | ||
387 | } {} | ||
388 | |||
389 | # For each database size, run various changes tests. | ||
390 | # | ||
391 | set num2 1 | ||
392 | foreach {n I K D} { | ||
393 | 0.5 0.5 0.1 0.1 | ||
394 | 1.0 0.2 0.1 0.1 | ||
395 | 1.0 0.8 0.1 0.1 | ||
396 | 2.0 0.0 0.1 0.1 | ||
397 | 2.0 1.0 0.1 0.1 | ||
398 | 2.0 0.0 0.0 0.0 | ||
399 | 2.0 1.0 0.0 0.0 | ||
400 | } { | ||
401 | set testid btree2-$testno.8.$num2 | ||
402 | set hash [md5file test2.bt] | ||
403 | do_test $testid.0 { | ||
404 | set ::b [btree_open test2.bt 2000 0] | ||
405 | set ::c2 [btree_cursor $::b 2 1] | ||
406 | set ::c3 [btree_cursor $::b 3 1] | ||
407 | set ::c4 [btree_cursor $::b 4 1] | ||
408 | set ::c5 [btree_cursor $::b 5 1] | ||
409 | set ::c6 [btree_cursor $::b 6 1] | ||
410 | check_invariants | ||
411 | } {} | ||
412 | set cnt 6 | ||
413 | for {set i 2} {$i<=6} {incr i} { | ||
414 | if {[lindex [btree_cursor_info [set ::c$i]] 0]!=$i} {incr cnt} | ||
415 | } | ||
416 | do_test $testid.1 { | ||
417 | btree_begin_transaction $::b | ||
418 | lindex [btree_pager_stats $::b] 1 | ||
419 | } $cnt | ||
420 | do_test $testid.2 [subst { | ||
421 | random_changes $n $I $K $D | ||
422 | }] {} | ||
423 | do_test $testid.3 { | ||
424 | check_invariants | ||
425 | } {} | ||
426 | do_test $testid.4 { | ||
427 | btree_close_cursor $::c2 | ||
428 | btree_close_cursor $::c3 | ||
429 | btree_close_cursor $::c4 | ||
430 | btree_close_cursor $::c5 | ||
431 | btree_close_cursor $::c6 | ||
432 | btree_rollback $::b | ||
433 | md5file test2.bt | ||
434 | } $hash | ||
435 | btree_begin_transaction $::b | ||
436 | set ::c2 [btree_cursor $::b 2 1] | ||
437 | set ::c3 [btree_cursor $::b 3 1] | ||
438 | set ::c4 [btree_cursor $::b 4 1] | ||
439 | set ::c5 [btree_cursor $::b 5 1] | ||
440 | set ::c6 [btree_cursor $::b 6 1] | ||
441 | do_test $testid.5 [subst { | ||
442 | random_changes $n $I $K $D | ||
443 | }] {} | ||
444 | do_test $testid.6 { | ||
445 | check_invariants | ||
446 | } {} | ||
447 | do_test $testid.7 { | ||
448 | btree_commit $::b | ||
449 | check_invariants | ||
450 | } {} | ||
451 | set hash [md5file test2.bt] | ||
452 | do_test $testid.8 { | ||
453 | btree_close_cursor $::c2 | ||
454 | btree_close_cursor $::c3 | ||
455 | btree_close_cursor $::c4 | ||
456 | btree_close_cursor $::c5 | ||
457 | btree_close_cursor $::c6 | ||
458 | lindex [btree_pager_stats $::b] 1 | ||
459 | } {0} | ||
460 | do_test $testid.9 { | ||
461 | btree_close $::b | ||
462 | set ::b [btree_open test2.bt 2000 0] | ||
463 | set ::c2 [btree_cursor $::b 2 1] | ||
464 | set ::c3 [btree_cursor $::b 3 1] | ||
465 | set ::c4 [btree_cursor $::b 4 1] | ||
466 | set ::c5 [btree_cursor $::b 5 1] | ||
467 | set ::c6 [btree_cursor $::b 6 1] | ||
468 | check_invariants | ||
469 | } {} | ||
470 | do_test $testid.10 { | ||
471 | btree_close_cursor $::c2 | ||
472 | btree_close_cursor $::c3 | ||
473 | btree_close_cursor $::c4 | ||
474 | btree_close_cursor $::c5 | ||
475 | btree_close_cursor $::c6 | ||
476 | lindex [btree_pager_stats $::b] 1 | ||
477 | } {0} | ||
478 | do_test $testid.11 { | ||
479 | btree_close $::b | ||
480 | } {} | ||
481 | incr num2 | ||
482 | } | ||
483 | incr testno | ||
484 | set ::b [btree_open test2.bt 2000 0] | ||
485 | } | ||
486 | |||
487 | # Testing is complete. Shut everything down. | ||
488 | # | ||
489 | do_test btree-999.1 { | ||
490 | lindex [btree_pager_stats $::b] 1 | ||
491 | } {0} | ||
492 | do_test btree-999.2 { | ||
493 | btree_close $::b | ||
494 | } {} | ||
495 | do_test btree-999.3 { | ||
496 | file delete -force test2.bt | ||
497 | file exists test2.bt-journal | ||
498 | } {0} | ||
499 | |||
500 | } ;# end if( not mem: and has pager_open command ); | ||
501 | |||
502 | finish_test | ||