gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/malloc4.test (about)

     1  # 2005 November 30
     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  #
    12  # This file contains tests to ensure that the library handles malloc() failures
    13  # correctly. The emphasis in this file is on sqlite3_column_XXX() APIs.
    14  #
    15  # $Id: malloc4.test,v 1.10 2008/02/18 22:24:58 drh Exp $
    16  
    17  #---------------------------------------------------------------------------
    18  # NOTES ON EXPECTED BEHAVIOUR
    19  #
    20  # [193] When a memory allocation failure occurs during sqlite3_column_name(),
    21  #       sqlite3_column_name16(), sqlite3_column_decltype(), or
    22  #       sqlite3_column_decltype16() the function shall return NULL.
    23  #
    24  #---------------------------------------------------------------------------
    25  
    26  set testdir [file dirname $argv0]
    27  source $testdir/tester.tcl
    28  source $testdir/malloc_common.tcl
    29  
    30  # Only run these tests if memory debugging is turned on.
    31  if {!$MEMDEBUG} {
    32     puts "Skipping malloc4 tests: not compiled with -DSQLITE_MEMDEBUG..."
    33     finish_test
    34     return
    35  }
    36  
    37  ifcapable !utf16 {
    38    finish_test
    39    return
    40  }
    41  
    42  proc do_stmt_test {id sql} {
    43    set ::sql $sql
    44    set go 1
    45    for {set n 0} {$go} {incr n} {
    46      set testid "malloc4-$id.$n"
    47  
    48      # Prepare the statement
    49      do_test ${testid}.1 {
    50        set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL]
    51        expr [string length $::STMT] > 0
    52      } {1}
    53  
    54      # Set the Nth malloc() to fail.
    55      sqlite3_memdebug_fail $n -repeat 0
    56  
    57      # Test malloc failure in the _name(), _name16(), decltype() and
    58      # decltype16() APIs. Calls that occur after the malloc() failure should
    59      # return NULL. No error is raised though.
    60      #
    61      # ${testid}.2.1 - Call _name()
    62      # ${testid}.2.2 - Call _name16()
    63      # ${testid}.2.3 - Call _name()
    64      # ${testid}.2.4 - Check that the return values of the above three calls are
    65      #                 consistent with each other and with the simulated
    66      #                 malloc() failures.
    67      #
    68      # Because the code that implements the _decltype() and _decltype16() APIs
    69      # is the same as the _name() and _name16() implementations, we don't worry
    70      # about explicitly testing them.
    71      #
    72      do_test ${testid}.2.1 {
    73        set mf1 [expr [sqlite3_memdebug_pending] < 0]
    74        set ::name8  [sqlite3_column_name $::STMT 0]
    75        set mf2 [expr [sqlite3_memdebug_pending] < 0]
    76        expr {$mf1 == $mf2 || $::name8 == ""}
    77      } {1}
    78      do_test ${testid}.2.2 {
    79        set mf1 [expr [sqlite3_memdebug_pending] < 0]
    80        set ::name16 [sqlite3_column_name16 $::STMT 0]
    81        set ::name16 [encoding convertfrom unicode $::name16]
    82        set ::name16 [string range $::name16 0 end-1]
    83        set mf2 [expr [sqlite3_memdebug_pending] < 0]
    84        expr {$mf1 == $mf2 || $::name16 == ""}
    85      } {1}
    86      do_test ${testid}.2.3 {
    87        set mf1 [expr [sqlite3_memdebug_pending] < 0]
    88        set ::name8_2 [sqlite3_column_name $::STMT 0]
    89        set mf2 [expr [sqlite3_memdebug_pending] < 0]
    90        expr {$mf1 == $mf2 || $::name8_2 == ""}
    91      } {1}
    92      set ::mallocFailed [expr [sqlite3_memdebug_pending] < 0]
    93      do_test ${testid}.2.4 {
    94        expr {
    95          $::name8 == $::name8_2 && $::name16 == $::name8 && !$::mallocFailed ||
    96          $::name8 == $::name8_2 && $::name16 == "" &&        $::mallocFailed ||
    97          $::name8 == $::name16 && $::name8_2 == "" &&        $::mallocFailed ||
    98          $::name8_2 == $::name16 && $::name8 == "" &&        $::mallocFailed
    99        }
   100      } {1}
   101  
   102      # Step the statement so that we can call _text() and _text16().  Before
   103      # running sqlite3_step(), make sure that malloc() is not about to fail.
   104      # Memory allocation failures that occur within sqlite3_step() are tested
   105      # elsewhere.
   106      set mf [sqlite3_memdebug_pending]
   107      sqlite3_memdebug_fail -1
   108      do_test ${testid}.3 {
   109        sqlite3_step $::STMT
   110      } {SQLITE_ROW}
   111      sqlite3_memdebug_fail $mf
   112  
   113      # Test for malloc() failures within _text() and _text16().
   114      #
   115      do_test ${testid}.4.1 {
   116        set ::text8 [sqlite3_column_text $::STMT 0]
   117        set mf [expr [sqlite3_memdebug_pending] < 0 && !$::mallocFailed]
   118        expr {$mf==0 || $::text8 == ""}
   119      } {1}
   120      do_test ${testid}.4.2 {
   121        set ::text16 [sqlite3_column_text16 $::STMT 0]
   122        set ::text16 [encoding convertfrom unicode $::text16]
   123        set ::text16 [string range $::text16 0 end-1]
   124        set mf [expr [sqlite3_memdebug_pending] < 0 && !$::mallocFailed]
   125        expr {$mf==0 || $::text16 == ""}
   126      } {1}
   127      do_test ${testid}.4.3 {
   128        set ::text8_2 [sqlite3_column_text $::STMT 0]
   129        set mf [expr [sqlite3_memdebug_pending] < 0 && !$::mallocFailed]
   130        expr {$mf==0 || $::text8_2 == "" || ($::text16 == "" && $::text8 != "")}
   131      } {1}
   132  
   133      # Test for malloc() failures within _int(), _int64() and _real(). The only
   134      # way this can occur is if the string has to be translated from UTF-16 to
   135      # UTF-8 before being converted to a numeric value.
   136      do_test ${testid}.4.4.1 {
   137        set mf [sqlite3_memdebug_pending]
   138        sqlite3_memdebug_fail -1
   139        sqlite3_column_text16 $::STMT 0
   140        sqlite3_memdebug_fail $mf
   141        sqlite3_column_int $::STMT 0
   142      } {0}
   143      do_test ${testid}.4.5 {
   144        set mf [sqlite3_memdebug_pending]
   145        sqlite3_memdebug_fail -1
   146        sqlite3_column_text16 $::STMT 0
   147        sqlite3_memdebug_fail $mf
   148        sqlite3_column_int64 $::STMT 0
   149      } {0}
   150  
   151      do_test ${testid}.4.6 {
   152        set mf [sqlite3_memdebug_pending]
   153        sqlite3_memdebug_fail -1
   154        sqlite3_column_text16 $::STMT 0
   155        sqlite3_memdebug_fail $mf
   156        sqlite3_column_double $::STMT 0
   157      } {0.0}
   158  
   159      set mallocFailedAfterStep [expr \
   160        [sqlite3_memdebug_pending] < 0 && !$::mallocFailed
   161      ]
   162  
   163      sqlite3_memdebug_fail -1
   164      # Test that if a malloc() failed the next call to sqlite3_step() returns
   165      # SQLITE_ERROR. If malloc() did not fail, it should return SQLITE_DONE.
   166      #
   167      do_test ${testid}.5 {
   168        sqlite3_step $::STMT
   169      } [expr {$mallocFailedAfterStep ? "SQLITE_ERROR" : "SQLITE_DONE"}]
   170  
   171      do_test ${testid}.6 {
   172        sqlite3_finalize $::STMT
   173      } [expr {$mallocFailedAfterStep ? "SQLITE_NOMEM" : "SQLITE_OK"}]
   174  
   175      if {$::mallocFailed == 0 && $mallocFailedAfterStep == 0} {
   176        sqlite3_memdebug_fail -1
   177        set go 0
   178      }
   179    }
   180  }
   181  
   182  execsql {
   183    CREATE TABLE tbl(
   184      the_first_reasonably_long_column_name that_also_has_quite_a_lengthy_type
   185    );
   186    INSERT INTO tbl VALUES(
   187      'An extra long string. Far too long to be stored in NBFS bytes.'
   188    );
   189  }
   190  
   191  do_stmt_test 1 "SELECT * FROM tbl"
   192  
   193  sqlite3_memdebug_fail -1
   194  finish_test