115926590Sdrh# 2007 April 6 215926590Sdrh# 315926590Sdrh# The author disclaims copyright to this source code. In place of 415926590Sdrh# a legal notice, here is a blessing: 515926590Sdrh# 615926590Sdrh# May you do good and not evil. 715926590Sdrh# May you find forgiveness for yourself and forgive others. 815926590Sdrh# May you share freely, never taking more than you give. 915926590Sdrh# 1015926590Sdrh#*********************************************************************** 1115926590Sdrh# This file implements regression tests for SQLite library. 1215926590Sdrh# 1315926590Sdrh# This file implements tests to verify database file format. 1415926590Sdrh# 15ccf6d093Sdrh# $Id: filefmt.test,v 1.3 2009/06/18 11:34:43 drh Exp $ 1615926590Sdrh 1715926590Sdrhset testdir [file dirname $argv0] 1815926590Sdrhsource $testdir/tester.tcl 1968928b6cSdan 2068928b6cSdan# Do not use a codec for tests in this file, as the database file is 2168928b6cSdan# manipulated directly using tcl scripts (using the [hexio_write] command). 2268928b6cSdan# 2368928b6cSdando_not_use_codec 2468928b6cSdan 2515926590Sdrhdb close 26fda06befSmistachkinforcedelete test.db test.db-journal 2715926590Sdrh 2815926590Sdrh# Database begins with valid 16-byte header string. 2915926590Sdrh# 3015926590Sdrhdo_test filefmt-1.1 { 3115926590Sdrh sqlite3 db test.db 3215926590Sdrh db eval {CREATE TABLE t1(x)} 3315926590Sdrh db close 3415926590Sdrh hexio_read test.db 0 16 3515926590Sdrh} {53514C69746520666F726D6174203300} 3615926590Sdrh 3715926590Sdrh# If the 16-byte header is changed, the file will not open 3815926590Sdrh# 3915926590Sdrhdo_test filefmt-1.2 { 4015926590Sdrh hexio_write test.db 0 54 4115926590Sdrh set x [catch {sqlite3 db test.db} err] 4215926590Sdrh lappend x $err 4315926590Sdrh} {0 {}} 4415926590Sdrhdo_test filefmt-1.3 { 4515926590Sdrh catchsql { 4615926590Sdrh SELECT count(*) FROM sqlite_master 4715926590Sdrh } 48*ff4fa772Sdrh} {1 {file is not a database}} 4915926590Sdrhdo_test filefmt-1.4 { 5015926590Sdrh db close 5115926590Sdrh hexio_write test.db 0 53 5215926590Sdrh sqlite3 db test.db 5315926590Sdrh catchsql { 5415926590Sdrh SELECT count(*) FROM sqlite_master 5515926590Sdrh } 5615926590Sdrh} {0 1} 5715926590Sdrh 5815926590Sdrh# The page-size is stored at offset 16 5915926590Sdrh# 6015926590Sdrhifcapable pager_pragmas { 6115926590Sdrh foreach pagesize {512 1024 2048 4096 8192 16384 32768} { 621e9daa6aSdrh if {[info exists SQLITE_MAX_PAGE_SIZE] 631e9daa6aSdrh && $pagesize>$SQLITE_MAX_PAGE_SIZE} continue 6415926590Sdrh do_test filefmt-1.5.$pagesize.1 { 6515926590Sdrh db close 66fda06befSmistachkin forcedelete test.db 6715926590Sdrh sqlite3 db test.db 681e9daa6aSdrh db eval "PRAGMA auto_vacuum=OFF" 6915926590Sdrh db eval "PRAGMA page_size=$pagesize" 7015926590Sdrh db eval {CREATE TABLE t1(x)} 7115926590Sdrh file size test.db 7215926590Sdrh } [expr $pagesize*2] 7315926590Sdrh do_test filefmt-1.5.$pagesize.2 { 7415926590Sdrh hexio_get_int [hexio_read test.db 16 2] 7515926590Sdrh } $pagesize 7615926590Sdrh } 7715926590Sdrh} 7815926590Sdrh 7915926590Sdrh# The page-size must be a power of 2 8015926590Sdrh# 8115926590Sdrhdo_test filefmt-1.6 { 8215926590Sdrh db close 8315926590Sdrh hexio_write test.db 16 [hexio_render_int16 1025] 8415926590Sdrh sqlite3 db test.db 8515926590Sdrh catchsql { 8615926590Sdrh SELECT count(*) FROM sqlite_master 8715926590Sdrh } 88*ff4fa772Sdrh} {1 {file is not a database}} 8915926590Sdrh 9015926590Sdrh 9115926590Sdrh# The page-size must be at least 512 bytes 9215926590Sdrh# 9315926590Sdrhdo_test filefmt-1.7 { 9415926590Sdrh db close 9515926590Sdrh hexio_write test.db 16 [hexio_render_int16 256] 9615926590Sdrh sqlite3 db test.db 9715926590Sdrh catchsql { 9815926590Sdrh SELECT count(*) FROM sqlite_master 9915926590Sdrh } 100*ff4fa772Sdrh} {1 {file is not a database}} 10115926590Sdrh 10215926590Sdrh# Usable space per page (page-size minus unused space per page) 103ccf6d093Sdrh# must be at least 480 bytes 10415926590Sdrh# 10515926590Sdrhifcapable pager_pragmas { 10615926590Sdrh do_test filefmt-1.8 { 10715926590Sdrh db close 108fda06befSmistachkin forcedelete test.db 10915926590Sdrh sqlite3 db test.db 11015926590Sdrh db eval {PRAGMA page_size=512; CREATE TABLE t1(x)} 11115926590Sdrh db close 112ccf6d093Sdrh hexio_write test.db 20 21 11315926590Sdrh sqlite3 db test.db 11415926590Sdrh catchsql { 11515926590Sdrh SELECT count(*) FROM sqlite_master 11615926590Sdrh } 117*ff4fa772Sdrh } {1 {file is not a database}} 11815926590Sdrh} 11915926590Sdrh 12059257dc6Sdan#------------------------------------------------------------------------- 12159257dc6Sdan# The following block of tests - filefmt-2.* - test that versions 3.7.0 12259257dc6Sdan# and later can read and write databases that have been modified or created 12359257dc6Sdan# by 3.6.23.1 and earlier. The difference difference is that 3.7.0 stores 12459257dc6Sdan# the size of the database in the database file header, whereas 3.6.23.1 12559257dc6Sdan# always derives this from the size of the file. 12659257dc6Sdan# 12759257dc6Sdandb close 128fda06befSmistachkinforcedelete test.db 12959257dc6Sdan 13059257dc6Sdanset a_string_counter 1 13159257dc6Sdanproc a_string {n} { 13259257dc6Sdan incr ::a_string_counter 13359257dc6Sdan string range [string repeat "${::a_string_counter}." $n] 1 $n 13459257dc6Sdan} 13559257dc6Sdansqlite3 db test.db 13659257dc6Sdandb func a_string a_string 13759257dc6Sdan 13859257dc6Sdando_execsql_test filefmt-2.1.1 { 13959257dc6Sdan PRAGMA page_size = 1024; 14059257dc6Sdan PRAGMA auto_vacuum = 0; 14159257dc6Sdan CREATE TABLE t1(a); 14259257dc6Sdan CREATE INDEX i1 ON t1(a); 14359257dc6Sdan INSERT INTO t1 VALUES(a_string(3000)); 14459257dc6Sdan CREATE TABLE t2(a); 14559257dc6Sdan INSERT INTO t2 VALUES(1); 14659257dc6Sdan} {} 14782f52540Sdrhif {![nonzero_reserved_bytes]} { 14859257dc6Sdan do_test filefmt-2.1.2 { 14959257dc6Sdan hexio_read test.db 28 4 15059257dc6Sdan } {00000009} 15182f52540Sdrh} 15259257dc6Sdan 15359257dc6Sdando_test filefmt-2.1.3 { 15459257dc6Sdan sql36231 { INSERT INTO t1 VALUES(a_string(3000)) } 15559257dc6Sdan} {} 15659257dc6Sdan 15759257dc6Sdando_execsql_test filefmt-2.1.4 { INSERT INTO t2 VALUES(2) } {} 15859257dc6Sdanintegrity_check filefmt-2.1.5 15959257dc6Sdando_test filefmt-2.1.6 { hexio_read test.db 28 4 } {00000010} 16059257dc6Sdan 16159257dc6Sdandb close 162fda06befSmistachkinforcedelete test.db 16359257dc6Sdansqlite3 db test.db 16459257dc6Sdandb func a_string a_string 16559257dc6Sdan 16659257dc6Sdando_execsql_test filefmt-2.2.1 { 16759257dc6Sdan PRAGMA page_size = 1024; 16859257dc6Sdan PRAGMA auto_vacuum = 0; 16959257dc6Sdan CREATE TABLE t1(a); 17059257dc6Sdan CREATE INDEX i1 ON t1(a); 17159257dc6Sdan INSERT INTO t1 VALUES(a_string(3000)); 17259257dc6Sdan CREATE TABLE t2(a); 17359257dc6Sdan INSERT INTO t2 VALUES(1); 17459257dc6Sdan} {} 17582f52540Sdrhif {![nonzero_reserved_bytes]} { 17659257dc6Sdan do_test filefmt-2.2.2 { 17759257dc6Sdan hexio_read test.db 28 4 17859257dc6Sdan } {00000009} 17982f52540Sdrh} 18059257dc6Sdan 18159257dc6Sdando_test filefmt-2.2.3 { 18259257dc6Sdan sql36231 { INSERT INTO t1 VALUES(a_string(3000)) } 18359257dc6Sdan} {} 18459257dc6Sdan 18559257dc6Sdando_execsql_test filefmt-2.2.4 { 18659257dc6Sdan PRAGMA integrity_check; 18759257dc6Sdan BEGIN; 18859257dc6Sdan INSERT INTO t2 VALUES(2); 18959257dc6Sdan SAVEPOINT a; 19059257dc6Sdan INSERT INTO t2 VALUES(3); 19159257dc6Sdan ROLLBACK TO a; 19259257dc6Sdan} {ok} 19359257dc6Sdan 19459257dc6Sdanintegrity_check filefmt-2.2.5 19559257dc6Sdando_execsql_test filefmt-2.2.6 { COMMIT } {} 19659257dc6Sdandb close 19759257dc6Sdansqlite3 db test.db 19859257dc6Sdanintegrity_check filefmt-2.2.7 19915926590Sdrh 200ecac670aSdan#-------------------------------------------------------------------------- 201ecac670aSdan# Check that ticket 89b8c9ac54 is fixed. Before the fix, the SELECT 202ecac670aSdan# statement would return SQLITE_CORRUPT. The database file was not actually 203ecac670aSdan# corrupted, but SQLite was reporting that it was. 204ecac670aSdan# 205ecac670aSdandb close 206ecac670aSdanforcedelete test.db 207ecac670aSdansqlite3 db test.db 208ecac670aSdando_execsql_test filefmt-3.1 { 209ecac670aSdan PRAGMA auto_vacuum = 1; 210ecac670aSdan CREATE TABLE t1(a, b); 211ecac670aSdan} {} 212ecac670aSdando_test filefmt-3.2 { 213ecac670aSdan sql36231 { DROP TABLE t1 } 214ecac670aSdan} {} 215ecac670aSdando_execsql_test filefmt-3.3 { 216ecac670aSdan SELECT * FROM sqlite_master; 217ecac670aSdan PRAGMA integrity_check; 218ecac670aSdan} {ok} 219ecac670aSdan 2205cc3bea4Sdanreset_db 2215cc3bea4Sdando_execsql_test filefmt-4.1 { 2225cc3bea4Sdan PRAGMA auto_vacuum = 1; 2235cc3bea4Sdan CREATE TABLE t1(x, y); 2245cc3bea4Sdan CREATE TABLE t2(x, y); 2255cc3bea4Sdan 2265cc3bea4Sdan INSERT INTO t1 VALUES(randomblob(100), randomblob(100)); 2275cc3bea4Sdan INSERT INTO t1 VALUES(randomblob(100), randomblob(100)); 2285cc3bea4Sdan INSERT INTO t1 VALUES(randomblob(100), randomblob(100)); 2295cc3bea4Sdan INSERT INTO t1 VALUES(randomblob(100), randomblob(100)); 2305cc3bea4Sdan INSERT INTO t1 VALUES(randomblob(100), randomblob(100)); 2315cc3bea4Sdan INSERT INTO t1 VALUES(randomblob(100), randomblob(100)); 2325cc3bea4Sdan 2335cc3bea4Sdan INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM t1; 2345cc3bea4Sdan INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM t1; 2355cc3bea4Sdan INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM t1; 2365cc3bea4Sdan INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM t1; 2375cc3bea4Sdan} 2385cc3bea4Sdan 2395cc3bea4Sdando_test filefmt-4.2 { 2405cc3bea4Sdan sql36231 { INSERT INTO t2 SELECT * FROM t1 } 2415cc3bea4Sdan} {} 2425cc3bea4Sdan 2435cc3bea4Sdando_test filefmt-4.3 { 2445cc3bea4Sdan forcedelete bak.db 2455cc3bea4Sdan db backup bak.db 2465cc3bea4Sdan} {} 2475cc3bea4Sdan 2485cc3bea4Sdando_test filefmt-4.4 { 2495cc3bea4Sdan sqlite3 db2 bak.db 2505cc3bea4Sdan db2 eval { PRAGMA integrity_check } 2515cc3bea4Sdan} {ok} 2525cc3bea4Sdandb2 close 2535cc3bea4Sdan 25415926590Sdrhfinish_test 255