1
0

rtreeA.test 6.0 KB

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