aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/sqlite/unix/sqlite-3.5.1/test/mallocC.test
blob: 54e4c5f7c6b8d5e2b2b1c6d8576cbcbaa4f5b9e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# 2007 Aug 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# 
# This file tests aspects of the malloc failure while parsing
# CREATE TABLE statements in auto_vacuum mode.
#
# $Id: mallocC.test,v 1.7 2007/10/03 08:46:45 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if memory debugging is turned on.
#
ifcapable !memdebug||!compound {
   puts "Skipping mallocC tests: not compiled with -DSQLITE_MEMDEBUG..."
   finish_test
   return
}

# Generate a checksum based on the contents of the database. If the
# checksum of two databases is the same, and the integrity-check passes
# for both, the two databases are identical.
#
proc cksum {db} {
  set ret [list]
  ifcapable tempdb {
    set sql {
      SELECT name FROM sqlite_master WHERE type = 'table' UNION
      SELECT name FROM sqlite_temp_master WHERE type = 'table' UNION
      SELECT 'sqlite_master' UNION
      SELECT 'sqlite_temp_master'
    }
  } else {
    set sql {
      SELECT name FROM sqlite_master WHERE type = 'table' UNION
      SELECT 'sqlite_master'
    }
  }
  set tbllist [$db eval $sql]
  set txt {}
  foreach tbl $tbllist {
    append txt [$db eval "SELECT * FROM $tbl"]
  }
  # puts txt=$txt
  return [md5 $txt]
}

proc do_mallocC_test {tn args} {
  array set ::mallocopts $args
  set sum [cksum db]

  for {set ::n 1} {true} {incr ::n} {

    # Run the SQL. Malloc number $::n is set to fail. A malloc() failure
    # may or may not be reported.
    sqlite3_memdebug_fail $::n -repeat 1
    do_test mallocC-$tn.$::n.1 {
      set res [catchsql [string trim $::mallocopts(-sql)]]
      set rc [expr { 
        0==[string compare $res {1 {out of memory}}] ||
        [db errorcode] == 3082 ||
        0==[lindex $res 0]
      }]
      if {$rc!=1} {
        puts "Error: $res"
      }
      set rc
    } {1}

    # If $::n is greater than the number of malloc() calls required to
    # execute the SQL, then this test is finished. Break out of the loop.
    set nFail [sqlite3_memdebug_fail -1]
    if {$nFail==0} {
      break
    }

    # Recover from the malloc failure.
    #
    # Update: The new malloc() failure handling means that a transaction may
    # still be active even if a malloc() has failed. But when these tests were
    # written this was not the case. So do a manual ROLLBACK here so that the
    # tests pass.
    do_test mallocC-$tn.$::n.2 {
      catch {
        execsql {
          ROLLBACK;
        }
      }
      expr 0
    } {0}

    # Checksum the database.
    #do_test mallocC-$tn.$::n.3 {
    #  cksum db
    #} $sum

    #integrity_check mallocC-$tn.$::n.4
  if {$::nErr>1} return
  }
  unset ::mallocopts
}

sqlite3_extended_result_codes db 1

execsql {
  PRAGMA auto_vacuum=1;
  CREATE TABLE t0(a, b, c);
}
do_mallocC_test 1 -sql {
  BEGIN;
  -- Allocate 32 new root pages. This will exercise the 'extract specific 
  -- page from the freelist' code when in auto-vacuum mode (see the
  -- allocatePage() routine in btree.c).
  CREATE TABLE t1(a UNIQUE, b UNIQUE, c UNIQUE);
  CREATE TABLE t2(a UNIQUE, b UNIQUE, c UNIQUE);
  CREATE TABLE t3(a UNIQUE, b UNIQUE, c UNIQUE);
  CREATE TABLE t4(a UNIQUE, b UNIQUE, c UNIQUE);
  CREATE TABLE t5(a UNIQUE, b UNIQUE, c UNIQUE);
  CREATE TABLE t6(a UNIQUE, b UNIQUE, c UNIQUE);
  CREATE TABLE t7(a UNIQUE, b UNIQUE, c UNIQUE);
  CREATE TABLE t8(a UNIQUE, b UNIQUE, c UNIQUE);

  ROLLBACK;
}

finish_test