# 2005 November 30 # # 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. # #*********************************************************************** # # $Id: malloc5.test,v 1.1 2005/12/19 14:18:12 danielk1977 Exp $ #--------------------------------------------------------------------------- # NOTES ON EXPECTED BEHAVIOUR # #--------------------------------------------------------------------------- set testdir [file dirname $argv0] source $testdir/tester.tcl do_test malloc5-1.1 { # Simplest possible test. Call [db release_memory] when there is exactly # one unused page in a single pager cache. This test case set's the # value of the ::pgalloc variable, which is used in subsequent tests. # # Note: Even though executing this statement on an empty database # modifies 2 pages (the root of sqlite_master and the new root page), # the sqlite_master root (page 1) is never freed because the btree layer # retains a reference to it for the entire transaction. execsql { BEGIN; CREATE TABLE abc(a, b, c); } set ::pgalloc [db release_memory] expr $::pgalloc > 0 } {1} do_test malloc5-1.2 { # Test that the transaction started in the above test is still active. # Because the page freed had been written to, freeing it required a # journal sync and exclusive lock on the database file. Test the file # appears to be locked. sqlite3 db2 test.db catchsql { SELECT * FROM abc; } db2 } {1 {database is locked}} do_test malloc5-1.3 { # Again call [db release_memory] when there is exactly one unused page # in the cache. The same amount of memory is required, but no journal-sync # or exclusive lock should be established. execsql { COMMIT; BEGIN; SELECT * FROM abc; } db release_memory } $::pgalloc do_test malloc5-1.4 { # Database should not be locked this time. catchsql { SELECT * FROM abc; } db2 } {0 {}} do_test malloc5-1.5 { # Manipulate the cache so that it contains two unused pages. One requires # a journal-sync to free, the other does not. execsql { SELECT * FROM abc; CREATE TABLE def(d, e, f); } db release_memory 500 } $::pgalloc do_test malloc5-1.6 { # Database should not be locked this time. The above test case only # requested 500 bytes of memory, which can be obtained by freeing the page # that does not require an fsync(). catchsql { SELECT * FROM abc; } db2 } {0 {}} do_test malloc5-1.7 { # Release another 500 bytes of memory. This time we require a sync(), # so the database file will be locked afterwards. db release_memory 500 } $::pgalloc do_test malloc5-1.8 { catchsql { SELECT * FROM abc; } db2 } {1 {database is locked}} do_test malloc5-1.9 { execsql { COMMIT; } } {} do_test malloc5-2.1 { # Put some data in tables abc and def. Both tables are still wholly # contained within their root pages. execsql { INSERT INTO abc VALUES(1, 2, 3); INSERT INTO abc VALUES(4, 5, 6); INSERT INTO def VALUES(7, 8, 9); INSERT INTO def VALUES(10,11,12); } } {} do_test malloc5-2.2 { # Load the root-page for table def into the cache. Then query table abc. # Halfway through the query call sqlite3_release_memory(). The goal of this # test is to make sure we don't free pages that are in use (specifically, # the root of table abc). set nRelease 0 execsql { BEGIN; SELECT * FROM def; } db eval {SELECT * FROM abc} { incr nRelease [db release_memory] lappend data $a $b $c } list $nRelease $data } [list $pgalloc [list 1 2 3 4 5 6]] finish_test