Annotation of embedaddon/sqlite3/test/fuzz3.test, revision 1.1

1.1     ! misho       1: # 2007 May 10
        !             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 implements regression tests for SQLite library.  The focus
        !            12: # of this file is checking the libraries response to subtly corrupting
        !            13: # the database file by changing the values of pseudo-randomly selected
        !            14: # bytes.
        !            15: #
        !            16: # $Id: fuzz3.test,v 1.3 2009/01/05 17:19:03 drh Exp $
        !            17: 
        !            18: set testdir [file dirname $argv0]
        !            19: source $testdir/tester.tcl
        !            20: 
        !            21: 
        !            22: expr srand(123)
        !            23: 
        !            24: proc rstring {n} {
        !            25:   set str s
        !            26:   while {[string length $str] < $n} {
        !            27:     append str [expr rand()]
        !            28:   }
        !            29:   return [string range $str 0 $n]
        !            30: }
        !            31: 
        !            32: # Return a randomly generated SQL literal.
        !            33: #
        !            34: proc rvalue {} {
        !            35:   switch -- [expr int(rand()*5)] {
        !            36:     0 { # SQL NULL value.
        !            37:       return NULL 
        !            38:     }
        !            39:     1 { # Integer value.
        !            40:       return [expr int(rand()*1024)] 
        !            41:     }
        !            42:     2 { # Real value.
        !            43:       return [expr rand()] 
        !            44:     }
        !            45:     3 { # String value.
        !            46:       set n [expr int(rand()*2500)]
        !            47:       return "'[rstring $n]'"
        !            48:     }
        !            49:     4 { # Blob value.
        !            50:       set n [expr int(rand()*2500)]
        !            51:       return "CAST('[rstring $n]' AS BLOB)"
        !            52:     }
        !            53:   }
        !            54: }
        !            55: 
        !            56: proc db_checksum {} {
        !            57:   set    cksum [execsql { SELECT md5sum(a, b, c) FROM t1 }]
        !            58:   append cksum [execsql { SELECT md5sum(d, e, f) FROM t2 }]
        !            59:   set cksum
        !            60: }
        !            61: 
        !            62: # Modify a single byte in the file 'test.db' using tcl IO commands. The
        !            63: # argument value, which must be an integer, determines both the offset of
        !            64: # the byte that is modified, and the value that it is set to. The lower
        !            65: # 8 bits of iMod determine the new byte value. The offset of the byte
        !            66: # modified is the value of ($iMod >> 8).
        !            67: #
        !            68: # The return value is the iMod value required to restore the file
        !            69: # to its original state. The command:
        !            70: #
        !            71: #   modify_database [modify_database $x]
        !            72: #
        !            73: # leaves the file in the same state as it was in at the start of the
        !            74: # command (assuming that the file is at least ($x>>8) bytes in size).
        !            75: #
        !            76: proc modify_database {iMod} {
        !            77:   set blob [binary format c [expr {$iMod&0xFF}]]
        !            78:   set offset [expr {$iMod>>8}]
        !            79: 
        !            80:   set fd [open test.db r+]
        !            81:   fconfigure $fd -encoding binary -translation binary
        !            82:   seek $fd $offset
        !            83:   set old_blob [read $fd 1]
        !            84:   seek $fd $offset
        !            85:   puts -nonewline $fd $blob
        !            86:   close $fd
        !            87: 
        !            88:   binary scan $old_blob c iOld
        !            89:   return [expr {($offset<<8) + ($iOld&0xFF)}]
        !            90: }
        !            91: 
        !            92: proc purge_pcache {} {
        !            93:   ifcapable !memorymanage {
        !            94:     db close
        !            95:     sqlite3 db test.db
        !            96:   } else {
        !            97:     sqlite3_release_memory 10000000
        !            98:   }
        !            99:   if {[lindex [pcache_stats] 1] != 0} {
        !           100:     error "purge_pcache failed: [pcache_stats]"
        !           101:   }
        !           102: }
        !           103: 
        !           104: # This block creates a database to work with. 
        !           105: #
        !           106: do_test fuzz3-1 {
        !           107:   execsql {
        !           108:     BEGIN;
        !           109:     CREATE TABLE t1(a, b, c);
        !           110:     CREATE TABLE t2(d, e, f);
        !           111:     CREATE INDEX i1 ON t1(a, b, c);
        !           112:     CREATE INDEX i2 ON t2(d, e, f);
        !           113:   }
        !           114:   for {set i 0} {$i < 50} {incr i} {
        !           115:     execsql "INSERT INTO t1 VALUES([rvalue], [rvalue], [rvalue])"
        !           116:     execsql "INSERT INTO t2 VALUES([rvalue], [rvalue], [rvalue])"
        !           117:   }
        !           118:   execsql COMMIT
        !           119: } {}
        !           120: 
        !           121: set ::cksum [db_checksum]
        !           122: do_test fuzz3-2 {
        !           123:   db_checksum
        !           124: } $::cksum
        !           125: 
        !           126: for {set ii 0} {$ii < 5000} {incr ii} {
        !           127:   purge_pcache
        !           128: 
        !           129:   # Randomly modify a single byte of the database file somewhere within
        !           130:   # the first 100KB of the file.
        !           131:   set iNew [expr int(rand()*5*1024*256)]
        !           132:   set iOld [modify_database $iNew]
        !           133: 
        !           134:   set iTest 0
        !           135:   foreach sql {
        !           136:     {SELECT * FROM t2 ORDER BY d}      
        !           137:     {SELECT * FROM t1}                 
        !           138:     {SELECT * FROM t2}                 
        !           139:     {SELECT * FROM t1 ORDER BY a}      
        !           140:     {SELECT * FROM t1 WHERE a = (SELECT a FROM t1 WHERE rowid=25)} 
        !           141:     {SELECT * FROM t2 WHERE d = (SELECT d FROM t2 WHERE rowid=1)}  
        !           142:     {SELECT * FROM t2 WHERE d = (SELECT d FROM t2 WHERE rowid=50)} 
        !           143:     {PRAGMA integrity_check}           
        !           144:   } {
        !           145:     do_test fuzz3-$ii.$iNew.[incr iTest] {
        !           146:       foreach {rc msg} [catchsql $sql] {}
        !           147:       if {$rc == 0 
        !           148:        || $msg eq "database or disk is full"
        !           149:        || $msg eq "database disk image is malformed"
        !           150:        || $msg eq "file is encrypted or is not a database"
        !           151:        || [string match "malformed database schema*" $msg]
        !           152:       } {
        !           153:         set msg ok
        !           154:       }
        !           155:       set msg
        !           156:     } {ok}
        !           157:   }
        !           158: 
        !           159:   # Restore the original database file content. Test that the correct 
        !           160:   # checksum is now returned.
        !           161:   #
        !           162:   purge_pcache
        !           163:   modify_database $iOld
        !           164:   do_test fuzz3-$ii.$iNew.[incr iTest] {
        !           165:     db_checksum
        !           166:   } $::cksum
        !           167: }
        !           168: 
        !           169: finish_test

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>