# 2013 February 08
#
# 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.
#
#***********************************************************************
#
# The focus of this file is testing the LSM library.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lsm_common.tcl
set testprefix lsm5
db close
# Create a new database with file name $file.
#
proc create_abc_db {file} {
forcedelete $file
lsm_open db $file {block_size 256 mmap 0}
db write a alpha
db write b bravo
db write c charlie
db close
}
proc create_abc_log {file} {
forcedelete $file ${file}-2
lsm_open db ${file}-2 {mmap 0}
db write a alpha
db write b bravo
db write c charlie
file copy ${file}-2 $file
file copy ${file}-2-log $file-log
db close
}
#-------------------------------------------------------------------------
# When the database system is shut down (i.e. when the last connection
# disconnects), an attempt is made to truncate the database file to the
# minimum number of blocks required.
#
# This test case checks that this process does not actually cause the
# database to grow.
#
do_test 1.1 {
lsm_open db test.db {mmap 0}
} {db}
do_test 1.2 {
db write 1 one
db write 2 two
db close
} {}
do_test 1.3 {
expr [file size test.db] <= (256*1024)
} 1
#-------------------------------------------------------------------------
# Test that if an attempt is made to open a read-write connection to a
# non-live database that the client does not have permission to write to is
# attempted an error is reported. In order to open a read-write connection
# to a database, the client requires:
#
# * read-write access to the db file,
# * read-write access to the log file,
# * for multi-process mode, read-write access to the shm file.
#
# In the above, "read-write access" includes the ability to create the db,
# log or shm file if it does not exist.
#
# These tests verify that the lsm_open() command returns LSM_IOERR. At some
# point in the future this will be improved. Likely when sqlite4 level tests
# for opening read-only databases are added.
#
foreach {tn filename setup} {
1 test.dir/test.db {
# Create a directory "test.dir".
forcedelete test.dir
file mkdir test.dir
# Create a database within test.dir
create_abc_db test.dir/test.db
# Now make the db and its directory read-only.
file attr test.dir/test.db -perm r--r--r--
file attr test.dir -perm r-xr-xr-x
}
2 test.db {
# Create a database test.db and set its permissions to read-only
create_abc_db test.db
file attr test.db -perm r--r--r--
}
3 test.dir/test.db {
# Create a directory "test.dir".
forcedelete test.dir
file mkdir test.dir
# Create a database within test.dir
create_abc_db test.dir/test.db
# Now make test.dir read-only.
file attr test.dir -perm r-xr-xr-x
}
} {
do_test 2.$tn.1 {
eval $setup
set rc [catch {lsm_open db $filename} msg]
list $rc $msg
} {1 {error in lsm_open() - 10}}
do_test 2.$tn.2 {
eval $setup
lsm_open db $filename {readonly 1}
set res [list [db_fetch db a] [db_fetch db b] [db_fetch db c]]
db close
set res
} {alpha bravo charlie}
}
#-------------------------------------------------------------------------
# Try having a read-only connection connect to a non-live system where the
# log file contains content. In this scenario the read-only client must
# read the contents from the log file at the start of each read-transaction.
#
do_test 3.1 {
create_abc_log test.db
list [file size test.db] [file size test.db-log]
} {0 56}
do_test 3.2 {
lsm_open db $filename {readonly 1}
set res [list [db_fetch db a] [db_fetch db b] [db_fetch db c]]
db close
set res
} {alpha bravo charlie}
do_test 3.3 {
list [file size test.db] [file size test.db-log]
} {0 56}
# Now make the same db live and check the read-only connection can still
# read it.
do_test 3.4 { file exists test.db-shm } 0
do_test 3.5 {
lsm_open db_rw test.db
file exists test.db-shm
} 1
do_test 3.6 {
lsm_open db test.db {readonly 1}
list [db_fetch db a] [db_fetch db b] [db_fetch db c]
} {alpha bravo charlie}
# Close the read-write connection. This should cause a checkpoint and delete
# the log file, even though the system remains live.
do_test 3.7 {
db_rw close
list [file exists test.db-log] [file exists test.db-shm]
} {0 1}
# Now close the read-only connection. The system is now non-live, but the
# *-shm remains in the file-system (the readonly connection cannot unlink it).
do_test 3.8 {
db close
list [file exists test.db-log] [file exists test.db-shm]
} {0 1}
#-------------------------------------------------------------------------
#
do_test 4.1 {
create_abc_log test.db
list [file size test.db] [file size test.db-log]
} {0 56}
do_test 4.2 {
lsm_open db test.db {readonly 1}
db csr_open T
list [db_fetch db a] [db_fetch db b] [db_fetch db c]
} {alpha bravo charlie}
do_test 4.3 {
lsm_open db_rw test.db {block_size 64}
db_rw write b BRAVO
db_rw close
list [file size test.db] [file size test.db-log]
} {65536 74}
do_test 4.4 {
list [db_fetch db a] [db_fetch db b] [db_fetch db c]
} {alpha bravo charlie}
do_test 4.5 {
T close
list [db_fetch db a] [db_fetch db b] [db_fetch db c]
} {alpha BRAVO charlie}
finish_test