# 2007 May 05
#
# 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 contains common code used by many different malloc tests
# within the test suite.
#
# $Id: malloc_common.tcl,v 1.22 2008/09/23 16:41:30 danielk1977 Exp $
# If we did not compile with malloc testing enabled, then do nothing.
#
ifcapable builtin_test else
# Transient and persistent OOM errors:
#
set FAULTSIM(oom-transient)
set FAULTSIM(oom-persistent)
# Transient and persistent IO errors:
#
set FAULTSIM(ioerr-transient)
set FAULTSIM(ioerr-persistent)
# SQLITE_FULL errors (always persistent):
#
set FAULTSIM(full)
# Transient and persistent SHM errors:
#
set FAULTSIM(shmerr-transient)
set FAULTSIM(shmerr-persistent)
# Transient and persistent CANTOPEN errors:
#
set FAULTSIM(cantopen-transient)
set FAULTSIM(cantopen-persistent)
set FAULTSIM(interrupt)
#--------------------------------------------------------------------------
# Usage do_faultsim_test NAME ?OPTIONS...?
#
# -faults List of fault types to simulate.
#
# -prep Script to execute before -body.
#
# -body Script to execute (with fault injection).
#
# -test Script to execute after -body.
#
# -install Script to execute after faultsim -injectinstall
#
# -uninstall Script to execute after faultsim -uninjectinstall
#
#-------------------------------------------------------------------------
# Procedures to save and restore the current file-system state:
#
# faultsim_save
# faultsim_restore
# faultsim_save_and_close
# faultsim_restore_and_reopen
# faultsim_delete_and_reopen
#
# The following procs are used as [do_one_faultsim_test] callbacks when
# injecting OOM faults into test cases.
#
# The following procs are used as [do_one_faultsim_test] callbacks when
# injecting IO error faults into test cases.
#
# The following procs are used as [do_one_faultsim_test] callbacks when
# injecting shared-memory related error faults into test cases.
#
# The following procs are used as [do_one_faultsim_test] callbacks when
# injecting SQLITE_FULL error faults into test cases.
#
# The following procs are used as [do_one_faultsim_test] callbacks when
# injecting SQLITE_CANTOPEN error faults into test cases.
#
# The following procs are used as [do_one_faultsim_test] callbacks
# when injecting SQLITE_INTERRUPT error faults into test cases.
#
# This command is not called directly. It is used by the
# [faultsim_test_result] command created by [do_faultsim_test] and used
# by -test scripts.
#
#--------------------------------------------------------------------------
# Usage do_one_faultsim_test NAME ?OPTIONS...?
#
# The first argument, <test number>, is used as a prefix of the test names
# taken by tests executed by this command. Options are as follows. All
# options take a single argument.
#
# -injectstart Script to enable fault-injection.
#
# -injectstop Script to disable fault-injection.
#
# -injecterrlist List of generally acceptable test results (i.e. error
# messages). Example: [list {1 {out of memory}}]
#
# -injectinstall
#
# -injectuninstall
#
# -prep Script to execute before -body.
#
# -body Script to execute (with fault injection).
#
# -test Script to execute after -body.
#
# -start Index of first fault to inject (default 1)
#
# Usage: do_malloc_test <test number> <options...>
#
# The first argument, <test number>, is an integer used to name the
# tests executed by this proc. Options are as follows:
#
# -tclprep TCL script to run to prepare test.
# -sqlprep SQL script to run to prepare test.
# -tclbody TCL script to run with malloc failure simulation.
# -sqlbody TCL script to run with malloc failure simulation.
# -cleanup TCL script to run after the test.
#
# This command runs a series of tests to verify SQLite's ability
# to handle an out-of-memory condition gracefully. It is assumed
# that if this condition occurs a malloc() call will return a
# NULL pointer. Linux, for example, doesn't do that by default. See
# the "BUGS" section of malloc(3).
#
# Each iteration of a loop, the TCL commands in any argument passed
# to the -tclbody switch, followed by the SQL commands in any argument
# passed to the -sqlbody switch are executed. Each iteration the
# Nth call to sqliteMalloc() is made to fail, where N is increased
# each time the loop runs starting from 1. When all commands execute
# successfully, the loop ends.
#
#-------------------------------------------------------------------------
# This proc is used to test a single SELECT statement. Parameter $name is
# passed a name for the test case (i.e. "fts3_malloc-1.4.1") and parameter
# $sql is passed the text of the SELECT statement. Parameter $result is
# set to the expected output if the SELECT statement is successfully
# executed using [db eval].
#
# Example:
#
# do_select_test testcase-1.1 "SELECT 1+1, 1+2" {1 2}
#
# If global variable DO_MALLOC_TEST is set to a non-zero value, or if
# it is not defined at all, then OOM testing is performed on the SELECT
# statement. Each OOM test case is said to pass if either (a) executing
# the SELECT statement succeeds and the results match those specified
# by parameter $result, or (b) TCL throws an "out of memory" error.
#
# If DO_MALLOC_TEST is defined and set to zero, then the SELECT statement
# is executed just once. In this case the test case passes if the results
# match the expected results passed via parameter $result.
#
#-------------------------------------------------------------------------
# Test a single write to the database. In this case a "write" is a
# DELETE, UPDATE or INSERT statement.
#
# If OOM testing is performed, there are several acceptable outcomes:
#
# 1) The write succeeds. No error is returned.
#
# 2) An "out of memory" exception is thrown and:
#
# a) The statement has no effect, OR
# b) The current transaction is rolled back, OR
# c) The statement succeeds. This can only happen if the connection
# is in auto-commit mode (after the statement is executed, so this
# includes COMMIT statements).
#
# If the write operation eventually succeeds, zero is returned. If a
# transaction is rolled back, non-zero is returned.
#
# Parameter $name is the name to use for the test case (or test cases).
# The second parameter, $tbl, should be the name of the database table
# being modified. Parameter $sql contains the SQL statement to test.
#