xref: /titanic_50/usr/src/lib/libsqlite/test/btree2.test (revision c5c4113dfcabb1eed3d4bdf7609de5170027a794)
1*c5c4113dSnw141292
2*c5c4113dSnw141292#pragma ident	"%Z%%M%	%I%	%E% SMI"
3*c5c4113dSnw141292
4*c5c4113dSnw141292# 2001 September 15
5*c5c4113dSnw141292#
6*c5c4113dSnw141292# The author disclaims copyright to this source code.  In place of
7*c5c4113dSnw141292# a legal notice, here is a blessing:
8*c5c4113dSnw141292#
9*c5c4113dSnw141292#    May you do good and not evil.
10*c5c4113dSnw141292#    May you find forgiveness for yourself and forgive others.
11*c5c4113dSnw141292#    May you share freely, never taking more than you give.
12*c5c4113dSnw141292#
13*c5c4113dSnw141292#***********************************************************************
14*c5c4113dSnw141292# This file implements regression tests for SQLite library.  The
15*c5c4113dSnw141292# focus of this script is btree database backend
16*c5c4113dSnw141292#
17*c5c4113dSnw141292# $Id: btree2.test,v 1.10 2002/02/19 13:39:23 drh Exp $
18*c5c4113dSnw141292
19*c5c4113dSnw141292
20*c5c4113dSnw141292set testdir [file dirname $argv0]
21*c5c4113dSnw141292source $testdir/tester.tcl
22*c5c4113dSnw141292
23*c5c4113dSnw141292if {[info commands btree_open]!=""} {
24*c5c4113dSnw141292
25*c5c4113dSnw141292# Create a new database file containing no entries.  The database should
26*c5c4113dSnw141292# contain 5 tables:
27*c5c4113dSnw141292#
28*c5c4113dSnw141292#     2   The descriptor table
29*c5c4113dSnw141292#     3   The foreground table
30*c5c4113dSnw141292#     4   The background table
31*c5c4113dSnw141292#     5   The long key table
32*c5c4113dSnw141292#     6   The long data table
33*c5c4113dSnw141292#
34*c5c4113dSnw141292# An explanation for what all these tables are used for is provided below.
35*c5c4113dSnw141292#
36*c5c4113dSnw141292do_test btree2-1.1 {
37*c5c4113dSnw141292  expr srand(1)
38*c5c4113dSnw141292  file delete -force test2.bt
39*c5c4113dSnw141292  file delete -force test2.bt-journal
40*c5c4113dSnw141292  set ::b [btree_open test2.bt]
41*c5c4113dSnw141292  btree_begin_transaction $::b
42*c5c4113dSnw141292  btree_create_table $::b
43*c5c4113dSnw141292} {3}
44*c5c4113dSnw141292do_test btree2-1.2 {
45*c5c4113dSnw141292  btree_create_table $::b
46*c5c4113dSnw141292} {4}
47*c5c4113dSnw141292do_test btree2-1.3 {
48*c5c4113dSnw141292  btree_create_table $::b
49*c5c4113dSnw141292} {5}
50*c5c4113dSnw141292do_test btree2-1.4 {
51*c5c4113dSnw141292  btree_create_table $::b
52*c5c4113dSnw141292} {6}
53*c5c4113dSnw141292do_test btree2-1.5 {
54*c5c4113dSnw141292  set ::c2 [btree_cursor $::b 2 1]
55*c5c4113dSnw141292  btree_insert $::c2 {one} {1}
56*c5c4113dSnw141292  btree_delete $::c2
57*c5c4113dSnw141292  btree_close_cursor $::c2
58*c5c4113dSnw141292  btree_commit $::b
59*c5c4113dSnw141292  btree_integrity_check $::b 2 3 4 5 6
60*c5c4113dSnw141292} {}
61*c5c4113dSnw141292
62*c5c4113dSnw141292# This test module works by making lots of pseudo-random changes to a
63*c5c4113dSnw141292# database while simultaneously maintaining an invariant on that database.
64*c5c4113dSnw141292# Periodically, the script does a sanity check on the database and verifies
65*c5c4113dSnw141292# that the invariant is satisfied.
66*c5c4113dSnw141292#
67*c5c4113dSnw141292# The invariant is as follows:
68*c5c4113dSnw141292#
69*c5c4113dSnw141292#   1.  The descriptor table always contains 2 enters.  An entry keyed by
70*c5c4113dSnw141292#       "N" is the number of elements in the foreground and background tables
71*c5c4113dSnw141292#       combined.  The entry keyed by "L" is the number of digits in the keys
72*c5c4113dSnw141292#       for foreground and background tables.
73*c5c4113dSnw141292#
74*c5c4113dSnw141292#   2.  The union of the foreground an background tables consists of N entries
75*c5c4113dSnw141292#       where each entry an L-digit key.  (Actually, some keys can be longer
76*c5c4113dSnw141292#       than L characters, but they always start with L digits.)  The keys
77*c5c4113dSnw141292#       cover all integers between 1 and N.  Whenever an entry is added to
78*c5c4113dSnw141292#       the foreground it is removed form the background and vice versa.
79*c5c4113dSnw141292#
80*c5c4113dSnw141292#   3.  Some entries in the foreground and background tables have keys that
81*c5c4113dSnw141292#       begin with an L-digit number but are followed by additional characters.
82*c5c4113dSnw141292#       For each such entry there is a corresponding entry in the long key
83*c5c4113dSnw141292#       table.  The long key table entry has a key which is just the L-digit
84*c5c4113dSnw141292#       number and data which is the length of the key in the foreground and
85*c5c4113dSnw141292#       background tables.
86*c5c4113dSnw141292#
87*c5c4113dSnw141292#   4.  The data for both foreground and background entries is usually a
88*c5c4113dSnw141292#       short string.  But some entries have long data strings.  For each
89*c5c4113dSnw141292#       such entries there is an entry in the long data type.  The key to
90*c5c4113dSnw141292#       long data table is an L-digit number.  (The extension on long keys
91*c5c4113dSnw141292#       is omitted.)  The data is the number of charaters in the data of the
92*c5c4113dSnw141292#       foreground or background entry.
93*c5c4113dSnw141292#
94*c5c4113dSnw141292# The following function builds a database that satisfies all of the above
95*c5c4113dSnw141292# invariants.
96*c5c4113dSnw141292#
97*c5c4113dSnw141292proc build_db {N L} {
98*c5c4113dSnw141292  for {set i 2} {$i<=6} {incr i} {
99*c5c4113dSnw141292    catch {btree_close_cursor [set ::c$i]}
100*c5c4113dSnw141292    btree_clear_table $::b $i
101*c5c4113dSnw141292    set ::c$i [btree_cursor $::b $i 1]
102*c5c4113dSnw141292  }
103*c5c4113dSnw141292  btree_insert $::c2 N $N
104*c5c4113dSnw141292  btree_insert $::c2 L $L
105*c5c4113dSnw141292  set format %0${L}d
106*c5c4113dSnw141292  for {set i 1} {$i<=$N} {incr i} {
107*c5c4113dSnw141292    set key [format $format $i]
108*c5c4113dSnw141292    set data $key
109*c5c4113dSnw141292    btree_insert $::c3 $key $data
110*c5c4113dSnw141292  }
111*c5c4113dSnw141292}
112*c5c4113dSnw141292
113*c5c4113dSnw141292# Given a base key number and a length, construct the full text of the key
114*c5c4113dSnw141292# or data.
115*c5c4113dSnw141292#
116*c5c4113dSnw141292proc make_payload {keynum L len} {
117*c5c4113dSnw141292  set key [format %0${L}d $keynum]
118*c5c4113dSnw141292  set r $key
119*c5c4113dSnw141292  set i 1
120*c5c4113dSnw141292  while {[string length $r]<$len} {
121*c5c4113dSnw141292    append r " ($i) $key"
122*c5c4113dSnw141292    incr i
123*c5c4113dSnw141292  }
124*c5c4113dSnw141292  return [string range $r 0 [expr {$len-1}]]
125*c5c4113dSnw141292}
126*c5c4113dSnw141292
127*c5c4113dSnw141292# Verify the invariants on the database.  Return an empty string on
128*c5c4113dSnw141292# success or an error message if something is amiss.
129*c5c4113dSnw141292#
130*c5c4113dSnw141292proc check_invariants {} {
131*c5c4113dSnw141292  set ck [btree_integrity_check $::b 2 3 4 5 6]
132*c5c4113dSnw141292  if {$ck!=""} {
133*c5c4113dSnw141292    puts "\n*** SANITY:\n$ck"
134*c5c4113dSnw141292    exit
135*c5c4113dSnw141292    return $ck
136*c5c4113dSnw141292  }
137*c5c4113dSnw141292  btree_move_to $::c3 {}
138*c5c4113dSnw141292  btree_move_to $::c4 {}
139*c5c4113dSnw141292  btree_move_to $::c2 N
140*c5c4113dSnw141292  set N [btree_data $::c2]
141*c5c4113dSnw141292  btree_move_to $::c2 L
142*c5c4113dSnw141292  set L [btree_data $::c2]
143*c5c4113dSnw141292  set LM1 [expr {$L-1}]
144*c5c4113dSnw141292  for {set i 1} {$i<=$N} {incr i} {
145*c5c4113dSnw141292    set key [btree_key $::c3]
146*c5c4113dSnw141292    if {[scan $key %d k]<1} {set k 0}
147*c5c4113dSnw141292    if {$k!=$i} {
148*c5c4113dSnw141292      set key [btree_key $::c4]
149*c5c4113dSnw141292      if {[scan $key %d k]<1} {set k 0}
150*c5c4113dSnw141292      if {$k!=$i} {
151*c5c4113dSnw141292        # puts "MISSING $i"
152*c5c4113dSnw141292        # puts {Page 3:}; btree_page_dump $::b 3
153*c5c4113dSnw141292        # puts {Page 4:}; btree_page_dump $::b 4
154*c5c4113dSnw141292        # exit
155*c5c4113dSnw141292        return "Key $i is missing from both foreground and background"
156*c5c4113dSnw141292      }
157*c5c4113dSnw141292      set data [btree_data $::c4]
158*c5c4113dSnw141292      btree_next $::c4
159*c5c4113dSnw141292    } else {
160*c5c4113dSnw141292      set data [btree_data $::c3]
161*c5c4113dSnw141292      btree_next $::c3
162*c5c4113dSnw141292    }
163*c5c4113dSnw141292    set skey [string range $key 0 $LM1]
164*c5c4113dSnw141292    if {[btree_move_to $::c5 $skey]==0} {
165*c5c4113dSnw141292      set keylen [btree_data $::c5]
166*c5c4113dSnw141292    } else {
167*c5c4113dSnw141292      set keylen $L
168*c5c4113dSnw141292    }
169*c5c4113dSnw141292    if {[string length $key]!=$keylen} {
170*c5c4113dSnw141292      return "Key $i is the wrong size.\
171*c5c4113dSnw141292              Is \"$key\" but should be \"[make_payload $k $L $keylen]\""
172*c5c4113dSnw141292    }
173*c5c4113dSnw141292    if {[make_payload $k $L $keylen]!=$key} {
174*c5c4113dSnw141292      return "Key $i has an invalid extension"
175*c5c4113dSnw141292    }
176*c5c4113dSnw141292    if {[btree_move_to $::c6 $skey]==0} {
177*c5c4113dSnw141292      set datalen [btree_data $::c6]
178*c5c4113dSnw141292    } else {
179*c5c4113dSnw141292      set datalen $L
180*c5c4113dSnw141292    }
181*c5c4113dSnw141292    if {[string length $data]!=$datalen} {
182*c5c4113dSnw141292      return "Data for $i is the wrong size.\
183*c5c4113dSnw141292              Is [string length $data] but should be $datalen"
184*c5c4113dSnw141292    }
185*c5c4113dSnw141292    if {[make_payload $k $L $datalen]!=$data} {
186*c5c4113dSnw141292      return "Entry $i has an incorrect data"
187*c5c4113dSnw141292    }
188*c5c4113dSnw141292  }
189*c5c4113dSnw141292}
190*c5c4113dSnw141292
191*c5c4113dSnw141292# Make random changes to the database such that each change preserves
192*c5c4113dSnw141292# the invariants.  The number of changes is $n*N where N is the parameter
193*c5c4113dSnw141292# from the descriptor table.  Each changes begins with a random key.
194*c5c4113dSnw141292# the entry with that key is put in the foreground table with probability
195*c5c4113dSnw141292# $I and it is put in background with probability (1.0-$I).  It gets
196*c5c4113dSnw141292# a long key with probability $K and long data with probability $D.
197*c5c4113dSnw141292#
198*c5c4113dSnw141292set chngcnt 0
199*c5c4113dSnw141292proc random_changes {n I K D} {
200*c5c4113dSnw141292  btree_move_to $::c2 N
201*c5c4113dSnw141292  set N [btree_data $::c2]
202*c5c4113dSnw141292  btree_move_to $::c2 L
203*c5c4113dSnw141292  set L [btree_data $::c2]
204*c5c4113dSnw141292  set LM1 [expr {$L-1}]
205*c5c4113dSnw141292  set total [expr {int($N*$n)}]
206*c5c4113dSnw141292  set format %0${L}d
207*c5c4113dSnw141292  for {set i 0} {$i<$total} {incr i} {
208*c5c4113dSnw141292    set k [expr {int(rand()*$N)+1}]
209*c5c4113dSnw141292    set insert [expr {rand()<=$I}]
210*c5c4113dSnw141292    set longkey [expr {rand()<=$K}]
211*c5c4113dSnw141292    set longdata [expr {rand()<=$D}]
212*c5c4113dSnw141292    # incr ::chngcnt
213*c5c4113dSnw141292    # if {$::chngcnt==251} {btree_tree_dump $::b 3}
214*c5c4113dSnw141292    # puts "CHANGE $::chngcnt: $k $insert $longkey $longdata"
215*c5c4113dSnw141292    if {$longkey} {
216*c5c4113dSnw141292      set x [expr {rand()}]
217*c5c4113dSnw141292      set keylen [expr {int($x*$x*$x*$x*3000)+10}]
218*c5c4113dSnw141292    } else {
219*c5c4113dSnw141292      set keylen $L
220*c5c4113dSnw141292    }
221*c5c4113dSnw141292    set key [make_payload $k $L $keylen]
222*c5c4113dSnw141292    if {$longdata} {
223*c5c4113dSnw141292      set x [expr {rand()}]
224*c5c4113dSnw141292      set datalen [expr {int($x*$x*$x*$x*3000)+10}]
225*c5c4113dSnw141292    } else {
226*c5c4113dSnw141292      set datalen $L
227*c5c4113dSnw141292    }
228*c5c4113dSnw141292    set data [make_payload $k $L $datalen]
229*c5c4113dSnw141292    set basekey [format $format $k]
230*c5c4113dSnw141292    if {[set c [btree_move_to $::c3 $basekey]]==0} {
231*c5c4113dSnw141292      btree_delete $::c3
232*c5c4113dSnw141292    } else {
233*c5c4113dSnw141292      if {$c<0} {btree_next $::c3}
234*c5c4113dSnw141292      if {[string match $basekey* [btree_key $::c3]]} {
235*c5c4113dSnw141292        btree_delete $::c3
236*c5c4113dSnw141292      }
237*c5c4113dSnw141292    }
238*c5c4113dSnw141292    if {[set c [btree_move_to $::c4 $basekey]]==0} {
239*c5c4113dSnw141292      btree_delete $::c4
240*c5c4113dSnw141292    } else {
241*c5c4113dSnw141292      if {$c<0} {btree_next $::c4}
242*c5c4113dSnw141292      if {[string match $basekey* [btree_key $::c4]]} {
243*c5c4113dSnw141292        btree_delete $::c4
244*c5c4113dSnw141292      }
245*c5c4113dSnw141292    }
246*c5c4113dSnw141292    if {[scan [btree_key $::c4] %d kx]<1} {set kx -1}
247*c5c4113dSnw141292    if {$kx==$k} {
248*c5c4113dSnw141292      btree_delete $::c4
249*c5c4113dSnw141292    }
250*c5c4113dSnw141292    if {$insert} {
251*c5c4113dSnw141292      btree_insert $::c3 $key $data
252*c5c4113dSnw141292    } else {
253*c5c4113dSnw141292      btree_insert $::c4 $key $data
254*c5c4113dSnw141292    }
255*c5c4113dSnw141292    if {$longkey} {
256*c5c4113dSnw141292      btree_insert $::c5 $basekey $keylen
257*c5c4113dSnw141292    } elseif {[btree_move_to $::c5 $basekey]==0} {
258*c5c4113dSnw141292      btree_delete $::c5
259*c5c4113dSnw141292    }
260*c5c4113dSnw141292    if {$longdata} {
261*c5c4113dSnw141292      btree_insert $::c6 $basekey $datalen
262*c5c4113dSnw141292    } elseif {[btree_move_to $::c6 $basekey]==0} {
263*c5c4113dSnw141292      btree_delete $::c6
264*c5c4113dSnw141292    }
265*c5c4113dSnw141292    # set ck [btree_integrity_check $::b 2 3 4 5 6]
266*c5c4113dSnw141292    # if {$ck!=""} {
267*c5c4113dSnw141292    #   puts "\nSANITY CHECK FAILED!\n$ck"
268*c5c4113dSnw141292    #   exit
269*c5c4113dSnw141292    # }
270*c5c4113dSnw141292    # puts "PAGE 3:"; btree_page_dump $::b 3
271*c5c4113dSnw141292    # puts "PAGE 4:"; btree_page_dump $::b 4
272*c5c4113dSnw141292  }
273*c5c4113dSnw141292}
274*c5c4113dSnw141292
275*c5c4113dSnw141292# Repeat this test sequence on database of various sizes
276*c5c4113dSnw141292#
277*c5c4113dSnw141292set testno 2
278*c5c4113dSnw141292foreach {N L} {
279*c5c4113dSnw141292  10 2
280*c5c4113dSnw141292  50 2
281*c5c4113dSnw141292  200 3
282*c5c4113dSnw141292  2000 5
283*c5c4113dSnw141292} {
284*c5c4113dSnw141292  puts "**** N=$N L=$L ****"
285*c5c4113dSnw141292  set hash [md5file test2.bt]
286*c5c4113dSnw141292  do_test btree2-$testno.1 [subst -nocommands {
287*c5c4113dSnw141292    set ::c2 [btree_cursor $::b 2 1]
288*c5c4113dSnw141292    set ::c3 [btree_cursor $::b 3 1]
289*c5c4113dSnw141292    set ::c4 [btree_cursor $::b 4 1]
290*c5c4113dSnw141292    set ::c5 [btree_cursor $::b 5 1]
291*c5c4113dSnw141292    set ::c6 [btree_cursor $::b 6 1]
292*c5c4113dSnw141292    btree_begin_transaction $::b
293*c5c4113dSnw141292    build_db $N $L
294*c5c4113dSnw141292    check_invariants
295*c5c4113dSnw141292  }] {}
296*c5c4113dSnw141292  do_test btree2-$testno.2 {
297*c5c4113dSnw141292    btree_close_cursor $::c2
298*c5c4113dSnw141292    btree_close_cursor $::c3
299*c5c4113dSnw141292    btree_close_cursor $::c4
300*c5c4113dSnw141292    btree_close_cursor $::c5
301*c5c4113dSnw141292    btree_close_cursor $::c6
302*c5c4113dSnw141292    btree_rollback $::b
303*c5c4113dSnw141292    md5file test2.bt
304*c5c4113dSnw141292  } $hash
305*c5c4113dSnw141292  do_test btree2-$testno.3 [subst -nocommands {
306*c5c4113dSnw141292    btree_begin_transaction $::b
307*c5c4113dSnw141292    set ::c2 [btree_cursor $::b 2 1]
308*c5c4113dSnw141292    set ::c3 [btree_cursor $::b 3 1]
309*c5c4113dSnw141292    set ::c4 [btree_cursor $::b 4 1]
310*c5c4113dSnw141292    set ::c5 [btree_cursor $::b 5 1]
311*c5c4113dSnw141292    set ::c6 [btree_cursor $::b 6 1]
312*c5c4113dSnw141292    build_db $N $L
313*c5c4113dSnw141292    check_invariants
314*c5c4113dSnw141292  }] {}
315*c5c4113dSnw141292  do_test btree2-$testno.4 {
316*c5c4113dSnw141292    btree_commit $::b
317*c5c4113dSnw141292    check_invariants
318*c5c4113dSnw141292  } {}
319*c5c4113dSnw141292  do_test btree2-$testno.5  {
320*c5c4113dSnw141292    lindex [btree_pager_stats $::b] 1
321*c5c4113dSnw141292  } {6}
322*c5c4113dSnw141292  do_test btree2-$testno.6  {
323*c5c4113dSnw141292    btree_close_cursor $::c2
324*c5c4113dSnw141292    btree_close_cursor $::c3
325*c5c4113dSnw141292    btree_close_cursor $::c4
326*c5c4113dSnw141292    btree_close_cursor $::c5
327*c5c4113dSnw141292    btree_close_cursor $::c6
328*c5c4113dSnw141292    lindex [btree_pager_stats $::b] 1
329*c5c4113dSnw141292  } {0}
330*c5c4113dSnw141292  do_test btree2-$testno.7 {
331*c5c4113dSnw141292    btree_close $::b
332*c5c4113dSnw141292  } {}
333*c5c4113dSnw141292after 100
334*c5c4113dSnw141292  # For each database size, run various changes tests.
335*c5c4113dSnw141292  #
336*c5c4113dSnw141292  set num2 1
337*c5c4113dSnw141292  foreach {n I K D} {
338*c5c4113dSnw141292    0.5 0.5 0.1 0.1
339*c5c4113dSnw141292    1.0 0.2 0.1 0.1
340*c5c4113dSnw141292    1.0 0.8 0.1 0.1
341*c5c4113dSnw141292    2.0 0.0 0.1 0.1
342*c5c4113dSnw141292    2.0 1.0 0.1 0.1
343*c5c4113dSnw141292    2.0 0.0 0.0 0.0
344*c5c4113dSnw141292    2.0 1.0 0.0 0.0
345*c5c4113dSnw141292  } {
346*c5c4113dSnw141292    set testid btree2-$testno.8.$num2
347*c5c4113dSnw141292    set hash [md5file test2.bt]
348*c5c4113dSnw141292    do_test $testid.0 {
349*c5c4113dSnw141292      set ::b [btree_open test2.bt]
350*c5c4113dSnw141292      set ::c2 [btree_cursor $::b 2 1]
351*c5c4113dSnw141292      set ::c3 [btree_cursor $::b 3 1]
352*c5c4113dSnw141292      set ::c4 [btree_cursor $::b 4 1]
353*c5c4113dSnw141292      set ::c5 [btree_cursor $::b 5 1]
354*c5c4113dSnw141292      set ::c6 [btree_cursor $::b 6 1]
355*c5c4113dSnw141292      check_invariants
356*c5c4113dSnw141292    } {}
357*c5c4113dSnw141292    set cnt 6
358*c5c4113dSnw141292    for {set i 2} {$i<=6} {incr i} {
359*c5c4113dSnw141292      if {[lindex [btree_cursor_dump [set ::c$i]] 0]!=$i} {incr cnt}
360*c5c4113dSnw141292    }
361*c5c4113dSnw141292    do_test $testid.1 {
362*c5c4113dSnw141292      btree_begin_transaction $::b
363*c5c4113dSnw141292      lindex [btree_pager_stats $::b] 1
364*c5c4113dSnw141292    } $cnt
365*c5c4113dSnw141292    # exec cp test2.bt test2.bt.bu1
366*c5c4113dSnw141292    do_test $testid.2 [subst {
367*c5c4113dSnw141292      random_changes $n $I $K $D
368*c5c4113dSnw141292    }] {}
369*c5c4113dSnw141292    do_test $testid.3 {
370*c5c4113dSnw141292      check_invariants
371*c5c4113dSnw141292    } {}
372*c5c4113dSnw141292    do_test $testid.4 {
373*c5c4113dSnw141292      btree_close_cursor $::c2
374*c5c4113dSnw141292      btree_close_cursor $::c3
375*c5c4113dSnw141292      btree_close_cursor $::c4
376*c5c4113dSnw141292      btree_close_cursor $::c5
377*c5c4113dSnw141292      btree_close_cursor $::c6
378*c5c4113dSnw141292      btree_rollback $::b
379*c5c4113dSnw141292      md5file test2.bt
380*c5c4113dSnw141292    } $hash
381*c5c4113dSnw141292    # exec cp test2.bt test2.bt.bu2
382*c5c4113dSnw141292    btree_begin_transaction $::b
383*c5c4113dSnw141292    set ::c2 [btree_cursor $::b 2 1]
384*c5c4113dSnw141292    set ::c3 [btree_cursor $::b 3 1]
385*c5c4113dSnw141292    set ::c4 [btree_cursor $::b 4 1]
386*c5c4113dSnw141292    set ::c5 [btree_cursor $::b 5 1]
387*c5c4113dSnw141292    set ::c6 [btree_cursor $::b 6 1]
388*c5c4113dSnw141292    do_test $testid.5 [subst {
389*c5c4113dSnw141292      random_changes $n $I $K $D
390*c5c4113dSnw141292    }] {}
391*c5c4113dSnw141292    do_test $testid.6 {
392*c5c4113dSnw141292      check_invariants
393*c5c4113dSnw141292    } {}
394*c5c4113dSnw141292    do_test $testid.7 {
395*c5c4113dSnw141292      btree_commit $::b
396*c5c4113dSnw141292      check_invariants
397*c5c4113dSnw141292    } {}
398*c5c4113dSnw141292    set hash [md5file test2.bt]
399*c5c4113dSnw141292    do_test $testid.8 {
400*c5c4113dSnw141292      btree_close_cursor $::c2
401*c5c4113dSnw141292      btree_close_cursor $::c3
402*c5c4113dSnw141292      btree_close_cursor $::c4
403*c5c4113dSnw141292      btree_close_cursor $::c5
404*c5c4113dSnw141292      btree_close_cursor $::c6
405*c5c4113dSnw141292      lindex [btree_pager_stats $::b] 1
406*c5c4113dSnw141292    } {0}
407*c5c4113dSnw141292    do_test $testid.9 {
408*c5c4113dSnw141292      btree_close $::b
409*c5c4113dSnw141292      set ::b [btree_open test2.bt]
410*c5c4113dSnw141292      set ::c2 [btree_cursor $::b 2 1]
411*c5c4113dSnw141292      set ::c3 [btree_cursor $::b 3 1]
412*c5c4113dSnw141292      set ::c4 [btree_cursor $::b 4 1]
413*c5c4113dSnw141292      set ::c5 [btree_cursor $::b 5 1]
414*c5c4113dSnw141292      set ::c6 [btree_cursor $::b 6 1]
415*c5c4113dSnw141292      check_invariants
416*c5c4113dSnw141292    } {}
417*c5c4113dSnw141292    do_test $testid.10 {
418*c5c4113dSnw141292      btree_close_cursor $::c2
419*c5c4113dSnw141292      btree_close_cursor $::c3
420*c5c4113dSnw141292      btree_close_cursor $::c4
421*c5c4113dSnw141292      btree_close_cursor $::c5
422*c5c4113dSnw141292      btree_close_cursor $::c6
423*c5c4113dSnw141292      lindex [btree_pager_stats $::b] 1
424*c5c4113dSnw141292    } {0}
425*c5c4113dSnw141292    do_test $testid.11 {
426*c5c4113dSnw141292      btree_close $::b
427*c5c4113dSnw141292    } {}
428*c5c4113dSnw141292    incr num2
429*c5c4113dSnw141292  }
430*c5c4113dSnw141292  incr testno
431*c5c4113dSnw141292  set ::b [btree_open test2.bt]
432*c5c4113dSnw141292}
433*c5c4113dSnw141292
434*c5c4113dSnw141292# Testing is complete.  Shut everything down.
435*c5c4113dSnw141292#
436*c5c4113dSnw141292do_test btree-999.1 {
437*c5c4113dSnw141292  lindex [btree_pager_stats $::b] 1
438*c5c4113dSnw141292} {0}
439*c5c4113dSnw141292do_test btree-999.2 {
440*c5c4113dSnw141292  btree_close $::b
441*c5c4113dSnw141292} {}
442*c5c4113dSnw141292do_test btree-999.3 {
443*c5c4113dSnw141292  file delete -force test2.bt
444*c5c4113dSnw141292  file exists test2.bt-journal
445*c5c4113dSnw141292} {0}
446*c5c4113dSnw141292
447*c5c4113dSnw141292} ;# end if( not mem: and has pager_open command );
448*c5c4113dSnw141292
449*c5c4113dSnw141292finish_test
450