| Index: third_party/sqlite/src/test/dbstatus.test
|
| diff --git a/third_party/sqlite/src/test/dbstatus.test b/third_party/sqlite/src/test/dbstatus.test
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..202f34a0435f928e93784e7724e0700280f48979
|
| --- /dev/null
|
| +++ b/third_party/sqlite/src/test/dbstatus.test
|
| @@ -0,0 +1,349 @@
|
| +# 2010 March 10
|
| +#
|
| +# 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.
|
| +#
|
| +#***********************************************************************
|
| +#
|
| +# Tests for the sqlite3_db_status() function
|
| +#
|
| +
|
| +set testdir [file dirname $argv0]
|
| +source $testdir/tester.tcl
|
| +
|
| +# Memory statistics must be enabled for this test.
|
| +db close
|
| +sqlite3_shutdown
|
| +sqlite3_config_memstatus 1
|
| +sqlite3_initialize
|
| +sqlite3 db test.db
|
| +
|
| +
|
| +# Make sure sqlite3_db_config() and sqlite3_db_status are working.
|
| +#
|
| +unset -nocomplain PAGESZ
|
| +unset -nocomplain BASESZ
|
| +do_test dbstatus-1.1 {
|
| + db close
|
| + sqlite3 db :memory:
|
| + db eval {
|
| + CREATE TABLE t1(x);
|
| + }
|
| + set sz1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
|
| + db eval {
|
| + CREATE TABLE t2(y);
|
| + }
|
| + set sz2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
|
| + set ::PAGESZ [expr {$sz2-$sz1}]
|
| + set ::BASESZ [expr {$sz1-$::PAGESZ}]
|
| + expr {$::PAGESZ>1024 && $::PAGESZ<1300}
|
| +} {1}
|
| +do_test dbstatus-1.2 {
|
| + db eval {
|
| + INSERT INTO t1 VALUES(zeroblob(9000));
|
| + }
|
| + lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1
|
| +} [expr {$BASESZ + 10*$PAGESZ}]
|
| +
|
| +
|
| +proc lookaside {db} {
|
| + expr { $::lookaside_buffer_size *
|
| + [lindex [sqlite3_db_status $db SQLITE_DBSTATUS_LOOKASIDE_USED 0] 1]
|
| + }
|
| +}
|
| +
|
| +#---------------------------------------------------------------------------
|
| +# Run the dbstatus-2 and dbstatus-3 tests with several of different
|
| +# lookaside buffer sizes.
|
| +#
|
| +foreach ::lookaside_buffer_size {0 64 120} {
|
| +
|
| + # Do not run any of these tests if there is SQL configured to run
|
| + # as part of the [sqlite3] command. This prevents the script from
|
| + # configuring the size of the lookaside buffer after [sqlite3] has
|
| + # returned.
|
| + if {[presql] != ""} break
|
| +
|
| + #-------------------------------------------------------------------------
|
| + # Tests for SQLITE_DBSTATUS_SCHEMA_USED.
|
| + #
|
| + # Each test in the following block works as follows. Each test uses a
|
| + # different database schema.
|
| + #
|
| + # 1. Open a connection to an empty database. Disable statement caching.
|
| + #
|
| + # 2. Execute the SQL to create the database schema. Measure the total
|
| + # heap and lookaside memory allocated by SQLite, and the memory
|
| + # allocated for the database schema according to sqlite3_db_status().
|
| + #
|
| + # 3. Drop all tables in the database schema. Measure the total memory
|
| + # and the schema memory again.
|
| + #
|
| + # 4. Repeat step 2.
|
| + #
|
| + # 5. Repeat step 3.
|
| + #
|
| + # Then test that:
|
| + #
|
| + # a) The difference in schema memory quantities in steps 2 and 3 is the
|
| + # same as the difference in total memory in steps 2 and 3.
|
| + #
|
| + # b) Step 4 reports the same amount of schema and total memory used as
|
| + # in step 2.
|
| + #
|
| + # c) Step 5 reports the same amount of schema and total memory used as
|
| + # in step 3.
|
| + #
|
| + foreach {tn schema} {
|
| + 1 { CREATE TABLE t1(a, b) }
|
| + 2 { CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1, c UNIQUE) }
|
| + 3 {
|
| + CREATE TABLE t1(a, b);
|
| + CREATE INDEX i1 ON t1(a, b);
|
| + }
|
| + 4 {
|
| + CREATE TABLE t1(a, b);
|
| + CREATE TABLE t2(c, d);
|
| + CREATE TRIGGER AFTER INSERT ON t1 BEGIN
|
| + INSERT INTO t2 VALUES(new.a, new.b);
|
| + SELECT * FROM t1, t2 WHERE a=c AND b=d GROUP BY b HAVING a>5 ORDER BY a;
|
| + END;
|
| + }
|
| + 5 {
|
| + CREATE TABLE t1(a, b);
|
| + CREATE TABLE t2(c, d);
|
| + CREATE VIEW v1 AS SELECT * FROM t1 UNION SELECT * FROM t2;
|
| + }
|
| + 6 {
|
| + CREATE TABLE t1(a, b);
|
| + CREATE INDEX i1 ON t1(a);
|
| + CREATE INDEX i2 ON t1(a,b);
|
| + CREATE INDEX i3 ON t1(b,b);
|
| + INSERT INTO t1 VALUES(randomblob(20), randomblob(25));
|
| + INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
|
| + ANALYZE;
|
| + }
|
| + 7 {
|
| + CREATE TABLE t1(a, b);
|
| + CREATE TABLE t2(c, d);
|
| + CREATE VIEW v1 AS
|
| + SELECT * FROM t1
|
| + UNION
|
| + SELECT * FROM t2
|
| + UNION ALL
|
| + SELECT c||b, d||a FROM t2 LEFT OUTER JOIN t1 GROUP BY c, d
|
| + ORDER BY 1, 2
|
| + ;
|
| + CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN
|
| + SELECT * FROM v1;
|
| + UPDATE t1 SET a=5, b=(SELECT c FROM t2);
|
| + END;
|
| + SELECT * FROM v1;
|
| + }
|
| + 8x {
|
| + CREATE TABLE t1(a, b, UNIQUE(a, b));
|
| + CREATE VIRTUAL TABLE t2 USING echo(t1);
|
| + }
|
| + } {
|
| + set tn "$::lookaside_buffer_size-$tn"
|
| +
|
| + # Step 1.
|
| + db close
|
| + file delete -force test.db
|
| + sqlite3 db test.db
|
| + sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
|
| + db cache size 0
|
| +
|
| + catch { register_echo_module db }
|
| + ifcapable !vtab { if {[string match *x $tn]} continue }
|
| +
|
| + # Step 2.
|
| + execsql $schema
|
| + set nAlloc1 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
|
| + incr nAlloc1 [lookaside db]
|
| + set nSchema1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
|
| +
|
| + # Step 3.
|
| + drop_all_tables
|
| + set nAlloc2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
|
| + incr nAlloc2 [lookaside db]
|
| + set nSchema2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
|
| +
|
| + # Step 4.
|
| + execsql $schema
|
| + set nAlloc3 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
|
| + incr nAlloc3 [lookaside db]
|
| + set nSchema3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
|
| +
|
| + # Step 5.
|
| + drop_all_tables
|
| + set nAlloc4 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
|
| + incr nAlloc4 [lookaside db]
|
| + set nSchema4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
|
| + set nFree [expr {$nAlloc1-$nAlloc2}]
|
| +
|
| + # Tests for which the test name ends in an "x" report slightly less
|
| + # memory than is actually freed when all schema items are finalized.
|
| + # This is because memory allocated by virtual table implementations
|
| + # for any reason is not counted as "schema memory".
|
| + #
|
| + # Additionally, in auto-vacuum mode, dropping tables and indexes causes
|
| + # the page-cache to shrink. So the amount of memory freed is always
|
| + # much greater than just that reported by DBSTATUS_SCHEMA_USED in this
|
| + # case.
|
| + #
|
| + if {[string match *x $tn] || $AUTOVACUUM} {
|
| + do_test dbstatus-2.$tn.ax { expr {($nSchema1-$nSchema2)<=$nFree} } 1
|
| + } else {
|
| + do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree
|
| + }
|
| +
|
| + do_test dbstatus-2.$tn.b { list $nAlloc1 $nSchema1 } "$nAlloc3 $nSchema3"
|
| + do_test dbstatus-2.$tn.c { list $nAlloc2 $nSchema2 } "$nAlloc4 $nSchema4"
|
| + }
|
| +
|
| + #-------------------------------------------------------------------------
|
| + # Tests for SQLITE_DBSTATUS_STMT_USED.
|
| + #
|
| + # Each test in the following block works as follows. Each test uses a
|
| + # different database schema.
|
| + #
|
| + # 1. Open a connection to an empty database. Initialized the database
|
| + # schema.
|
| + #
|
| + # 2. Prepare a bunch of SQL statements. Measure the total heap and
|
| + # lookaside memory allocated by SQLite, and the memory allocated
|
| + # for the prepared statements according to sqlite3_db_status().
|
| + #
|
| + # 3. Finalize all prepared statements Measure the total memory
|
| + # and the prepared statement memory again.
|
| + #
|
| + # 4. Repeat step 2.
|
| + #
|
| + # 5. Repeat step 3.
|
| + #
|
| + # Then test that:
|
| + #
|
| + # a) The difference in schema memory quantities in steps 2 and 3 is the
|
| + # same as the difference in total memory in steps 2 and 3.
|
| + #
|
| + # b) Step 4 reports the same amount of schema and total memory used as
|
| + # in step 2.
|
| + #
|
| + # c) Step 5 reports the same amount of schema and total memory used as
|
| + # in step 3.
|
| + #
|
| + foreach {tn schema statements} {
|
| + 1 { CREATE TABLE t1(a, b) } {
|
| + SELECT * FROM t1;
|
| + INSERT INTO t1 VALUES(1, 2);
|
| + INSERT INTO t1 SELECT * FROM t1;
|
| + UPDATE t1 SET a=5;
|
| + DELETE FROM t1;
|
| + }
|
| + 2 {
|
| + PRAGMA recursive_triggers = 1;
|
| + CREATE TABLE t1(a, b);
|
| + CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
|
| + INSERT INTO t1 VALUES(new.a-1, new.b);
|
| + END;
|
| + } {
|
| + INSERT INTO t1 VALUES(5, 'x');
|
| + }
|
| + 3 {
|
| + PRAGMA recursive_triggers = 1;
|
| + CREATE TABLE t1(a, b);
|
| + CREATE TABLE t2(a, b);
|
| + CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
|
| + INSERT INTO t2 VALUES(new.a-1, new.b);
|
| + END;
|
| + CREATE TRIGGER tr2 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
|
| + INSERT INTO t1 VALUES(new.a-1, new.b);
|
| + END;
|
| + } {
|
| + INSERT INTO t1 VALUES(10, 'x');
|
| + }
|
| + 4 {
|
| + CREATE TABLE t1(a, b);
|
| + } {
|
| + SELECT count(*) FROM t1 WHERE upper(a)='ABC';
|
| + }
|
| + 5x {
|
| + CREATE TABLE t1(a, b UNIQUE);
|
| + CREATE VIRTUAL TABLE t2 USING echo(t1);
|
| + } {
|
| + SELECT count(*) FROM t2;
|
| + SELECT * FROM t2 WHERE b>5;
|
| + SELECT * FROM t2 WHERE b='abcdefg';
|
| + }
|
| + } {
|
| + set tn "$::lookaside_buffer_size-$tn"
|
| +
|
| + # Step 1.
|
| + db close
|
| + file delete -force test.db
|
| + sqlite3 db test.db
|
| + sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
|
| + db cache size 1000
|
| +
|
| + catch { register_echo_module db }
|
| + ifcapable !vtab { if {[string match *x $tn]} continue }
|
| +
|
| + execsql $schema
|
| + db cache flush
|
| +
|
| + # Step 2.
|
| + execsql $statements
|
| + set nAlloc1 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
|
| + incr nAlloc1 [lookaside db]
|
| + set nStmt1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
|
| + execsql $statements
|
| +
|
| + # Step 3.
|
| + db cache flush
|
| + set nAlloc2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
|
| + incr nAlloc2 [lookaside db]
|
| + set nStmt2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
|
| +
|
| + # Step 3.
|
| + execsql $statements
|
| + set nAlloc3 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
|
| + incr nAlloc3 [lookaside db]
|
| + set nStmt3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
|
| + execsql $statements
|
| +
|
| + # Step 4.
|
| + db cache flush
|
| + set nAlloc4 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
|
| + incr nAlloc4 [lookaside db]
|
| + set nStmt4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
|
| +
|
| + set nFree [expr {$nAlloc1-$nAlloc2}]
|
| +
|
| + do_test dbstatus-3.$tn.a { expr $nStmt2 } {0}
|
| +
|
| + # Tests for which the test name ends in an "x" report slightly less
|
| + # memory than is actually freed when all statements are finalized.
|
| + # This is because a small amount of memory allocated by a virtual table
|
| + # implementation using sqlite3_mprintf() is technically considered
|
| + # external and so is not counted as "statement memory".
|
| + #
|
| +#puts "$nStmt1 $nFree"
|
| + if {[string match *x $tn]} {
|
| + do_test dbstatus-3.$tn.bx { expr $nStmt1<=$nFree } {1}
|
| + } else {
|
| + do_test dbstatus-3.$tn.b { expr $nStmt1==$nFree } {1}
|
| + }
|
| +
|
| + do_test dbstatus-3.$tn.c { list $nAlloc1 $nStmt1 } [list $nAlloc3 $nStmt3]
|
| + do_test dbstatus-3.$tn.d { list $nAlloc2 $nStmt2 } [list $nAlloc4 $nStmt4]
|
| + }
|
| +}
|
| +
|
| +finish_test
|
|
|