# 2017 April 25
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the server mode of SQLite.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix serverlimit
source $testdir/server_common.tcl
source $testdir/lock_common.tcl
return_if_no_server
#-------------------------------------------------------------------------
# Test plan:
#
# 1.* The concurrent connections limit in multi-process mode. With all
# connections in the local process.
#
# 2.* The concurrent connections limit in multi-process mode. Using
# multiple processes.
#
# 3.* The concurrent transactions limit in single-process mode.
#
server_set_vfs multi
server_reset_db
set MLIMIT 16 ;# maximum number of allowed connections
do_test 1.0 {
server_sqlite3 db test.db
db eval {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES('hello'), ('world');
}
db close
for {set i 0} {$i < $MLIMIT} {incr i} {
server_sqlite3 db.$i test.db
db.$i eval { SELECT * FROM t1 }
}
set {} {}
} {}
# Connection [db] cannot connect - all client slots are occupied.
#
do_test 1.1 {
server_sqlite3 db test.db
list [catch { db eval { SELECT * FROM t1 } } msg] $msg
} {1 {database is locked}}
# But, if one connection disconnects, [db] can then connect and
# query the db.
#
do_test 1.2 {
db.0 close
list [catch { db eval { SELECT * FROM t1 } } msg] $msg
} {0 {hello world}}
do_test 1.3 {
for {set i 0} {$i < $MLIMIT} {incr i} {
catch { db.$i close }
}
set {} {}
} {}
#-------------------------------------------------------------------------
# Connections in different processes.
do_multiclient_test tn {
code1 { db close }
code2 { db2 close }
code3 { db3 close }
set N1 [expr $MLIMIT / 2]
set N2 [expr $MLIMIT - $N1]
do_test 2.$tn.0 {
file mkdir test.db-journal
code1 {
sqlite3 db test.db
db eval {
CREATE TABLE t11(a, b);
INSERT INTO t11 VALUES(1, 2), (3, 4);
}
db close
for {set i 0} {$i < $N1} {incr i} {
sqlite3 db.$i test.db
db.$i eval { SELECT * FROM t11 }
}
}
code2 [string map [list %N2% $N2] {
for {set i 0} {$i < %N2%} {incr i} {
sqlite3 db2.$i test.db
db2.$i eval { SELECT * FROM t11 }
}
}]
code2 { db2.0 eval {SELECT * FROM t11} }
} {1 2 3 4}
do_test 2.$tn.1 {
code3 { sqlite3 db3 test.db }
csql3 { SELECT * FROM t11 }
} {1 {database is locked}}
do_test 2.$tn.2 {
code2 { db2.0 close }
csql3 { SELECT * FROM t11 }
} {0 {1 2 3 4}}
do_test 2.$tn.3 {
code1 { sqlite3 db test.db }
csql1 { SELECT * FROM t11 }
} {1 {database is locked}}
do_test 2.$tn.4 {
code2 { db2.1 close }
csql1 { SELECT * FROM t11 }
} {0 {1 2 3 4}}
do_test 2.$tn.X {
code1 { for {set i 0} {$i < 50} {incr i} { catch {db.$i close} } }
code2 { for {set i 0} {$i < 50} {incr i} { catch {db2.$i close} } }
} {}
}
server_set_vfs single
server_reset_db
set TLIMIT 16
do_test 3.0 {
execsql "CREATE TABLE t1 (o PRIMARY KEY) WITHOUT ROWID"
for {set i 0} {$i < $TLIMIT} {incr i} {
execsql "CREATE TABLE x$i (o PRIMARY KEY) WITHOUT ROWID"
}
set "" ""
} {}
do_test 3.1 {
for {set i 0} {$i < $TLIMIT} {incr i} {
sqlite3 db.$i test.db
db.$i eval "
BEGIN;
INSERT INTO x$i VALUES ('one');
"
}
} {}
do_catchsql_test 3.2 {
INSERT INTO t1 VALUES('two');
} {1 {database is locked}}
do_test 3.3 {
db.0 eval COMMIT
execsql { INSERT INTO t1 VALUES('two'); }
} {}
do_catchsql_test 3.4 { SELECT * FROM x1 } {1 {database is locked}}
do_catchsql_test 3.5 { SELECT * FROM x0 } {0 one}
do_test 3.6 {
for {set i 1} {$i < $TLIMIT} {incr i} {
db.$i eval COMMIT
}
} {}
finish_test